From c64cd0cd05ef3d237097ff38d1da727a88bb7c7c Mon Sep 17 00:00:00 2001 From: Timothee TTimo Besset Date: Sat, 7 Apr 2012 18:53:01 -0500 Subject: [PATCH] Q2Tools source - didn't import this in initially --- tools/quake2/extra/COPYING.txt | 281 ++ tools/quake2/extra/Unpack/Unpack.dsp | 72 + tools/quake2/extra/Unpack/Unpack.dsw | 29 + tools/quake2/extra/Unpack/Unpack.java | 198 ++ tools/quake2/extra/bsp/bsp.mak | 1776 ++++++++++ tools/quake2/extra/bsp/bspinfo3/bspinfo3.c | 56 + tools/quake2/extra/bsp/bspinfo3/makefile | 53 + tools/quake2/extra/bsp/qbsp3/brushbsp.c | 1330 +++++++ tools/quake2/extra/bsp/qbsp3/csg.c | 635 ++++ tools/quake2/extra/bsp/qbsp3/faces.c | 1076 ++++++ tools/quake2/extra/bsp/qbsp3/gldraw.c | 232 ++ tools/quake2/extra/bsp/qbsp3/glfile.c | 149 + tools/quake2/extra/bsp/qbsp3/leakfile.c | 100 + tools/quake2/extra/bsp/qbsp3/makefile | 98 + tools/quake2/extra/bsp/qbsp3/map.c | 1017 ++++++ tools/quake2/extra/bsp/qbsp3/nodraw.c | 47 + tools/quake2/extra/bsp/qbsp3/portals.c | 1111 ++++++ tools/quake2/extra/bsp/qbsp3/prtfile.c | 287 ++ tools/quake2/extra/bsp/qbsp3/qbsp.h | 355 ++ tools/quake2/extra/bsp/qbsp3/qbsp3.c | 537 +++ tools/quake2/extra/bsp/qbsp3/textures.c | 221 ++ tools/quake2/extra/bsp/qbsp3/tree.c | 219 ++ tools/quake2/extra/bsp/qbsp3/writebsp.c | 590 ++++ tools/quake2/extra/bsp/qrad3/lightmap.c | 1316 +++++++ tools/quake2/extra/bsp/qrad3/makefile | 77 + tools/quake2/extra/bsp/qrad3/patches.c | 515 +++ tools/quake2/extra/bsp/qrad3/qrad.h | 158 + tools/quake2/extra/bsp/qrad3/qrad3.c | 717 ++++ tools/quake2/extra/bsp/qrad3/trace.c | 295 ++ tools/quake2/extra/bsp/qvis3/flow.c | 788 +++++ tools/quake2/extra/bsp/qvis3/makefile | 62 + tools/quake2/extra/bsp/qvis3/qvis3.c | 615 ++++ tools/quake2/extra/bsp/qvis3/vis.h | 149 + tools/quake2/extra/common/bspfile.c | 789 +++++ tools/quake2/extra/common/bspfile.h | 129 + tools/quake2/extra/common/cmdlib.c | 1055 ++++++ tools/quake2/extra/common/cmdlib.h | 145 + tools/quake2/extra/common/l3dslib.c | 301 ++ tools/quake2/extra/common/l3dslib.h | 27 + tools/quake2/extra/common/lbmlib.c | 824 +++++ tools/quake2/extra/common/lbmlib.h | 40 + tools/quake2/extra/common/mathlib.c | 174 + tools/quake2/extra/common/mathlib.h | 77 + tools/quake2/extra/common/mdfour.c | 224 ++ tools/quake2/extra/common/mdfour.h | 54 + tools/quake2/extra/common/polylib.c | 642 ++++ tools/quake2/extra/common/polylib.h | 55 + tools/quake2/extra/common/qfiles.h | 486 +++ tools/quake2/extra/common/scriplib.c | 297 ++ tools/quake2/extra/common/scriplib.h | 45 + tools/quake2/extra/common/threads.c | 448 +++ tools/quake2/extra/common/threads.h | 31 + tools/quake2/extra/common/trilib.c | 187 + tools/quake2/extra/common/trilib.h | 33 + tools/quake2/extra/qdata/anorms.h | 184 + tools/quake2/extra/qdata/images.c | 763 ++++ tools/quake2/extra/qdata/makefile | 81 + tools/quake2/extra/qdata/models.c | 1152 ++++++ tools/quake2/extra/qdata/qdata.c | 551 +++ tools/quake2/extra/qdata/qdata.dsp | 204 ++ tools/quake2/extra/qdata/qdata.dsw | 29 + tools/quake2/extra/qdata/qdata.h | 89 + tools/quake2/extra/qdata/qdata.mak | 549 +++ tools/quake2/extra/qdata/sprites.c | 228 ++ tools/quake2/extra/qdata/tables.c | 172 + tools/quake2/extra/qdata/video.c | 1259 +++++++ tools/quake2/extra/qe4/brush.c | 1568 +++++++++ tools/quake2/extra/qe4/brush.h | 87 + tools/quake2/extra/qe4/bspfile.h | 378 ++ tools/quake2/extra/qe4/camera.c | 594 ++++ tools/quake2/extra/qe4/camera.h | 63 + tools/quake2/extra/qe4/cmdlib.c | 686 ++++ tools/quake2/extra/qe4/cmdlib.h | 99 + tools/quake2/extra/qe4/csg.c | 168 + tools/quake2/extra/qe4/drag.c | 457 +++ tools/quake2/extra/qe4/eclass.c | 281 ++ tools/quake2/extra/qe4/entity.c | 538 +++ tools/quake2/extra/qe4/entity.h | 84 + tools/quake2/extra/qe4/entityw.h | 66 + tools/quake2/extra/qe4/glingr.h | 98 + tools/quake2/extra/qe4/icon1.ico | Bin 0 -> 766 bytes tools/quake2/extra/qe4/lbmlib.c | 835 +++++ tools/quake2/extra/qe4/lbmlib.h | 40 + tools/quake2/extra/qe4/makefile | 23 + tools/quake2/extra/qe4/map.c | 661 ++++ tools/quake2/extra/qe4/map.h | 53 + tools/quake2/extra/qe4/mathlib.c | 131 + tools/quake2/extra/qe4/mathlib.h | 66 + tools/quake2/extra/qe4/mru.c | 671 ++++ tools/quake2/extra/qe4/mru.h | 101 + tools/quake2/extra/qe4/parse.c | 141 + tools/quake2/extra/qe4/parse.h | 34 + tools/quake2/extra/qe4/points.c | 155 + tools/quake2/extra/qe4/q.bmp | Bin 0 -> 13878 bytes tools/quake2/extra/qe4/qe3.c | 451 +++ tools/quake2/extra/qe4/qe3.h | 306 ++ tools/quake2/extra/qe4/qe4.mak | 3716 ++++++++++++++++++++ tools/quake2/extra/qe4/qedefs.h | 117 + tools/quake2/extra/qe4/qfiles.h | 389 ++ tools/quake2/extra/qe4/resource.h | 308 ++ tools/quake2/extra/qe4/select.c | 706 ++++ tools/quake2/extra/qe4/select.h | 62 + tools/quake2/extra/qe4/textures.c | 1147 ++++++ tools/quake2/extra/qe4/textures.h | 70 + tools/quake2/extra/qe4/toolbar1.bmp | Bin 0 -> 1918 bytes tools/quake2/extra/qe4/vertsel.c | 245 ++ tools/quake2/extra/qe4/view.h | 52 + tools/quake2/extra/qe4/win_cam.c | 273 ++ tools/quake2/extra/qe4/win_dlg.c | 653 ++++ tools/quake2/extra/qe4/win_ent.c | 1137 ++++++ tools/quake2/extra/qe4/win_main.c | 1327 +++++++ tools/quake2/extra/qe4/win_qe3.aps | Bin 0 -> 78688 bytes tools/quake2/extra/qe4/win_qe3.c | 605 ++++ tools/quake2/extra/qe4/win_qe3.rc | 693 ++++ tools/quake2/extra/qe4/win_xy.c | 306 ++ tools/quake2/extra/qe4/win_z.c | 195 + tools/quake2/extra/qe4/xy.c | 973 +++++ tools/quake2/extra/qe4/xy.h | 48 + tools/quake2/extra/qe4/z.c | 426 +++ tools/quake2/extra/qe4/z.h | 42 + tools/quake2/extra/texpaint/docs.txt | 38 + tools/quake2/extra/texpaint/resource.h | 58 + tools/quake2/extra/texpaint/texmake.aps | Bin 0 -> 33472 bytes tools/quake2/extra/texpaint/texmake.rc | 156 + tools/quake2/extra/texpaint/texpaint.c | 311 ++ tools/quake2/extra/texpaint/texpaint.h | 88 + tools/quake2/extra/texpaint/texpaint.mak | 468 +++ tools/quake2/extra/texpaint/win_cam.c | 414 +++ tools/quake2/extra/texpaint/win_main.c | 496 +++ tools/quake2/extra/texpaint/win_pal.c | 257 ++ tools/quake2/extra/texpaint/win_skin.c | 946 +++++ 131 files changed, 52042 insertions(+) create mode 100644 tools/quake2/extra/COPYING.txt create mode 100644 tools/quake2/extra/Unpack/Unpack.dsp create mode 100644 tools/quake2/extra/Unpack/Unpack.dsw create mode 100644 tools/quake2/extra/Unpack/Unpack.java create mode 100644 tools/quake2/extra/bsp/bsp.mak create mode 100644 tools/quake2/extra/bsp/bspinfo3/bspinfo3.c create mode 100644 tools/quake2/extra/bsp/bspinfo3/makefile create mode 100644 tools/quake2/extra/bsp/qbsp3/brushbsp.c create mode 100644 tools/quake2/extra/bsp/qbsp3/csg.c create mode 100644 tools/quake2/extra/bsp/qbsp3/faces.c create mode 100644 tools/quake2/extra/bsp/qbsp3/gldraw.c create mode 100644 tools/quake2/extra/bsp/qbsp3/glfile.c create mode 100644 tools/quake2/extra/bsp/qbsp3/leakfile.c create mode 100644 tools/quake2/extra/bsp/qbsp3/makefile create mode 100644 tools/quake2/extra/bsp/qbsp3/map.c create mode 100644 tools/quake2/extra/bsp/qbsp3/nodraw.c create mode 100644 tools/quake2/extra/bsp/qbsp3/portals.c create mode 100644 tools/quake2/extra/bsp/qbsp3/prtfile.c create mode 100644 tools/quake2/extra/bsp/qbsp3/qbsp.h create mode 100644 tools/quake2/extra/bsp/qbsp3/qbsp3.c create mode 100644 tools/quake2/extra/bsp/qbsp3/textures.c create mode 100644 tools/quake2/extra/bsp/qbsp3/tree.c create mode 100644 tools/quake2/extra/bsp/qbsp3/writebsp.c create mode 100644 tools/quake2/extra/bsp/qrad3/lightmap.c create mode 100644 tools/quake2/extra/bsp/qrad3/makefile create mode 100644 tools/quake2/extra/bsp/qrad3/patches.c create mode 100644 tools/quake2/extra/bsp/qrad3/qrad.h create mode 100644 tools/quake2/extra/bsp/qrad3/qrad3.c create mode 100644 tools/quake2/extra/bsp/qrad3/trace.c create mode 100644 tools/quake2/extra/bsp/qvis3/flow.c create mode 100644 tools/quake2/extra/bsp/qvis3/makefile create mode 100644 tools/quake2/extra/bsp/qvis3/qvis3.c create mode 100644 tools/quake2/extra/bsp/qvis3/vis.h create mode 100644 tools/quake2/extra/common/bspfile.c create mode 100644 tools/quake2/extra/common/bspfile.h create mode 100644 tools/quake2/extra/common/cmdlib.c create mode 100644 tools/quake2/extra/common/cmdlib.h create mode 100644 tools/quake2/extra/common/l3dslib.c create mode 100644 tools/quake2/extra/common/l3dslib.h create mode 100644 tools/quake2/extra/common/lbmlib.c create mode 100644 tools/quake2/extra/common/lbmlib.h create mode 100644 tools/quake2/extra/common/mathlib.c create mode 100644 tools/quake2/extra/common/mathlib.h create mode 100644 tools/quake2/extra/common/mdfour.c create mode 100644 tools/quake2/extra/common/mdfour.h create mode 100644 tools/quake2/extra/common/polylib.c create mode 100644 tools/quake2/extra/common/polylib.h create mode 100644 tools/quake2/extra/common/qfiles.h create mode 100644 tools/quake2/extra/common/scriplib.c create mode 100644 tools/quake2/extra/common/scriplib.h create mode 100644 tools/quake2/extra/common/threads.c create mode 100644 tools/quake2/extra/common/threads.h create mode 100644 tools/quake2/extra/common/trilib.c create mode 100644 tools/quake2/extra/common/trilib.h create mode 100644 tools/quake2/extra/qdata/anorms.h create mode 100644 tools/quake2/extra/qdata/images.c create mode 100644 tools/quake2/extra/qdata/makefile create mode 100644 tools/quake2/extra/qdata/models.c create mode 100644 tools/quake2/extra/qdata/qdata.c create mode 100644 tools/quake2/extra/qdata/qdata.dsp create mode 100644 tools/quake2/extra/qdata/qdata.dsw create mode 100644 tools/quake2/extra/qdata/qdata.h create mode 100644 tools/quake2/extra/qdata/qdata.mak create mode 100644 tools/quake2/extra/qdata/sprites.c create mode 100644 tools/quake2/extra/qdata/tables.c create mode 100644 tools/quake2/extra/qdata/video.c create mode 100644 tools/quake2/extra/qe4/brush.c create mode 100644 tools/quake2/extra/qe4/brush.h create mode 100644 tools/quake2/extra/qe4/bspfile.h create mode 100644 tools/quake2/extra/qe4/camera.c create mode 100644 tools/quake2/extra/qe4/camera.h create mode 100644 tools/quake2/extra/qe4/cmdlib.c create mode 100644 tools/quake2/extra/qe4/cmdlib.h create mode 100644 tools/quake2/extra/qe4/csg.c create mode 100644 tools/quake2/extra/qe4/drag.c create mode 100644 tools/quake2/extra/qe4/eclass.c create mode 100644 tools/quake2/extra/qe4/entity.c create mode 100644 tools/quake2/extra/qe4/entity.h create mode 100644 tools/quake2/extra/qe4/entityw.h create mode 100644 tools/quake2/extra/qe4/glingr.h create mode 100644 tools/quake2/extra/qe4/icon1.ico create mode 100644 tools/quake2/extra/qe4/lbmlib.c create mode 100644 tools/quake2/extra/qe4/lbmlib.h create mode 100644 tools/quake2/extra/qe4/makefile create mode 100644 tools/quake2/extra/qe4/map.c create mode 100644 tools/quake2/extra/qe4/map.h create mode 100644 tools/quake2/extra/qe4/mathlib.c create mode 100644 tools/quake2/extra/qe4/mathlib.h create mode 100644 tools/quake2/extra/qe4/mru.c create mode 100644 tools/quake2/extra/qe4/mru.h create mode 100644 tools/quake2/extra/qe4/parse.c create mode 100644 tools/quake2/extra/qe4/parse.h create mode 100644 tools/quake2/extra/qe4/points.c create mode 100644 tools/quake2/extra/qe4/q.bmp create mode 100644 tools/quake2/extra/qe4/qe3.c create mode 100644 tools/quake2/extra/qe4/qe3.h create mode 100644 tools/quake2/extra/qe4/qe4.mak create mode 100644 tools/quake2/extra/qe4/qedefs.h create mode 100644 tools/quake2/extra/qe4/qfiles.h create mode 100644 tools/quake2/extra/qe4/resource.h create mode 100644 tools/quake2/extra/qe4/select.c create mode 100644 tools/quake2/extra/qe4/select.h create mode 100644 tools/quake2/extra/qe4/textures.c create mode 100644 tools/quake2/extra/qe4/textures.h create mode 100644 tools/quake2/extra/qe4/toolbar1.bmp create mode 100644 tools/quake2/extra/qe4/vertsel.c create mode 100644 tools/quake2/extra/qe4/view.h create mode 100644 tools/quake2/extra/qe4/win_cam.c create mode 100644 tools/quake2/extra/qe4/win_dlg.c create mode 100644 tools/quake2/extra/qe4/win_ent.c create mode 100644 tools/quake2/extra/qe4/win_main.c create mode 100644 tools/quake2/extra/qe4/win_qe3.aps create mode 100644 tools/quake2/extra/qe4/win_qe3.c create mode 100644 tools/quake2/extra/qe4/win_qe3.rc create mode 100644 tools/quake2/extra/qe4/win_xy.c create mode 100644 tools/quake2/extra/qe4/win_z.c create mode 100644 tools/quake2/extra/qe4/xy.c create mode 100644 tools/quake2/extra/qe4/xy.h create mode 100644 tools/quake2/extra/qe4/z.c create mode 100644 tools/quake2/extra/qe4/z.h create mode 100644 tools/quake2/extra/texpaint/docs.txt create mode 100644 tools/quake2/extra/texpaint/resource.h create mode 100644 tools/quake2/extra/texpaint/texmake.aps create mode 100644 tools/quake2/extra/texpaint/texmake.rc create mode 100644 tools/quake2/extra/texpaint/texpaint.c create mode 100644 tools/quake2/extra/texpaint/texpaint.h create mode 100644 tools/quake2/extra/texpaint/texpaint.mak create mode 100644 tools/quake2/extra/texpaint/win_cam.c create mode 100644 tools/quake2/extra/texpaint/win_main.c create mode 100644 tools/quake2/extra/texpaint/win_pal.c create mode 100644 tools/quake2/extra/texpaint/win_skin.c diff --git a/tools/quake2/extra/COPYING.txt b/tools/quake2/extra/COPYING.txt new file mode 100644 index 00000000..98443f35 --- /dev/null +++ b/tools/quake2/extra/COPYING.txt @@ -0,0 +1,281 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 + diff --git a/tools/quake2/extra/Unpack/Unpack.dsp b/tools/quake2/extra/Unpack/Unpack.dsp new file mode 100644 index 00000000..89bea7ca --- /dev/null +++ b/tools/quake2/extra/Unpack/Unpack.dsp @@ -0,0 +1,72 @@ +# Microsoft Developer Studio Project File - Name="Unpack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Java Virtual Machine Java Project" 0x0809 + +CFG=Unpack - Java Virtual Machine 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 "Unpack.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 "Unpack.mak" CFG="Unpack - Java Virtual Machine Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Unpack - Java Virtual Machine Release" (based on\ + "Java Virtual Machine Java Project") +!MESSAGE "Unpack - Java Virtual Machine Debug" (based on\ + "Java Virtual Machine Java Project") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +JAVA=jvc.exe + +!IF "$(CFG)" == "Unpack - Java Virtual Machine Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" +# ADD BASE JAVA /O +# ADD JAVA /O + +!ELSEIF "$(CFG)" == "Unpack - Java Virtual Machine Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" +# ADD BASE JAVA /g +# ADD JAVA /g + +!ENDIF + +# Begin Target + +# Name "Unpack - Java Virtual Machine Release" +# Name "Unpack - Java Virtual Machine Debug" +# Begin Source File + +SOURCE=.\Unpack.java +# End Source File +# End Target +# End Project diff --git a/tools/quake2/extra/Unpack/Unpack.dsw b/tools/quake2/extra/Unpack/Unpack.dsw new file mode 100644 index 00000000..29aef98e --- /dev/null +++ b/tools/quake2/extra/Unpack/Unpack.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Unpack"=.\Unpack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/tools/quake2/extra/Unpack/Unpack.java b/tools/quake2/extra/Unpack/Unpack.java new file mode 100644 index 00000000..a18e72fa --- /dev/null +++ b/tools/quake2/extra/Unpack/Unpack.java @@ -0,0 +1,198 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +/* + * Unpack -- a completely non-object oriented utility... + * + */ + +import java.io.*; + +class Unpack { + static final int IDPAKHEADER = (('K'<<24)+('C'<<16)+('A'<<8)+'P'); + + static int intSwap(int i) { + int a, b, c, d; + + a = i & 255; + b = (i >> 8) & 255; + c = (i >> 16) & 255; + d = (i >> 24) & 255; + + return (a << 24) + (b << 16) + (c << 8) + d; + } + + static boolean patternMatch (String pattern, String s) { + int index; + int remaining; + + if (pattern.equals(s)) { + return true; + } + + // fairly lame single wildcard matching + index = pattern.indexOf('*'); + if (index == -1) { + return false; + } + if (!pattern.regionMatches(0, s, 0, index)) { + return false; + } + + index += 1; // skip the * + remaining = pattern.length() - index; + if (s.length() < remaining) { + return false; + } + + if (!pattern.regionMatches(index, s, s.length()-remaining, remaining)) { + return false; + } + + return true; + } + + static void usage() { + System.out.println ("Usage: unpack "); + System.out.println (" or: unpack -list "); + System.out.println (" may contain a single * wildcard"); + System.exit (1); + } + + public static void main (String[] args) { + int ident; + int dirofs; + int dirlen; + int i; + int numLumps; + byte[] name = new byte[56]; + String nameString; + int filepos; + int filelen; + RandomAccessFile readLump; + DataInputStream directory; + String pakName; + String pattern; + + if (args.length == 2) { + if (!args[0].equals("-list")) { + usage(); + } + pakName = args[1]; + pattern = null; + } else if (args.length == 3) { + pakName = args[0]; + pattern = args[1]; + } else { + pakName = null; + pattern = null; + usage (); + } + + try { + // one stream to read the directory + directory = new DataInputStream(new FileInputStream(pakName)); + + // another to read lumps + readLump = new RandomAccessFile(pakName, "r"); + + // read the header + ident = intSwap(directory.readInt()); + dirofs = intSwap(directory.readInt()); + dirlen = intSwap(directory.readInt()); + + if (ident != IDPAKHEADER) { + System.out.println ( pakName + " is not a pakfile."); + System.exit (1); + } + + // read the directory + directory.skipBytes (dirofs - 12); + numLumps = dirlen / 64; + + System.out.println (numLumps + " lumps in " + pakName); + + for (i = 0 ; i < numLumps ; i++) { + directory.readFully(name); + filepos = intSwap(directory.readInt()); + filelen = intSwap(directory.readInt()); + + nameString = new String (name, 0); + // chop to the first 0 byte + nameString = nameString.substring (0, nameString.indexOf(0)); + + if (pattern == null) { + // listing mode + System.out.println (nameString + " : " + filelen + "bytes"); + } else if (patternMatch (pattern, nameString) ) { + File writeFile; + DataOutputStream writeLump; + byte[] buffer = new byte[filelen]; + StringBuffer fixedString; + String finalName; + int index; + + System.out.println ("Unpaking " + nameString + " " + filelen + + " bytes"); + + // load the lump + readLump.seek(filepos); + readLump.readFully(buffer); + + // quake uses forward slashes, but java requires + // they only by the host's seperator, which + // varies from win to unix + fixedString = new StringBuffer (args[2] + File.separator + nameString); + for (index = 0 ; index < fixedString.length() ; index++) { + if (fixedString.charAt(index) == '/') { + fixedString.setCharAt(index, File.separatorChar); + } + } + finalName = fixedString.toString (); + + index = finalName.lastIndexOf(File.separatorChar); + if (index != -1) { + String finalPath; + File writePath; + + finalPath = finalName.substring(0, index); + writePath = new File (finalPath); + writePath.mkdirs(); + } + + writeFile = new File (finalName); + writeLump = new DataOutputStream ( new FileOutputStream(writeFile) ); + writeLump.write(buffer); + writeLump.close(); + + } + } + + readLump.close(); + directory.close(); + + } catch (IOException e) { + System.out.println ( e.toString() ); + } + } + +} diff --git a/tools/quake2/extra/bsp/bsp.mak b/tools/quake2/extra/bsp/bsp.mak new file mode 100644 index 00000000..17218de7 --- /dev/null +++ b/tools/quake2/extra/bsp/bsp.mak @@ -0,0 +1,1776 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=bspinfo3 - Win32 Debug +!MESSAGE No configuration specified. Defaulting to bspinfo3 - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "bsp - Win32 Release" && "$(CFG)" != "bsp - Win32 Debug" &&\ + "$(CFG)" != "qbsp3 - Win32 Release" && "$(CFG)" != "qbsp3 - Win32 Debug" &&\ + "$(CFG)" != "qvis3 - Win32 Release" && "$(CFG)" != "qvis3 - Win32 Debug" &&\ + "$(CFG)" != "qrad3 - Win32 Release" && "$(CFG)" != "qrad3 - Win32 Debug" &&\ + "$(CFG)" != "bspinfo3 - Win32 Release" && "$(CFG)" != "bspinfo3 - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "bsp.mak" CFG="bspinfo3 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "bsp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "bsp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "qbsp3 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "qbsp3 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "qvis3 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "qvis3 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "qrad3 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "qrad3 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "bspinfo3 - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "bspinfo3 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "bspinfo3 - Win32 Debug" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bsp - 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 "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : + +CLEAN : + -@erase + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/bsp.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/bsp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:no /pdb:"$(OUTDIR)/bsp.pdb" /machine:I386\ + /out:"$(OUTDIR)/bsp.exe" +LINK32_OBJS= \ + + +!ELSEIF "$(CFG)" == "bsp - 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 "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : + +CLEAN : + -@erase + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/bsp.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/bsp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:yes /pdb:"$(OUTDIR)/bsp.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/bsp.exe" +LINK32_OBJS= \ + + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "qbsp3\Release" +# PROP BASE Intermediate_Dir "qbsp3\Release" +# PROP BASE Target_Dir "qbsp3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "qbsp3\Release" +# PROP Intermediate_Dir "qbsp3\Release" +# PROP Target_Dir "qbsp3" +OUTDIR=.\qbsp3\Release +INTDIR=.\qbsp3\Release + +ALL : "$(OUTDIR)\qbsp3.exe" + +CLEAN : + -@erase "$(INTDIR)\brushbsp.obj" + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\csg.obj" + -@erase "$(INTDIR)\faces.obj" + -@erase "$(INTDIR)\gldraw.obj" + -@erase "$(INTDIR)\glfile.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\leakfile.obj" + -@erase "$(INTDIR)\map.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\polylib.obj" + -@erase "$(INTDIR)\portals.obj" + -@erase "$(INTDIR)\prtfile.obj" + -@erase "$(INTDIR)\qbsp3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\textures.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\tree.obj" + -@erase "$(INTDIR)\writebsp.obj" + -@erase "$(OUTDIR)\qbsp3.exe" + -@erase "$(OUTDIR)\qbsp3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/qbsp3.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\qbsp3\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qbsp3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:no /pdb:"$(OUTDIR)/qbsp3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qbsp3.exe" +LINK32_OBJS= \ + "$(INTDIR)\brushbsp.obj" \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\faces.obj" \ + "$(INTDIR)\gldraw.obj" \ + "$(INTDIR)\glfile.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\leakfile.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\polylib.obj" \ + "$(INTDIR)\portals.obj" \ + "$(INTDIR)\prtfile.obj" \ + "$(INTDIR)\qbsp3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\tree.obj" \ + "$(INTDIR)\writebsp.obj" + +"$(OUTDIR)\qbsp3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "qbsp3\Debug" +# PROP BASE Intermediate_Dir "qbsp3\Debug" +# PROP BASE Target_Dir "qbsp3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "qbsp3\Debug" +# PROP Intermediate_Dir "qbsp3\Debug" +# PROP Target_Dir "qbsp3" +OUTDIR=.\qbsp3\Debug +INTDIR=.\qbsp3\Debug + +ALL : "$(OUTDIR)\qbsp3.exe" + +CLEAN : + -@erase "$(INTDIR)\brushbsp.obj" + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\csg.obj" + -@erase "$(INTDIR)\faces.obj" + -@erase "$(INTDIR)\gldraw.obj" + -@erase "$(INTDIR)\glfile.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\leakfile.obj" + -@erase "$(INTDIR)\map.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\polylib.obj" + -@erase "$(INTDIR)\portals.obj" + -@erase "$(INTDIR)\prtfile.obj" + -@erase "$(INTDIR)\qbsp3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\textures.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\tree.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\writebsp.obj" + -@erase "$(OUTDIR)\qbsp3.exe" + -@erase "$(OUTDIR)\qbsp3.ilk" + -@erase "$(OUTDIR)\qbsp3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/qbsp3.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\qbsp3\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qbsp3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:yes /pdb:"$(OUTDIR)/qbsp3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qbsp3.exe" +LINK32_OBJS= \ + "$(INTDIR)\brushbsp.obj" \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\faces.obj" \ + "$(INTDIR)\gldraw.obj" \ + "$(INTDIR)\glfile.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\leakfile.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\polylib.obj" \ + "$(INTDIR)\portals.obj" \ + "$(INTDIR)\prtfile.obj" \ + "$(INTDIR)\qbsp3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\tree.obj" \ + "$(INTDIR)\writebsp.obj" + +"$(OUTDIR)\qbsp3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qvis3 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "qvis3\Release" +# PROP BASE Intermediate_Dir "qvis3\Release" +# PROP BASE Target_Dir "qvis3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "qvis3\Release" +# PROP Intermediate_Dir "qvis3\Release" +# PROP Target_Dir "qvis3" +OUTDIR=.\qvis3\Release +INTDIR=.\qvis3\Release + +ALL : "$(OUTDIR)\qvis3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\flow.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\qvis3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(OUTDIR)\qvis3.exe" + -@erase "$(OUTDIR)\qvis3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/qvis3.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\qvis3\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qvis3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:no /pdb:"$(OUTDIR)/qvis3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qvis3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\flow.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\qvis3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\threads.obj" + +"$(OUTDIR)\qvis3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qvis3 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "qvis3\Debug" +# PROP BASE Intermediate_Dir "qvis3\Debug" +# PROP BASE Target_Dir "qvis3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "qvis3\Debug" +# PROP Intermediate_Dir "qvis3\Debug" +# PROP Target_Dir "qvis3" +OUTDIR=.\qvis3\Debug +INTDIR=.\qvis3\Debug + +ALL : "$(OUTDIR)\qvis3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\flow.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\qvis3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\qvis3.exe" + -@erase "$(OUTDIR)\qvis3.ilk" + -@erase "$(OUTDIR)\qvis3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/qvis3.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\qvis3\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qvis3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:yes /pdb:"$(OUTDIR)/qvis3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qvis3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\flow.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\qvis3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\threads.obj" + +"$(OUTDIR)\qvis3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qrad3 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "qrad3\Release" +# PROP BASE Intermediate_Dir "qrad3\Release" +# PROP BASE Target_Dir "qrad3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "qrad3\Release" +# PROP Intermediate_Dir "qrad3\Release" +# PROP Target_Dir "qrad3" +OUTDIR=.\qrad3\Release +INTDIR=.\qrad3\Release + +ALL : "$(OUTDIR)\qrad3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\lightmap.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\patches.obj" + -@erase "$(INTDIR)\polylib.obj" + -@erase "$(INTDIR)\qrad3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\trace.obj" + -@erase "$(OUTDIR)\qrad3.exe" + -@erase "$(OUTDIR)\qrad3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/qrad3.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\qrad3\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qrad3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:no /pdb:"$(OUTDIR)/qrad3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qrad3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\lightmap.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\patches.obj" \ + "$(INTDIR)\polylib.obj" \ + "$(INTDIR)\qrad3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\trace.obj" + +"$(OUTDIR)\qrad3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qrad3 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "qrad3\Debug" +# PROP BASE Intermediate_Dir "qrad3\Debug" +# PROP BASE Target_Dir "qrad3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "qrad3\Debug" +# PROP Intermediate_Dir "qrad3\Debug" +# PROP Target_Dir "qrad3" +OUTDIR=.\qrad3\Debug +INTDIR=.\qrad3\Debug + +ALL : "$(OUTDIR)\qrad3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\lightmap.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\patches.obj" + -@erase "$(INTDIR)\polylib.obj" + -@erase "$(INTDIR)\qrad3.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\trace.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\qrad3.exe" + -@erase "$(OUTDIR)\qrad3.ilk" + -@erase "$(OUTDIR)\qrad3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/qrad3.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\qrad3\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qrad3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:yes /pdb:"$(OUTDIR)/qrad3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/qrad3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\lightmap.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\patches.obj" \ + "$(INTDIR)\polylib.obj" \ + "$(INTDIR)\qrad3.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\trace.obj" + +"$(OUTDIR)\qrad3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "bspinfo3 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "bspinfo3\Release" +# PROP BASE Intermediate_Dir "bspinfo3\Release" +# PROP BASE Target_Dir "bspinfo3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "bspinfo3\Release" +# PROP Intermediate_Dir "bspinfo3\Release" +# PROP Target_Dir "bspinfo3" +OUTDIR=.\bspinfo3\Release +INTDIR=.\bspinfo3\Release + +ALL : "$(OUTDIR)\bspinfo3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\bspinfo3.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(OUTDIR)\bspinfo3.exe" + -@erase "$(OUTDIR)\bspinfo3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /GX /Zd /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/bspinfo3.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\bspinfo3\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/bspinfo3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:no /pdb:"$(OUTDIR)/bspinfo3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/bspinfo3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\bspinfo3.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\scriplib.obj" + +"$(OUTDIR)\bspinfo3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "bspinfo3 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "bspinfo3\Debug" +# PROP BASE Intermediate_Dir "bspinfo3\Debug" +# PROP BASE Target_Dir "bspinfo3" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "bspinfo3\Debug" +# PROP Intermediate_Dir "bspinfo3\Debug" +# PROP Target_Dir "bspinfo3" +OUTDIR=.\bspinfo3\Debug +INTDIR=.\bspinfo3\Debug + +ALL : "$(OUTDIR)\bspinfo3.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\bspinfo3.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\bspinfo3.exe" + -@erase "$(OUTDIR)\bspinfo3.ilk" + -@erase "$(OUTDIR)\bspinfo3.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MT /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/bspinfo3.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/"\ + /c +CPP_OBJS=.\bspinfo3\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/bspinfo3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib opengl32.lib glaux.lib glu32.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 +LINK32_FLAGS=wsock32.lib opengl32.lib glaux.lib glu32.lib kernel32.lib\ + user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib\ + ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo\ + /subsystem:console /incremental:yes /pdb:"$(OUTDIR)/bspinfo3.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)/bspinfo3.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\bspinfo3.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\scriplib.obj" + +"$(OUTDIR)\bspinfo3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "bsp - Win32 Release" +# Name "bsp - Win32 Debug" + +!IF "$(CFG)" == "bsp - Win32 Release" + +!ELSEIF "$(CFG)" == "bsp - Win32 Debug" + +!ENDIF + +# End Target +################################################################################ +# Begin Target + +# Name "qbsp3 - Win32 Release" +# Name "qbsp3 - Win32 Debug" + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\writebsp.c + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +DEP_CPP_WRITE=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\writebsp.obj" : $(SOURCE) $(DEP_CPP_WRITE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +DEP_CPP_WRITE=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\writebsp.obj" : $(SOURCE) $(DEP_CPP_WRITE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\brushbsp.c +DEP_CPP_BRUSH=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\brushbsp.obj" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\csg.c +DEP_CPP_CSG_C=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\csg.obj" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\faces.c +DEP_CPP_FACES=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\faces.obj" : $(SOURCE) $(DEP_CPP_FACES) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\gldraw.c + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +DEP_CPP_GLDRA=\ + ".\qbsp3\qbsp.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\gldraw.obj" : $(SOURCE) $(DEP_CPP_GLDRA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +DEP_CPP_GLDRA=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\gldraw.obj" : $(SOURCE) $(DEP_CPP_GLDRA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\glfile.c + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +DEP_CPP_GLFIL=\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\glfile.obj" : $(SOURCE) $(DEP_CPP_GLFIL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +DEP_CPP_GLFIL=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\glfile.obj" : $(SOURCE) $(DEP_CPP_GLFIL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\leakfile.c + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +DEP_CPP_LEAKF=\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\leakfile.obj" : $(SOURCE) $(DEP_CPP_LEAKF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +DEP_CPP_LEAKF=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\leakfile.obj" : $(SOURCE) $(DEP_CPP_LEAKF) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\map.c +DEP_CPP_MAP_C=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\map.obj" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\portals.c +DEP_CPP_PORTA=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\portals.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\prtfile.c +DEP_CPP_PRTFI=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\prtfile.obj" : $(SOURCE) $(DEP_CPP_PRTFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\qbsp.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\qbsp3.c +DEP_CPP_QBSP3=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\qbsp3.obj" : $(SOURCE) $(DEP_CPP_QBSP3) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\textures.c +DEP_CPP_TEXTU=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\textures.obj" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qbsp3\tree.c +DEP_CPP_TREE_=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + "..\common\threads.h"\ + ".\qbsp3\qbsp.h"\ + + +"$(INTDIR)\tree.obj" : $(SOURCE) $(DEP_CPP_TREE_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\threads.c +DEP_CPP_THREA=\ + "..\common\cmdlib.h"\ + "..\common\threads.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\threads.obj" : $(SOURCE) $(DEP_CPP_THREA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.c +DEP_CPP_CMDLI=\ + "..\common\cmdlib.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\lbmlib.c +DEP_CPP_LBMLI=\ + "..\common\cmdlib.h"\ + "..\common\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.c +DEP_CPP_MATHL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\polylib.c +DEP_CPP_POLYL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + + +"$(INTDIR)\polylib.obj" : $(SOURCE) $(DEP_CPP_POLYL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.c +DEP_CPP_SCRIP=\ + "..\common\cmdlib.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.c +DEP_CPP_BSPFI=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\threads.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\lbmlib.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\polylib.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\qfiles.h + +!IF "$(CFG)" == "qbsp3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qbsp3 - Win32 Debug" + +!ENDIF + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "qvis3 - Win32 Release" +# Name "qvis3 - Win32 Debug" + +!IF "$(CFG)" == "qvis3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qvis3 - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\qvis3\vis.h + +!IF "$(CFG)" == "qvis3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qvis3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qvis3\qvis3.c +DEP_CPP_QVIS3=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + "..\common\threads.h"\ + ".\qvis3\vis.h"\ + + +"$(INTDIR)\qvis3.obj" : $(SOURCE) $(DEP_CPP_QVIS3) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qvis3\flow.c +DEP_CPP_FLOW_=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + ".\qvis3\vis.h"\ + + +"$(INTDIR)\flow.obj" : $(SOURCE) $(DEP_CPP_FLOW_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.c +DEP_CPP_CMDLI=\ + "..\common\cmdlib.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.c +DEP_CPP_MATHL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.c +DEP_CPP_SCRIP=\ + "..\common\cmdlib.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\threads.c +DEP_CPP_THREA=\ + "..\common\cmdlib.h"\ + "..\common\threads.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\threads.obj" : $(SOURCE) $(DEP_CPP_THREA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.c +DEP_CPP_BSPFI=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "qrad3 - Win32 Release" +# Name "qrad3 - Win32 Debug" + +!IF "$(CFG)" == "qrad3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qrad3 - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\qrad3\patches.c +DEP_CPP_PATCH=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\threads.h"\ + ".\qrad3\qrad.h"\ + + +"$(INTDIR)\patches.obj" : $(SOURCE) $(DEP_CPP_PATCH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qrad3\lightmap.c +DEP_CPP_LIGHT=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\threads.h"\ + ".\qrad3\qrad.h"\ + + +"$(INTDIR)\lightmap.obj" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qrad3\qrad.h + +!IF "$(CFG)" == "qrad3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qrad3 - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qrad3\qrad3.c +DEP_CPP_QRAD3=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + "..\common\qfiles.h"\ + "..\common\threads.h"\ + ".\qrad3\qrad.h"\ + + +"$(INTDIR)\qrad3.obj" : $(SOURCE) $(DEP_CPP_QRAD3) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qrad3\trace.c +DEP_CPP_TRACE=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + + +"$(INTDIR)\trace.obj" : $(SOURCE) $(DEP_CPP_TRACE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\threads.c +DEP_CPP_THREA=\ + "..\common\cmdlib.h"\ + "..\common\threads.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\threads.obj" : $(SOURCE) $(DEP_CPP_THREA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.c +DEP_CPP_CMDLI=\ + "..\common\cmdlib.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.c +DEP_CPP_MATHL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\polylib.c +DEP_CPP_POLYL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\polylib.h"\ + + +"$(INTDIR)\polylib.obj" : $(SOURCE) $(DEP_CPP_POLYL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.c +DEP_CPP_SCRIP=\ + "..\common\cmdlib.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.c +DEP_CPP_BSPFI=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\lbmlib.c +DEP_CPP_LBMLI=\ + "..\common\cmdlib.h"\ + "..\common\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "bspinfo3 - Win32 Release" +# Name "bspinfo3 - Win32 Debug" + +!IF "$(CFG)" == "bspinfo3 - Win32 Release" + +!ELSEIF "$(CFG)" == "bspinfo3 - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\bspinfo3\bspinfo3.c +DEP_CPP_BSPIN=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + + +"$(INTDIR)\bspinfo3.obj" : $(SOURCE) $(DEP_CPP_BSPIN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.c +DEP_CPP_MATHL=\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.c +DEP_CPP_CMDLI=\ + "..\common\cmdlib.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.c +DEP_CPP_BSPFI=\ + "..\common\bspfile.h"\ + "..\common\cmdlib.h"\ + "..\common\mathlib.h"\ + "..\common\qfiles.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.c +DEP_CPP_SCRIP=\ + "..\common\cmdlib.h"\ + "..\common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/tools/quake2/extra/bsp/bspinfo3/bspinfo3.c b/tools/quake2/extra/bsp/bspinfo3/bspinfo3.c new file mode 100644 index 00000000..75a414f3 --- /dev/null +++ b/tools/quake2/extra/bsp/bspinfo3/bspinfo3.c @@ -0,0 +1,56 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "bspfile.h" + +void main (int argc, char **argv) +{ + int i; + char source[1024]; + int size; + FILE *f; + + if (argc == 1) + Error ("usage: bspinfo bspfile [bspfiles]"); + + for (i=1 ; i /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmdlib.o : ../../common/cmdlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/scriplib.o : ../../common/scriplib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/bspfile.o : ../../common/bspfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i diff --git a/tools/quake2/extra/bsp/qbsp3/brushbsp.c b/tools/quake2/extra/bsp/qbsp3/brushbsp.c new file mode 100644 index 00000000..a111bd3b --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/brushbsp.c @@ -0,0 +1,1330 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + + +int c_nodes; +int c_nonvis; +int c_active_brushes; + +// if a brush just barely pokes onto the other side, +// let it slide by without chopping +#define PLANESIDE_EPSILON 0.001 +//0.1 + +#define PSIDE_FRONT 1 +#define PSIDE_BACK 2 +#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK) +#define PSIDE_FACING 4 + + +void FindBrushInTree (node_t *node, int brushnum) +{ + bspbrush_t *b; + + if (node->planenum == PLANENUM_LEAF) + { + for (b=node->brushlist ; b ; b=b->next) + if (b->original->brushnum == brushnum) + printf ("here\n"); + return; + } + FindBrushInTree (node->children[0], brushnum); + FindBrushInTree (node->children[1], brushnum); +} + +//================================================== + +/* +================ +DrawBrushList +================ +*/ +void DrawBrushList (bspbrush_t *brush, node_t *node) +{ + int i; + side_t *s; + + GLS_BeginScene (); + for ( ; brush ; brush=brush->next) + { + for (i=0 ; inumsides ; i++) + { + s = &brush->sides[i]; + if (!s->winding) + continue; + if (s->texinfo == TEXINFO_NODE) + GLS_Winding (s->winding, 1); + else if (!s->visible) + GLS_Winding (s->winding, 2); + else + GLS_Winding (s->winding, 0); + } + } + GLS_EndScene (); +} + +/* +================ +WriteBrushList +================ +*/ +void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis) +{ + int i; + side_t *s; + FILE *f; + + qprintf ("writing %s\n", name); + f = SafeOpenWrite (name); + + for ( ; brush ; brush=brush->next) + { + for (i=0 ; inumsides ; i++) + { + s = &brush->sides[i]; + if (!s->winding) + continue; + if (onlyvis && !s->visible) + continue; + OutputWinding (brush->sides[i].winding, f); + } + } + + fclose (f); +} + +void PrintBrush (bspbrush_t *brush) +{ + int i; + + printf ("brush: %p\n", brush); + for (i=0;inumsides ; i++) + { + pw(brush->sides[i].winding); + printf ("\n"); + } +} + +/* +================== +BoundBrush + +Sets the mins/maxs based on the windings +================== +*/ +void BoundBrush (bspbrush_t *brush) +{ + int i, j; + winding_t *w; + + ClearBounds (brush->mins, brush->maxs); + for (i=0 ; inumsides ; i++) + { + w = brush->sides[i].winding; + if (!w) + continue; + for (j=0 ; jnumpoints ; j++) + AddPointToBounds (w->p[j], brush->mins, brush->maxs); + } +} + +/* +================== +CreateBrushWindings + +================== +*/ +void CreateBrushWindings (bspbrush_t *brush) +{ + int i, j; + winding_t *w; + side_t *side; + plane_t *plane; + + for (i=0 ; inumsides ; i++) + { + side = &brush->sides[i]; + plane = &mapplanes[side->planenum]; + w = BaseWindingForPlane (plane->normal, plane->dist); + for (j=0 ; jnumsides && w; j++) + { + if (i == j) + continue; + if (brush->sides[j].bevel) + continue; + plane = &mapplanes[brush->sides[j].planenum^1]; + ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON); + } + + side->winding = w; + } + + BoundBrush (brush); +} + +/* +================== +BrushFromBounds + +Creates a new axial brush +================== +*/ +bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs) +{ + bspbrush_t *b; + int i; + vec3_t normal; + vec_t dist; + + b = AllocBrush (6); + b->numsides = 6; + for (i=0 ; i<3 ; i++) + { + VectorClear (normal); + normal[i] = 1; + dist = maxs[i]; + b->sides[i].planenum = FindFloatPlane (normal, dist); + + normal[i] = -1; + dist = -mins[i]; + b->sides[3+i].planenum = FindFloatPlane (normal, dist); + } + + CreateBrushWindings (b); + + return b; +} + +/* +================== +BrushVolume + +================== +*/ +vec_t BrushVolume (bspbrush_t *brush) +{ + int i; + winding_t *w; + vec3_t corner; + vec_t d, area, volume; + plane_t *plane; + + if (!brush) + return 0; + + // grab the first valid point as the corner + + w = NULL; + for (i=0 ; inumsides ; i++) + { + w = brush->sides[i].winding; + if (w) + break; + } + if (!w) + return 0; + VectorCopy (w->p[0], corner); + + // make tetrahedrons to all other faces + + volume = 0; + for ( ; inumsides ; i++) + { + w = brush->sides[i].winding; + if (!w) + continue; + plane = &mapplanes[brush->sides[i].planenum]; + d = -(DotProduct (corner, plane->normal) - plane->dist); + area = WindingArea (w); + volume += d*area; + } + + volume /= 3; + return volume; +} + +/* +================ +CountBrushList +================ +*/ +int CountBrushList (bspbrush_t *brushes) +{ + int c; + + c = 0; + for ( ; brushes ; brushes = brushes->next) + c++; + return c; +} + +/* +================ +AllocTree +================ +*/ +tree_t *AllocTree (void) +{ + tree_t *tree; + + tree = malloc(sizeof(*tree)); + memset (tree, 0, sizeof(*tree)); + ClearBounds (tree->mins, tree->maxs); + + return tree; +} + +/* +================ +AllocNode +================ +*/ +node_t *AllocNode (void) +{ + node_t *node; + + node = malloc(sizeof(*node)); + memset (node, 0, sizeof(*node)); + + return node; +} + + +/* +================ +AllocBrush +================ +*/ +bspbrush_t *AllocBrush (int numsides) +{ + bspbrush_t *bb; + int c; + + c = (int)&(((bspbrush_t *)0)->sides[numsides]); + bb = malloc(c); + memset (bb, 0, c); + if (numthreads == 1) + c_active_brushes++; + return bb; +} + +/* +================ +FreeBrush +================ +*/ +void FreeBrush (bspbrush_t *brushes) +{ + int i; + + for (i=0 ; inumsides ; i++) + if (brushes->sides[i].winding) + FreeWinding(brushes->sides[i].winding); + free (brushes); + if (numthreads == 1) + c_active_brushes--; +} + + +/* +================ +FreeBrushList +================ +*/ +void FreeBrushList (bspbrush_t *brushes) +{ + bspbrush_t *next; + + for ( ; brushes ; brushes = next) + { + next = brushes->next; + + FreeBrush (brushes); + } +} + +/* +================== +CopyBrush + +Duplicates the brush, the sides, and the windings +================== +*/ +bspbrush_t *CopyBrush (bspbrush_t *brush) +{ + bspbrush_t *newbrush; + int size; + int i; + + size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]); + + newbrush = AllocBrush (brush->numsides); + memcpy (newbrush, brush, size); + + for (i=0 ; inumsides ; i++) + { + if (brush->sides[i].winding) + newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding); + } + + return newbrush; +} + + +/* +================== +PointInLeaf + +================== +*/ +node_t *PointInLeaf (node_t *node, vec3_t point) +{ + vec_t d; + plane_t *plane; + + while (node->planenum != PLANENUM_LEAF) + { + plane = &mapplanes[node->planenum]; + d = DotProduct (point, plane->normal) - plane->dist; + if (d > 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return node; +} + +//======================================================== + +/* +============== +BoxOnPlaneSide + +Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH +============== +*/ +int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane) +{ + int side; + int i; + vec3_t corners[2]; + vec_t dist1, dist2; + + // axial planes are easy + if (plane->type < 3) + { + side = 0; + if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON) + side |= PSIDE_FRONT; + if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON) + side |= PSIDE_BACK; + return side; + } + + // create the proper leading and trailing verts for the box + + for (i=0 ; i<3 ; i++) + { + if (plane->normal[i] < 0) + { + corners[0][i] = mins[i]; + corners[1][i] = maxs[i]; + } + else + { + corners[1][i] = mins[i]; + corners[0][i] = maxs[i]; + } + } + + dist1 = DotProduct (plane->normal, corners[0]) - plane->dist; + dist2 = DotProduct (plane->normal, corners[1]) - plane->dist; + side = 0; + if (dist1 >= PLANESIDE_EPSILON) + side = PSIDE_FRONT; + if (dist2 < PLANESIDE_EPSILON) + side |= PSIDE_BACK; + + return side; +} + +/* +============ +QuickTestBrushToPlanenum + +============ +*/ +int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits) +{ + int i, num; + plane_t *plane; + int s; + + *numsplits = 0; + + // if the brush actually uses the planenum, + // we can tell the side for sure + for (i=0 ; inumsides ; i++) + { + num = brush->sides[i].planenum; + if (num >= 0x10000) + Error ("bad planenum"); + if (num == planenum) + return PSIDE_BACK|PSIDE_FACING; + if (num == (planenum ^ 1) ) + return PSIDE_FRONT|PSIDE_FACING; + } + + // box on plane side + plane = &mapplanes[planenum]; + s = BoxOnPlaneSide (brush->mins, brush->maxs, plane); + + // if both sides, count the visible faces split + if (s == PSIDE_BOTH) + { + *numsplits += 3; + } + + return s; +} + +/* +============ +TestBrushToPlanenum + +============ +*/ +int TestBrushToPlanenum (bspbrush_t *brush, int planenum, + int *numsplits, qboolean *hintsplit, int *epsilonbrush) +{ + int i, j, num; + plane_t *plane; + int s; + winding_t *w; + vec_t d, d_front, d_back; + int front, back; + + *numsplits = 0; + *hintsplit = false; + + // if the brush actually uses the planenum, + // we can tell the side for sure + for (i=0 ; inumsides ; i++) + { + num = brush->sides[i].planenum; + if (num >= 0x10000) + Error ("bad planenum"); + if (num == planenum) + return PSIDE_BACK|PSIDE_FACING; + if (num == (planenum ^ 1) ) + return PSIDE_FRONT|PSIDE_FACING; + } + + // box on plane side + plane = &mapplanes[planenum]; + s = BoxOnPlaneSide (brush->mins, brush->maxs, plane); + + if (s != PSIDE_BOTH) + return s; + +// if both sides, count the visible faces split + d_front = d_back = 0; + + for (i=0 ; inumsides ; i++) + { + if (brush->sides[i].texinfo == TEXINFO_NODE) + continue; // on node, don't worry about splits + if (!brush->sides[i].visible) + continue; // we don't care about non-visible + w = brush->sides[i].winding; + if (!w) + continue; + front = back = 0; + for (j=0 ; jnumpoints; j++) + { + d = DotProduct (w->p[j], plane->normal) - plane->dist; + if (d > d_front) + d_front = d; + if (d < d_back) + d_back = d; + + if (d > 0.1) // PLANESIDE_EPSILON) + front = 1; + if (d < -0.1) // PLANESIDE_EPSILON) + back = 1; + } + if (front && back) + { + if ( !(brush->sides[i].surf & SURF_SKIP) ) + { + (*numsplits)++; + if (brush->sides[i].surf & SURF_HINT) + *hintsplit = true; + } + } + } + + if ( (d_front > 0.0 && d_front < 1.0) + || (d_back < 0.0 && d_back > -1.0) ) + (*epsilonbrush)++; + +#if 0 + if (*numsplits == 0) + { // didn't really need to be split + if (front) + s = PSIDE_FRONT; + else if (back) + s = PSIDE_BACK; + else + s = 0; + } +#endif + + return s; +} + +//======================================================== + +/* +================ +WindingIsTiny + +Returns true if the winding would be crunched out of +existance by the vertex snapping. +================ +*/ +#define EDGE_LENGTH 0.2 +qboolean WindingIsTiny (winding_t *w) +{ +#if 0 + if (WindingArea (w) < 1) + return true; + return false; +#else + int i, j; + vec_t len; + vec3_t delta; + int edges; + + edges = 0; + for (i=0 ; inumpoints ; i++) + { + j = i == w->numpoints - 1 ? 0 : i+1; + VectorSubtract (w->p[j], w->p[i], delta); + len = VectorLength (delta); + if (len > EDGE_LENGTH) + { + if (++edges == 3) + return false; + } + } + return true; +#endif +} + +/* +================ +WindingIsHuge + +Returns true if the winding still has one of the points +from basewinding for plane +================ +*/ +qboolean WindingIsHuge (winding_t *w) +{ + int i, j; + + for (i=0 ; inumpoints ; i++) + { + for (j=0 ; j<3 ; j++) + if (w->p[i][j] < -8000 || w->p[i][j] > 8000) + return true; + } + return false; +} + +//============================================================ + +/* +================ +Leafnode +================ +*/ +void LeafNode (node_t *node, bspbrush_t *brushes) +{ + bspbrush_t *b; + int i; + + node->planenum = PLANENUM_LEAF; + node->contents = 0; + + for (b=brushes ; b ; b=b->next) + { + // if the brush is solid and all of its sides are on nodes, + // it eats everything + if (b->original->contents & CONTENTS_SOLID) + { + for (i=0 ; inumsides ; i++) + if (b->sides[i].texinfo != TEXINFO_NODE) + break; + if (i == b->numsides) + { + node->contents = CONTENTS_SOLID; + break; + } + } + node->contents |= b->original->contents; + } + + node->brushlist = brushes; +} + + +//============================================================ + +void CheckPlaneAgainstParents (int pnum, node_t *node) +{ + node_t *p; + + for (p=node->parent ; p ; p=p->parent) + { + if (p->planenum == pnum) + Error ("Tried parent"); + } +} + +qboolean CheckPlaneAgainstVolume (int pnum, node_t *node) +{ + bspbrush_t *front, *back; + qboolean good; + + SplitBrush (node->volume, pnum, &front, &back); + + good = (front && back); + + if (front) + FreeBrush (front); + if (back) + FreeBrush (back); + + return good; +} + +/* +================ +SelectSplitSide + +Using a hueristic, choses one of the sides out of the brushlist +to partition the brushes with. +Returns NULL if there are no valid planes to split with.. +================ +*/ +side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node) +{ + int value, bestvalue; + bspbrush_t *brush, *test; + side_t *side, *bestside; + int i, j, pass, numpasses; + int pnum; + int s; + int front, back, both, facing, splits; + int bsplits; + int bestsplits; + int epsilonbrush; + qboolean hintsplit; + + bestside = NULL; + bestvalue = -99999; + bestsplits = 0; + + // the search order goes: visible-structural, visible-detail, + // nonvisible-structural, nonvisible-detail. + // If any valid plane is available in a pass, no further + // passes will be tried. + numpasses = 4; + for (pass = 0 ; pass < numpasses ; pass++) + { + for (brush = brushes ; brush ; brush=brush->next) + { + if ( (pass & 1) && !(brush->original->contents & CONTENTS_DETAIL) ) + continue; + if ( !(pass & 1) && (brush->original->contents & CONTENTS_DETAIL) ) + continue; + for (i=0 ; inumsides ; i++) + { + side = brush->sides + i; + if (side->bevel) + continue; // never use a bevel as a spliter + if (!side->winding) + continue; // nothing visible, so it can't split + if (side->texinfo == TEXINFO_NODE) + continue; // allready a node splitter + if (side->tested) + continue; // we allready have metrics for this plane + if (side->surf & SURF_SKIP) + continue; // skip surfaces are never chosen + if ( side->visible ^ (pass<2) ) + continue; // only check visible faces on first pass + + pnum = side->planenum; + pnum &= ~1; // allways use positive facing plane + + CheckPlaneAgainstParents (pnum, node); + + if (!CheckPlaneAgainstVolume (pnum, node)) + continue; // would produce a tiny volume + + front = 0; + back = 0; + both = 0; + facing = 0; + splits = 0; + epsilonbrush = 0; + + for (test = brushes ; test ; test=test->next) + { + s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush); + + splits += bsplits; + if (bsplits && (s&PSIDE_FACING) ) + Error ("PSIDE_FACING with splits"); + + test->testside = s; + // if the brush shares this face, don't bother + // testing that facenum as a splitter again + if (s & PSIDE_FACING) + { + facing++; + for (j=0 ; jnumsides ; j++) + { + if ( (test->sides[j].planenum&~1) == pnum) + test->sides[j].tested = true; + } + } + if (s & PSIDE_FRONT) + front++; + if (s & PSIDE_BACK) + back++; + if (s == PSIDE_BOTH) + both++; + } + + // give a value estimate for using this plane + + value = 5*facing - 5*splits - abs(front-back); +// value = -5*splits; +// value = 5*facing - 5*splits; + if (mapplanes[pnum].type < 3) + value+=5; // axial is better + value -= epsilonbrush*1000; // avoid! + + // never split a hint side except with another hint + if (hintsplit && !(side->surf & SURF_HINT) ) + value = -9999999; + + // save off the side test so we don't need + // to recalculate it when we actually seperate + // the brushes + if (value > bestvalue) + { + bestvalue = value; + bestside = side; + bestsplits = splits; + for (test = brushes ; test ; test=test->next) + test->side = test->testside; + } + } + } + + // if we found a good plane, don't bother trying any + // other passes + if (bestside) + { + if (pass > 1) + { + if (numthreads == 1) + c_nonvis++; + } + if (pass > 0) + node->detail_seperator = true; // not needed for vis + break; + } + } + + // + // clear all the tested flags we set + // + for (brush = brushes ; brush ; brush=brush->next) + { + for (i=0 ; inumsides ; i++) + brush->sides[i].tested = false; + } + + return bestside; +} + + +/* +================== +BrushMostlyOnSide + +================== +*/ +int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane) +{ + int i, j; + winding_t *w; + vec_t d, max; + int side; + + max = 0; + side = PSIDE_FRONT; + for (i=0 ; inumsides ; i++) + { + w = brush->sides[i].winding; + if (!w) + continue; + for (j=0 ; jnumpoints ; j++) + { + d = DotProduct (w->p[j], plane->normal) - plane->dist; + if (d > max) + { + max = d; + side = PSIDE_FRONT; + } + if (-d > max) + { + max = -d; + side = PSIDE_BACK; + } + } + } + return side; +} + +/* +================ +SplitBrush + +Generates two new brushes, leaving the original +unchanged +================ +*/ +void SplitBrush (bspbrush_t *brush, int planenum, + bspbrush_t **front, bspbrush_t **back) +{ + bspbrush_t *b[2]; + int i, j; + winding_t *w, *cw[2], *midwinding; + plane_t *plane, *plane2; + side_t *s, *cs; + float d, d_front, d_back; + + *front = *back = NULL; + plane = &mapplanes[planenum]; + + // check all points + d_front = d_back = 0; + for (i=0 ; inumsides ; i++) + { + w = brush->sides[i].winding; + if (!w) + continue; + for (j=0 ; jnumpoints ; j++) + { + d = DotProduct (w->p[j], plane->normal) - plane->dist; + if (d > 0 && d > d_front) + d_front = d; + if (d < 0 && d < d_back) + d_back = d; + } + } + if (d_front < 0.1) // PLANESIDE_EPSILON) + { // only on back + *back = CopyBrush (brush); + return; + } + if (d_back > -0.1) // PLANESIDE_EPSILON) + { // only on front + *front = CopyBrush (brush); + return; + } + + // create a new winding from the split plane + + w = BaseWindingForPlane (plane->normal, plane->dist); + for (i=0 ; inumsides && w ; i++) + { + plane2 = &mapplanes[brush->sides[i].planenum ^ 1]; + ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON); + } + + if (!w || WindingIsTiny (w) ) + { // the brush isn't really split + int side; + + side = BrushMostlyOnSide (brush, plane); + if (side == PSIDE_FRONT) + *front = CopyBrush (brush); + if (side == PSIDE_BACK) + *back = CopyBrush (brush); + return; + } + + if (WindingIsHuge (w)) + { + qprintf ("WARNING: huge winding\n"); + } + + midwinding = w; + + // split it for real + + for (i=0 ; i<2 ; i++) + { + b[i] = AllocBrush (brush->numsides+1); + b[i]->original = brush->original; + } + + // split all the current windings + + for (i=0 ; inumsides ; i++) + { + s = &brush->sides[i]; + w = s->winding; + if (!w) + continue; + ClipWindingEpsilon (w, plane->normal, plane->dist, + 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]); + for (j=0 ; j<2 ; j++) + { + if (!cw[j]) + continue; +#if 0 + if (WindingIsTiny (cw[j])) + { + FreeWinding (cw[j]); + continue; + } +#endif + cs = &b[j]->sides[b[j]->numsides]; + b[j]->numsides++; + *cs = *s; +// cs->planenum = s->planenum; +// cs->texinfo = s->texinfo; +// cs->visible = s->visible; +// cs->original = s->original; + cs->winding = cw[j]; + cs->tested = false; + } + } + + + // see if we have valid polygons on both sides + + for (i=0 ; i<2 ; i++) + { + BoundBrush (b[i]); + for (j=0 ; j<3 ; j++) + { + if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096) + { + qprintf ("bogus brush after clip\n"); + break; + } + } + + if (b[i]->numsides < 3 || j < 3) + { + FreeBrush (b[i]); + b[i] = NULL; + } + } + + if ( !(b[0] && b[1]) ) + { + if (!b[0] && !b[1]) + qprintf ("split removed brush\n"); + else + qprintf ("split not on both sides\n"); + if (b[0]) + { + FreeBrush (b[0]); + *front = CopyBrush (brush); + } + if (b[1]) + { + FreeBrush (b[1]); + *back = CopyBrush (brush); + } + return; + } + + // add the midwinding to both sides + for (i=0 ; i<2 ; i++) + { + cs = &b[i]->sides[b[i]->numsides]; + b[i]->numsides++; + + cs->planenum = planenum^i^1; + cs->texinfo = TEXINFO_NODE; + cs->visible = false; + cs->tested = false; + if (i==0) + cs->winding = CopyWinding (midwinding); + else + cs->winding = midwinding; + } + +{ + vec_t v1; + int i; + + for (i=0 ; i<2 ; i++) + { + v1 = BrushVolume (b[i]); + if (v1 < 1.0) + { + FreeBrush (b[i]); + b[i] = NULL; +// qprintf ("tiny volume after clip\n"); + } + } +} + + *front = b[0]; + *back = b[1]; +} + +/* +================ +SplitBrushList +================ +*/ +void SplitBrushList (bspbrush_t *brushes, + node_t *node, bspbrush_t **front, bspbrush_t **back) +{ + bspbrush_t *brush, *newbrush, *newbrush2; + side_t *side; + int sides; + int i; + + *front = *back = NULL; + + for (brush = brushes ; brush ; brush=brush->next) + { + sides = brush->side; + + if (sides == PSIDE_BOTH) + { // split into two brushes + SplitBrush (brush, node->planenum, &newbrush, &newbrush2); + if (newbrush) + { + newbrush->next = *front; + *front = newbrush; + } + if (newbrush2) + { + newbrush2->next = *back; + *back = newbrush2; + } + continue; + } + + newbrush = CopyBrush (brush); + + // if the planenum is actualy a part of the brush + // find the plane and flag it as used so it won't be tried + // as a splitter again + if (sides & PSIDE_FACING) + { + for (i=0 ; inumsides ; i++) + { + side = newbrush->sides + i; + if ( (side->planenum& ~1) == node->planenum) + side->texinfo = TEXINFO_NODE; + } + } + + + if (sides & PSIDE_FRONT) + { + newbrush->next = *front; + *front = newbrush; + continue; + } + if (sides & PSIDE_BACK) + { + newbrush->next = *back; + *back = newbrush; + continue; + } + } +} + + +/* +================ +BuildTree_r +================ +*/ +node_t *BuildTree_r (node_t *node, bspbrush_t *brushes) +{ + node_t *newnode; + side_t *bestside; + int i; + bspbrush_t *children[2]; + + if (numthreads == 1) + c_nodes++; + + if (drawflag) + DrawBrushList (brushes, node); + + // find the best plane to use as a splitter + bestside = SelectSplitSide (brushes, node); + if (!bestside) + { + // leaf node + node->side = NULL; + node->planenum = -1; + LeafNode (node, brushes); + return node; + } + + // this is a splitplane node + node->side = bestside; + node->planenum = bestside->planenum & ~1; // always use front facing + + SplitBrushList (brushes, node, &children[0], &children[1]); + FreeBrushList (brushes); + + // allocate children before recursing + for (i=0 ; i<2 ; i++) + { + newnode = AllocNode (); + newnode->parent = node; + node->children[i] = newnode; + } + + SplitBrush (node->volume, node->planenum, &node->children[0]->volume, + &node->children[1]->volume); + + // recursively process children + for (i=0 ; i<2 ; i++) + { + node->children[i] = BuildTree_r (node->children[i], children[i]); + } + + return node; +} + +//=========================================================== + +/* +================= +BrushBSP + +The incoming list will be freed before exiting +================= +*/ +tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs) +{ + node_t *node; + bspbrush_t *b; + int c_faces, c_nonvisfaces; + int c_brushes; + tree_t *tree; + int i; + vec_t volume; + + qprintf ("--- BrushBSP ---\n"); + + tree = AllocTree (); + + c_faces = 0; + c_nonvisfaces = 0; + c_brushes = 0; + for (b=brushlist ; b ; b=b->next) + { + c_brushes++; + + volume = BrushVolume (b); + if (volume < microvolume) + { + printf ("WARNING: entity %i, brush %i: microbrush\n", + b->original->entitynum, b->original->brushnum); + } + + for (i=0 ; inumsides ; i++) + { + if (b->sides[i].bevel) + continue; + if (!b->sides[i].winding) + continue; + if (b->sides[i].texinfo == TEXINFO_NODE) + continue; + if (b->sides[i].visible) + c_faces++; + else + c_nonvisfaces++; + } + + AddPointToBounds (b->mins, tree->mins, tree->maxs); + AddPointToBounds (b->maxs, tree->mins, tree->maxs); + } + + qprintf ("%5i brushes\n", c_brushes); + qprintf ("%5i visible faces\n", c_faces); + qprintf ("%5i nonvisible faces\n", c_nonvisfaces); + + c_nodes = 0; + c_nonvis = 0; + node = AllocNode (); + + node->volume = BrushFromBounds (mins, maxs); + + tree->headnode = node; + + node = BuildTree_r (node, brushlist); + qprintf ("%5i visible nodes\n", c_nodes/2 - c_nonvis); + qprintf ("%5i nonvis nodes\n", c_nonvis); + qprintf ("%5i leafs\n", (c_nodes+1)/2); +#if 0 +{ // debug code +static node_t *tnode; +vec3_t p; + +p[0] = -1469; +p[1] = -118; +p[2] = 119; +tnode = PointInLeaf (tree->headnode, p); +printf ("contents: %i\n", tnode->contents); +p[0] = 0; +} +#endif + return tree; +} + diff --git a/tools/quake2/extra/bsp/qbsp3/csg.c b/tools/quake2/extra/bsp/qbsp3/csg.c new file mode 100644 index 00000000..2d69aa22 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/csg.c @@ -0,0 +1,635 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +/* + +tag all brushes with original contents +brushes may contain multiple contents +there will be no brush overlap after csg phase + + + + +each side has a count of the other sides it splits + +the best split will be the one that minimizes the total split counts +of all remaining sides + +precalc side on plane table + +evaluate split side +{ +cost = 0 +for all sides + for all sides + get + if side splits side and splitside is on same child + cost++; +} + + + */ + +void SplitBrush2 (bspbrush_t *brush, int planenum, + bspbrush_t **front, bspbrush_t **back) +{ + SplitBrush (brush, planenum, front, back); +#if 0 + if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1) + (*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo; // not -1 + if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1) + (*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo; // not -1 +#endif +} + +/* +=============== +SubtractBrush + +Returns a list of brushes that remain after B is subtracted from A. +May by empty if A is contained inside B. + +The originals are undisturbed. +=============== +*/ +bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b) +{ // a - b = out (list) + int i; + bspbrush_t *front, *back; + bspbrush_t *out, *in; + + in = a; + out = NULL; + for (i=0 ; inumsides && in ; i++) + { + SplitBrush2 (in, b->sides[i].planenum, &front, &back); + if (in != a) + FreeBrush (in); + if (front) + { // add to list + front->next = out; + out = front; + } + in = back; + } + if (in) + FreeBrush (in); + else + { // didn't really intersect + FreeBrushList (out); + return a; + } + return out; +} + +/* +=============== +IntersectBrush + +Returns a single brush made up by the intersection of the +two provided brushes, or NULL if they are disjoint. + +The originals are undisturbed. +=============== +*/ +bspbrush_t *IntersectBrush (bspbrush_t *a, bspbrush_t *b) +{ + int i; + bspbrush_t *front, *back; + bspbrush_t *in; + + in = a; + for (i=0 ; inumsides && in ; i++) + { + SplitBrush2 (in, b->sides[i].planenum, &front, &back); + if (in != a) + FreeBrush (in); + if (front) + FreeBrush (front); + in = back; + } + + if (in == a) + return NULL; + + in->next = NULL; + return in; +} + + +/* +=============== +BrushesDisjoint + +Returns true if the two brushes definately do not intersect. +There will be false negatives for some non-axial combinations. +=============== +*/ +qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b) +{ + int i, j; + + // check bounding boxes + for (i=0 ; i<3 ; i++) + if (a->mins[i] >= b->maxs[i] + || a->maxs[i] <= b->mins[i]) + return true; // bounding boxes don't overlap + + // check for opposing planes + for (i=0 ; inumsides ; i++) + { + for (j=0 ; jnumsides ; j++) + { + if (a->sides[i].planenum == + (b->sides[j].planenum^1) ) + return true; // opposite planes, so not touching + } + } + + return false; // might intersect +} + +/* +=============== +IntersectionContents + +Returns a content word for the intersection of two brushes. +Some combinations will generate a combination (water + clip), +but most will be the stronger of the two contents. +=============== +*/ +int IntersectionContents (int c1, int c2) +{ + int out; + + out = c1 | c2; + + if (out & CONTENTS_SOLID) + out = CONTENTS_SOLID; + + return out; +} + + +int minplanenums[3]; +int maxplanenums[3]; + +/* +=============== +ClipBrushToBox + +Any planes shared with the box edge will be set to no texinfo +=============== +*/ +bspbrush_t *ClipBrushToBox (bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs) +{ + int i, j; + bspbrush_t *front, *back; + int p; + + for (j=0 ; j<2 ; j++) + { + if (brush->maxs[j] > clipmaxs[j]) + { + SplitBrush (brush, maxplanenums[j], &front, &back); + if (front) + FreeBrush (front); + brush = back; + if (!brush) + return NULL; + } + if (brush->mins[j] < clipmins[j]) + { + SplitBrush (brush, minplanenums[j], &front, &back); + if (back) + FreeBrush (back); + brush = front; + if (!brush) + return NULL; + } + } + + // remove any colinear faces + + for (i=0 ; inumsides ; i++) + { + p = brush->sides[i].planenum & ~1; + if (p == maxplanenums[0] || p == maxplanenums[1] + || p == minplanenums[0] || p == minplanenums[1]) + { + brush->sides[i].texinfo = TEXINFO_NODE; + brush->sides[i].visible = false; + } + } + return brush; +} + +/* +=============== +MakeBspBrushList +=============== +*/ +bspbrush_t *MakeBspBrushList (int startbrush, int endbrush, + vec3_t clipmins, vec3_t clipmaxs) +{ + mapbrush_t *mb; + bspbrush_t *brushlist, *newbrush; + int i, j; + int c_faces; + int c_brushes; + int numsides; + int vis; + vec3_t normal; + float dist; + + for (i=0 ; i<2 ; i++) + { + VectorClear (normal); + normal[i] = 1; + dist = clipmaxs[i]; + maxplanenums[i] = FindFloatPlane (normal, dist); + dist = clipmins[i]; + minplanenums[i] = FindFloatPlane (normal, dist); + } + + brushlist = NULL; + c_faces = 0; + c_brushes = 0; + + for (i=startbrush ; inumsides; + if (!numsides) + continue; + // make sure the brush has at least one face showing + vis = 0; + for (j=0 ; joriginal_sides[j].visible && mb->original_sides[j].winding) + vis++; +#if 0 + if (!vis) + continue; // no faces at all +#endif + // if the brush is outside the clip area, skip it + for (j=0 ; j<3 ; j++) + if (mb->mins[j] >= clipmaxs[j] + || mb->maxs[j] <= clipmins[j]) + break; + if (j != 3) + continue; + + // + // make a copy of the brush + // + newbrush = AllocBrush (mb->numsides); + newbrush->original = mb; + newbrush->numsides = mb->numsides; + memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t)); + for (j=0 ; jsides[j].winding) + newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding); + if (newbrush->sides[j].surf & SURF_HINT) + newbrush->sides[j].visible = true; // hints are always visible + } + VectorCopy (mb->mins, newbrush->mins); + VectorCopy (mb->maxs, newbrush->maxs); + + // + // carve off anything outside the clip box + // + newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs); + if (!newbrush) + continue; + + c_faces += vis; + c_brushes++; + + newbrush->next = brushlist; + brushlist = newbrush; + } + + return brushlist; +} + +/* +=============== +AddBspBrushListToTail +=============== +*/ +bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail) +{ + bspbrush_t *walk, *next; + + for (walk=list ; walk ; walk=next) + { // add to end of list + next = walk->next; + walk->next = NULL; + tail->next = walk; + tail = walk; + } + + return tail; +} + +/* +=========== +CullList + +Builds a new list that doesn't hold the given brush +=========== +*/ +bspbrush_t *CullList (bspbrush_t *list, bspbrush_t *skip1) +{ + bspbrush_t *newlist; + bspbrush_t *next; + + newlist = NULL; + + for ( ; list ; list = next) + { + next = list->next; + if (list == skip1) + { + FreeBrush (list); + continue; + } + list->next = newlist; + newlist = list; + } + return newlist; +} + + +/* +================== +WriteBrushMap +================== +*/ +void WriteBrushMap (char *name, bspbrush_t *list) +{ + FILE *f; + side_t *s; + int i; + winding_t *w; + + printf ("writing %s\n", name); + f = fopen (name, "wb"); + if (!f) + Error ("Can't write %s\b", name); + + fprintf (f, "{\n\"classname\" \"worldspawn\"\n"); + + for ( ; list ; list=list->next ) + { + fprintf (f, "{\n"); + for (i=0,s=list->sides ; inumsides ; i++,s++) + { + w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist); + + fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]); + fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]); + fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]); + + fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture); + FreeWinding (w); + } + fprintf (f, "}\n"); + } + fprintf (f, "}\n"); + + fclose (f); + +} + +/* +================== +BrushGE + +Returns true if b1 is allowed to bite b2 +================== +*/ +qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2) +{ + // detail brushes never bite structural brushes + if ( (b1->original->contents & CONTENTS_DETAIL) + && !(b2->original->contents & CONTENTS_DETAIL) ) + return false; + if (b1->original->contents & CONTENTS_SOLID) + return true; + return false; +} + +/* +================= +ChopBrushes + +Carves any intersecting solid brushes into the minimum number +of non-intersecting brushes. +================= +*/ +bspbrush_t *ChopBrushes (bspbrush_t *head) +{ + bspbrush_t *b1, *b2, *next; + bspbrush_t *tail; + bspbrush_t *keep; + bspbrush_t *sub, *sub2; + int c1, c2; + + qprintf ("---- ChopBrushes ----\n"); + qprintf ("original brushes: %i\n", CountBrushList (head)); + +#if 0 + if (startbrush == 0) + WriteBrushList ("before.gl", head, false); +#endif + keep = NULL; + +newlist: + // find tail + if (!head) + return NULL; + for (tail=head ; tail->next ; tail=tail->next) + ; + + for (b1=head ; b1 ; b1=next) + { + next = b1->next; + for (b2=b1->next ; b2 ; b2 = b2->next) + { + if (BrushesDisjoint (b1, b2)) + continue; + + sub = NULL; + sub2 = NULL; + c1 = 999999; + c2 = 999999; + + if ( BrushGE (b2, b1) ) + { + sub = SubtractBrush (b1, b2); + if (sub == b1) + continue; // didn't really intersect + if (!sub) + { // b1 is swallowed by b2 + head = CullList (b1, b1); + goto newlist; + } + c1 = CountBrushList (sub); + } + + if ( BrushGE (b1, b2) ) + { + sub2 = SubtractBrush (b2, b1); + if (sub2 == b2) + continue; // didn't really intersect + if (!sub2) + { // b2 is swallowed by b1 + FreeBrushList (sub); + head = CullList (b1, b2); + goto newlist; + } + c2 = CountBrushList (sub2); + } + + if (!sub && !sub2) + continue; // neither one can bite + + // only accept if it didn't fragment + // (commening this out allows full fragmentation) + if (c1 > 1 && c2 > 1) + { + if (sub2) + FreeBrushList (sub2); + if (sub) + FreeBrushList (sub); + continue; + } + + if (c1 < c2) + { + if (sub2) + FreeBrushList (sub2); + tail = AddBrushListToTail (sub, tail); + head = CullList (b1, b1); + goto newlist; + } + else + { + if (sub) + FreeBrushList (sub); + tail = AddBrushListToTail (sub2, tail); + head = CullList (b1, b2); + goto newlist; + } + } + + if (!b2) + { // b1 is no longer intersecting anything, so keep it + b1->next = keep; + keep = b1; + } + } + + qprintf ("output brushes: %i\n", CountBrushList (keep)); +#if 0 + { + WriteBrushList ("after.gl", keep, false); + WriteBrushMap ("after.map", keep); + } +#endif + return keep; +} + + +/* +================= +InitialBrushList +================= +*/ +bspbrush_t *InitialBrushList (bspbrush_t *list) +{ + bspbrush_t *b; + bspbrush_t *out, *newb; + int i; + + // only return brushes that have visible faces + out = NULL; + for (b=list ; b ; b=b->next) + { +#if 0 + for (i=0 ; inumsides ; i++) + if (b->sides[i].visible) + break; + if (i == b->numsides) + continue; +#endif + newb = CopyBrush (b); + newb->next = out; + out = newb; + + // clear visible, so it must be set by MarkVisibleFaces_r + // to be used in the optimized list + for (i=0 ; inumsides ; i++) + { + newb->sides[i].original = &b->sides[i]; +// newb->sides[i].visible = true; + b->sides[i].visible = false; + } + } + + return out; +} + +/* +================= +OptimizedBrushList +================= +*/ +bspbrush_t *OptimizedBrushList (bspbrush_t *list) +{ + bspbrush_t *b; + bspbrush_t *out, *newb; + int i; + + // only return brushes that have visible faces + out = NULL; + for (b=list ; b ; b=b->next) + { + for (i=0 ; inumsides ; i++) + if (b->sides[i].visible) + break; + if (i == b->numsides) + continue; + newb = CopyBrush (b); + newb->next = out; + out = newb; + } + +// WriteBrushList ("vis.gl", out, true); + + return out; +} diff --git a/tools/quake2/extra/bsp/qbsp3/faces.c b/tools/quake2/extra/bsp/qbsp3/faces.c new file mode 100644 index 00000000..1bbc922b --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/faces.c @@ -0,0 +1,1076 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +/* + + some faces will be removed before saving, but still form nodes: + + the insides of sky volumes + meeting planes of different water current volumes + +*/ + +// undefine for dumb linear searches +#define USE_HASHING + +#define INTEGRAL_EPSILON 0.01 +#define POINT_EPSILON 0.5 +#define OFF_EPSILON 0.5 + +int c_merge; +int c_subdivide; + +int c_totalverts; +int c_uniqueverts; +int c_degenerate; +int c_tjunctions; +int c_faceoverflows; +int c_facecollapse; +int c_badstartverts; + +#define MAX_SUPERVERTS 512 +int superverts[MAX_SUPERVERTS]; +int numsuperverts; + +face_t *edgefaces[MAX_MAP_EDGES][2]; +int firstmodeledge = 1; +int firstmodelface; + +int c_tryedges; + +vec3_t edge_dir; +vec3_t edge_start; +vec_t edge_len; + +int num_edge_verts; +int edge_verts[MAX_MAP_VERTS]; + + +float subdivide_size = 240; + + +face_t *NewFaceFromFace (face_t *f); + +//=========================================================================== + +typedef struct hashvert_s +{ + struct hashvert_s *next; + int num; +} hashvert_t; + + +#define HASH_SIZE 64 + + +int vertexchain[MAX_MAP_VERTS]; // the next vertex in a hash chain +int hashverts[HASH_SIZE*HASH_SIZE]; // a vertex number, or 0 for no verts + +face_t *edgefaces[MAX_MAP_EDGES][2]; + +//============================================================================ + + +unsigned HashVec (vec3_t vec) +{ + int x, y; + + x = (4096 + (int)(vec[0]+0.5)) >> 7; + y = (4096 + (int)(vec[1]+0.5)) >> 7; + + if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE ) + Error ("HashVec: point outside valid range"); + + return y*HASH_SIZE + x; +} + +#ifdef USE_HASHING +/* +============= +GetVertex + +Uses hashing +============= +*/ +int GetVertexnum (vec3_t in) +{ + int h; + int i; + float *p; + vec3_t vert; + int vnum; + + c_totalverts++; + + for (i=0 ; i<3 ; i++) + { + if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON) + vert[i] = Q_rint(in[i]); + else + vert[i] = in[i]; + } + + h = HashVec (vert); + + for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum]) + { + p = dvertexes[vnum].point; + if ( fabs(p[0]-vert[0]) 4096) + Error ("GetVertexnum: outside +/- 4096"); + } + + // search for an existing vertex match + for (i=0, dv=dvertexes ; ipoint[j]; + if ( d > POINT_EPSILON || d < -POINT_EPSILON) + break; + } + if (j == 3) + return i; // a match + } + + // new point + if (numvertexes == MAX_MAP_VERTS) + Error ("MAX_MAP_VERTS"); + VectorCopy (v, dv->point); + numvertexes++; + c_uniqueverts++; + + return numvertexes-1; +} +#endif + + +/* +================== +FaceFromSuperverts + +The faces vertexes have beeb added to the superverts[] array, +and there may be more there than can be held in a face (MAXEDGES). + +If less, the faces vertexnums[] will be filled in, otherwise +face will reference a tree of split[] faces until all of the +vertexnums can be added. + +superverts[base] will become face->vertexnums[0], and the others +will be circularly filled in. +================== +*/ +void FaceFromSuperverts (node_t *node, face_t *f, int base) +{ + face_t *newf; + int remaining; + int i; + + remaining = numsuperverts; + while (remaining > MAXEDGES) + { // must split into two faces, because of vertex overload + c_faceoverflows++; + + newf = f->split[0] = NewFaceFromFace (f); + newf = f->split[0]; + newf->next = node->faces; + node->faces = newf; + + newf->numpoints = MAXEDGES; + for (i=0 ; ivertexnums[i] = superverts[(i+base)%numsuperverts]; + + f->split[1] = NewFaceFromFace (f); + f = f->split[1]; + f->next = node->faces; + node->faces = f; + + remaining -= (MAXEDGES-2); + base = (base+MAXEDGES-1)%numsuperverts; + } + + // copy the vertexes back to the face + f->numpoints = remaining; + for (i=0 ; ivertexnums[i] = superverts[(i+base)%numsuperverts]; +} + + +/* +================== +EmitFaceVertexes +================== +*/ +void EmitFaceVertexes (node_t *node, face_t *f) +{ + winding_t *w; + int i; + + if (f->merged || f->split[0] || f->split[1]) + return; + + w = f->w; + for (i=0 ; inumpoints ; i++) + { + if (noweld) + { // make every point unique + if (numvertexes == MAX_MAP_VERTS) + Error ("MAX_MAP_VERTS"); + superverts[i] = numvertexes; + VectorCopy (w->p[i], dvertexes[numvertexes].point); + numvertexes++; + c_uniqueverts++; + c_totalverts++; + } + else + superverts[i] = GetVertexnum (w->p[i]); + } + numsuperverts = w->numpoints; + + // this may fragment the face if > MAXEDGES + FaceFromSuperverts (node, f, 0); +} + +/* +================== +EmitVertexes_r +================== +*/ +void EmitVertexes_r (node_t *node) +{ + int i; + face_t *f; + + if (node->planenum == PLANENUM_LEAF) + return; + + for (f=node->faces ; f ; f=f->next) + { + EmitFaceVertexes (node, f); + } + + for (i=0 ; i<2 ; i++) + EmitVertexes_r (node->children[i]); +} + + +#ifdef USE_HASHING +/* +========== +FindEdgeVerts + +Uses the hash tables to cut down to a small number +========== +*/ +void FindEdgeVerts (vec3_t v1, vec3_t v2) +{ + int x1, x2, y1, y2, t; + int x, y; + int vnum; + +#if 0 +{ + int i; + num_edge_verts = numvertexes-1; + for (i=0 ; i> 7; + y1 = (4096 + (int)(v1[1]+0.5)) >> 7; + x2 = (4096 + (int)(v2[0]+0.5)) >> 7; + y2 = (4096 + (int)(v2[1]+0.5)) >> 7; + + if (x1 > x2) + { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) + { + t = y1; + y1 = y2; + y2 = t; + } +#if 0 + x1--; + x2++; + y1--; + y2++; + if (x1 < 0) + x1 = 0; + if (x2 >= HASH_SIZE) + x2 = HASH_SIZE; + if (y1 < 0) + y1 = 0; + if (y2 >= HASH_SIZE) + y2 = HASH_SIZE; +#endif + num_edge_verts = 0; + for (x=x1 ; x <= x2 ; x++) + { + for (y=y1 ; y <= y2 ; y++) + { + for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum]) + { + edge_verts[num_edge_verts++] = vnum; + } + } + } +} + +#else +/* +========== +FindEdgeVerts + +Forced a dumb check of everything +========== +*/ +void FindEdgeVerts (vec3_t v1, vec3_t v2) +{ + int i; + + num_edge_verts = numvertexes-1; + for (i=0 ; i= end) + continue; // off an end + VectorMA (edge_start, dist, edge_dir, exact); + VectorSubtract (p, exact, off); + error = VectorLength (off); + + if (fabs(error) > OFF_EPSILON) + continue; // not on the edge + + // break the edge + c_tjunctions++; + TestEdge (start, dist, p1, j, k+1); + TestEdge (dist, end, j, p2, k+1); + return; + } + + // the edge p1 to p2 is now free of tjunctions + if (numsuperverts >= MAX_SUPERVERTS) + Error ("MAX_SUPERVERTS"); + superverts[numsuperverts] = p1; + numsuperverts++; +} + +/* +================== +FixFaceEdges + +================== +*/ +void FixFaceEdges (node_t *node, face_t *f) +{ + int p1, p2; + int i; + vec3_t e2; + vec_t len; + int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS]; + int base; + + if (f->merged || f->split[0] || f->split[1]) + return; + + numsuperverts = 0; + + for (i=0 ; inumpoints ; i++) + { + p1 = f->vertexnums[i]; + p2 = f->vertexnums[(i+1)%f->numpoints]; + + VectorCopy (dvertexes[p1].point, edge_start); + VectorCopy (dvertexes[p2].point, e2); + + FindEdgeVerts (edge_start, e2); + + VectorSubtract (e2, edge_start, edge_dir); + len = VectorNormalize (edge_dir, edge_dir); + + start[i] = numsuperverts; + TestEdge (0, len, p1, p2, 0); + + count[i] = numsuperverts - start[i]; + } + + if (numsuperverts < 3) + { // entire face collapsed + f->numpoints = 0; + c_facecollapse++; + return; + } + + // we want to pick a vertex that doesn't have tjunctions + // on either side, which can cause artifacts on trifans, + // especially underwater + for (i=0 ; inumpoints ; i++) + { + if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1) + break; + } + if (i == f->numpoints) + { + f->badstartvert = true; + c_badstartverts++; + base = 0; + } + else + { // rotate the vertex order + base = start[i]; + } + + // this may fragment the face if > MAXEDGES + FaceFromSuperverts (node, f, base); +} + +/* +================== +FixEdges_r +================== +*/ +void FixEdges_r (node_t *node) +{ + int i; + face_t *f; + + if (node->planenum == PLANENUM_LEAF) + return; + + for (f=node->faces ; f ; f=f->next) + FixFaceEdges (node, f); + + for (i=0 ; i<2 ; i++) + FixEdges_r (node->children[i]); +} + +/* +=========== +FixTjuncs + +=========== +*/ +void FixTjuncs (node_t *headnode) +{ + // snap and merge all vertexes + qprintf ("---- snap verts ----\n"); + memset (hashverts, 0, sizeof(hashverts)); + c_totalverts = 0; + c_uniqueverts = 0; + c_faceoverflows = 0; + EmitVertexes_r (headnode); + qprintf ("%i unique from %i\n", c_uniqueverts, c_totalverts); + + // break edges on tjunctions + qprintf ("---- tjunc ----\n"); + c_tryedges = 0; + c_degenerate = 0; + c_facecollapse = 0; + c_tjunctions = 0; + if (!notjunc) + FixEdges_r (headnode); + qprintf ("%5i edges degenerated\n", c_degenerate); + qprintf ("%5i faces degenerated\n", c_facecollapse); + qprintf ("%5i edges added by tjunctions\n", c_tjunctions); + qprintf ("%5i faces added by tjunctions\n", c_faceoverflows); + qprintf ("%5i bad start verts\n", c_badstartverts); +} + + +//======================================================== + +int c_faces; + +face_t *AllocFace (void) +{ + face_t *f; + + f = malloc(sizeof(*f)); + memset (f, 0, sizeof(*f)); + c_faces++; + + return f; +} + +face_t *NewFaceFromFace (face_t *f) +{ + face_t *newf; + + newf = AllocFace (); + *newf = *f; + newf->merged = NULL; + newf->split[0] = newf->split[1] = NULL; + newf->w = NULL; + return newf; +} + +void FreeFace (face_t *f) +{ + if (f->w) + FreeWinding (f->w); + free (f); + c_faces--; +} + +//======================================================== + +/* +================== +GetEdge + +Called by writebsp. +Don't allow four way edges +================== +*/ +int GetEdge2 (int v1, int v2, face_t *f) +{ + dedge_t *edge; + int i; + + c_tryedges++; + + if (!noshare) + { + for (i=firstmodeledge ; i < numedges ; i++) + { + edge = &dedges[i]; + if (v1 == edge->v[1] && v2 == edge->v[0] + && edgefaces[i][0]->contents == f->contents) + { + if (edgefaces[i][1]) + // printf ("WARNING: multiple backward edge\n"); + continue; + edgefaces[i][1] = f; + return -i; + } + #if 0 + if (v1 == edge->v[0] && v2 == edge->v[1]) + { + printf ("WARNING: multiple forward edge\n"); + return i; + } + #endif + } + } + +// emit an edge + if (numedges >= MAX_MAP_EDGES) + Error ("numedges == MAX_MAP_EDGES"); + edge = &dedges[numedges]; + numedges++; + edge->v[0] = v1; + edge->v[1] = v2; + edgefaces[numedges-1][0] = f; + + return numedges-1; +} + +/* +=========================================================================== + +FACE MERGING + +=========================================================================== +*/ + +#define CONTINUOUS_EPSILON 0.001 + +/* +============= +TryMergeWinding + +If two polygons share a common edge and the edges that meet at the +common points are both inside the other polygons, merge them + +Returns NULL if the faces couldn't be merged, or the new face. +The originals will NOT be freed. +============= +*/ +winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal) +{ + vec_t *p1, *p2, *p3, *p4, *back; + winding_t *newf; + int i, j, k, l; + vec3_t normal, delta; + vec_t dot; + qboolean keep1, keep2; + + + // + // find a common edge + // + p1 = p2 = NULL; // stop compiler warning + j = 0; // + + for (i=0 ; inumpoints ; i++) + { + p1 = f1->p[i]; + p2 = f1->p[(i+1)%f1->numpoints]; + for (j=0 ; jnumpoints ; j++) + { + p3 = f2->p[j]; + p4 = f2->p[(j+1)%f2->numpoints]; + for (k=0 ; k<3 ; k++) + { + if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON) + break; + if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON) + break; + } + if (k==3) + break; + } + if (j < f2->numpoints) + break; + } + + if (i == f1->numpoints) + return NULL; // no matching edges + + // + // check slope of connected lines + // if the slopes are colinear, the point can be removed + // + back = f1->p[(i+f1->numpoints-1)%f1->numpoints]; + VectorSubtract (p1, back, delta); + CrossProduct (planenormal, delta, normal); + VectorNormalize (normal, normal); + + back = f2->p[(j+2)%f2->numpoints]; + VectorSubtract (back, p1, delta); + dot = DotProduct (delta, normal); + if (dot > CONTINUOUS_EPSILON) + return NULL; // not a convex polygon + keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON); + + back = f1->p[(i+2)%f1->numpoints]; + VectorSubtract (back, p2, delta); + CrossProduct (planenormal, delta, normal); + VectorNormalize (normal, normal); + + back = f2->p[(j+f2->numpoints-1)%f2->numpoints]; + VectorSubtract (back, p2, delta); + dot = DotProduct (delta, normal); + if (dot > CONTINUOUS_EPSILON) + return NULL; // not a convex polygon + keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON); + + // + // build the new polygon + // + newf = AllocWinding (f1->numpoints + f2->numpoints); + + // copy first polygon + for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints) + { + if (k==(i+1)%f1->numpoints && !keep2) + continue; + + VectorCopy (f1->p[k], newf->p[newf->numpoints]); + newf->numpoints++; + } + + // copy second polygon + for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints) + { + if (l==(j+1)%f2->numpoints && !keep1) + continue; + VectorCopy (f2->p[l], newf->p[newf->numpoints]); + newf->numpoints++; + } + + return newf; +} + +/* +============= +TryMerge + +If two polygons share a common edge and the edges that meet at the +common points are both inside the other polygons, merge them + +Returns NULL if the faces couldn't be merged, or the new face. +The originals will NOT be freed. +============= +*/ +face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal) +{ + face_t *newf; + winding_t *nw; + + if (!f1->w || !f2->w) + return NULL; + if (f1->texinfo != f2->texinfo) + return NULL; + if (f1->planenum != f2->planenum) // on front and back sides + return NULL; + if (f1->contents != f2->contents) + return NULL; + + + nw = TryMergeWinding (f1->w, f2->w, planenormal); + if (!nw) + return NULL; + + c_merge++; + newf = NewFaceFromFace (f1); + newf->w = nw; + + f1->merged = newf; + f2->merged = newf; + + return newf; +} + +/* +=============== +MergeNodeFaces +=============== +*/ +void MergeNodeFaces (node_t *node) +{ + face_t *f1, *f2, *end; + face_t *merged; + plane_t *plane; + + plane = &mapplanes[node->planenum]; + merged = NULL; + + for (f1 = node->faces ; f1 ; f1 = f1->next) + { + if (f1->merged || f1->split[0] || f1->split[1]) + continue; + for (f2 = node->faces ; f2 != f1 ; f2=f2->next) + { + if (f2->merged || f2->split[0] || f2->split[1]) + continue; + merged = TryMerge (f1, f2, plane->normal); + if (!merged) + continue; + + // add merged to the end of the node face list + // so it will be checked against all the faces again + for (end = node->faces ; end->next ; end = end->next) + ; + merged->next = NULL; + end->next = merged; + break; + } + } +} + +//===================================================================== + +/* +=============== +SubdivideFace + +Chop up faces that are larger than we want in the surface cache +=============== +*/ +void SubdivideFace (node_t *node, face_t *f) +{ + float mins, maxs; + vec_t v; + int axis, i; + texinfo_t *tex; + vec3_t temp; + vec_t dist; + winding_t *w, *frontw, *backw; + + if (f->merged) + return; + +// special (non-surface cached) faces don't need subdivision + tex = &texinfo[f->texinfo]; + + if ( tex->flags & (SURF_WARP|SURF_SKY) ) + { + return; + } + + for (axis = 0 ; axis < 2 ; axis++) + { + while (1) + { + mins = 999999; + maxs = -999999; + + VectorCopy (tex->vecs[axis], temp); + w = f->w; + for (i=0 ; inumpoints ; i++) + { + v = DotProduct (w->p[i], temp); + if (v < mins) + mins = v; + if (v > maxs) + maxs = v; + } +#if 0 + if (maxs - mins <= 0) + Error ("zero extents"); +#endif + if (axis == 2) + { // allow double high walls + if (maxs - mins <= subdivide_size/* *2 */) + break; + } + else if (maxs - mins <= subdivide_size) + break; + + // split it + c_subdivide++; + + v = VectorNormalize (temp, temp); + + dist = (mins + subdivide_size - 16)/v; + + ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw); + if (!frontw || !backw) + Error ("SubdivideFace: didn't split the polygon"); + + f->split[0] = NewFaceFromFace (f); + f->split[0]->w = frontw; + f->split[0]->next = node->faces; + node->faces = f->split[0]; + + f->split[1] = NewFaceFromFace (f); + f->split[1]->w = backw; + f->split[1]->next = node->faces; + node->faces = f->split[1]; + + SubdivideFace (node, f->split[0]); + SubdivideFace (node, f->split[1]); + return; + } + } +} + +void SubdivideNodeFaces (node_t *node) +{ + face_t *f; + + for (f = node->faces ; f ; f=f->next) + { + SubdivideFace (node, f); + } +} + +//=========================================================================== + +int c_nodefaces; + + +/* +============ +FaceFromPortal + +============ +*/ +face_t *FaceFromPortal (portal_t *p, int pside) +{ + face_t *f; + side_t *side; + + side = p->side; + if (!side) + return NULL; // portal does not bridge different visible contents + + f = AllocFace (); + + f->texinfo = side->texinfo; + f->planenum = (side->planenum & ~1) | pside; + f->portal = p; + + if ( (p->nodes[pside]->contents & CONTENTS_WINDOW) + && VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW ) + return NULL; // don't show insides of windows + + if (pside) + { + f->w = ReverseWinding(p->winding); + f->contents = p->nodes[1]->contents; + } + else + { + f->w = CopyWinding(p->winding); + f->contents = p->nodes[0]->contents; + } + return f; +} + + +/* +=============== +MakeFaces_r + +If a portal will make a visible face, +mark the side that originally created it + + solid / empty : solid + solid / water : solid + water / empty : water + water / water : none +=============== +*/ +void MakeFaces_r (node_t *node) +{ + portal_t *p; + int s; + + // recurse down to leafs + if (node->planenum != PLANENUM_LEAF) + { + MakeFaces_r (node->children[0]); + MakeFaces_r (node->children[1]); + + // merge together all visible faces on the node + if (!nomerge) + MergeNodeFaces (node); + if (!nosubdiv) + SubdivideNodeFaces (node); + + return; + } + + // solid leafs never have visible faces + if (node->contents & CONTENTS_SOLID) + return; + + // see which portals are valid + for (p=node->portals ; p ; p = p->next[s]) + { + s = (p->nodes[1] == node); + + p->face[s] = FaceFromPortal (p, s); + if (p->face[s]) + { + c_nodefaces++; + p->face[s]->next = p->onnode->faces; + p->onnode->faces = p->face[s]; + } + } +} + +/* +============ +MakeFaces +============ +*/ +void MakeFaces (node_t *node) +{ + qprintf ("--- MakeFaces ---\n"); + c_merge = 0; + c_subdivide = 0; + c_nodefaces = 0; + + MakeFaces_r (node); + + qprintf ("%5i makefaces\n", c_nodefaces); + qprintf ("%5i merged\n", c_merge); + qprintf ("%5i subdivided\n", c_subdivide); +} diff --git a/tools/quake2/extra/bsp/qbsp3/gldraw.c b/tools/quake2/extra/bsp/qbsp3/gldraw.c new file mode 100644 index 00000000..08ab9c45 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/gldraw.c @@ -0,0 +1,232 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include +#include +#include +#include + +#include "qbsp.h" + +// can't use the glvertex3fv functions, because the vec3_t fields +// could be either floats or doubles, depending on DOUBLEVEC_T + +qboolean drawflag; +vec3_t draw_mins, draw_maxs; + + +#define WIN_SIZE 512 + +void InitWindow (void) +{ + auxInitDisplayMode (AUX_SINGLE | AUX_RGB); + auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE); + auxInitWindow ("qcsg"); +} + +void Draw_ClearWindow (void) +{ + static int init; + int w, h, g; + vec_t mx, my; + + if (!drawflag) + return; + + if (!init) + { + init = true; + InitWindow (); + } + + glClearColor (1,0.8,0.8,0); + glClear (GL_COLOR_BUFFER_BIT); + + w = (draw_maxs[0] - draw_mins[0]); + h = (draw_maxs[1] - draw_mins[1]); + + mx = draw_mins[0] + w/2; + my = draw_mins[1] + h/2; + + g = w > h ? w : h; + + glLoadIdentity (); + gluPerspective (90, 1, 2, 16384); + gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0); + + glColor3f (0,0,0); +// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glDisable (GL_DEPTH_TEST); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +#if 0 + glColor4f (1,0,0,0.5); + glBegin (GL_POLYGON); + + glVertex3f (0, 500, 0); + glVertex3f (0, 900, 0); + glVertex3f (0, 900, 100); + glVertex3f (0, 500, 100); + + glEnd (); +#endif + + glFlush (); + +} + +void Draw_SetRed (void) +{ + if (!drawflag) + return; + + glColor3f (1,0,0); +} + +void Draw_SetGrey (void) +{ + if (!drawflag) + return; + + glColor3f (0.5,0.5,0.5); +} + +void Draw_SetBlack (void) +{ + if (!drawflag) + return; + + glColor3f (0,0,0); +} + +void DrawWinding (winding_t *w) +{ + int i; + + if (!drawflag) + return; + + glColor4f (0,0,0,0.5); + glBegin (GL_LINE_LOOP); + for (i=0 ; inumpoints ; i++) + glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); + glEnd (); + + glColor4f (0,1,0,0.3); + glBegin (GL_POLYGON); + for (i=0 ; inumpoints ; i++) + glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); + glEnd (); + + glFlush (); +} + +void DrawAuxWinding (winding_t *w) +{ + int i; + + if (!drawflag) + return; + + glColor4f (0,0,0,0.5); + glBegin (GL_LINE_LOOP); + for (i=0 ; inumpoints ; i++) + glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); + glEnd (); + + glColor4f (1,0,0,0.3); + glBegin (GL_POLYGON); + for (i=0 ; inumpoints ; i++) + glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); + glEnd (); + + glFlush (); +} + +//============================================================ + +#define GLSERV_PORT 25001 + +qboolean wins_init; +int draw_socket; + +void GLS_BeginScene (void) +{ + WSADATA winsockdata; + WORD wVersionRequested; + struct sockaddr_in address; + int r; + + if (!wins_init) + { + wins_init = true; + + wVersionRequested = MAKEWORD(1, 1); + + r = WSAStartup (MAKEWORD(1, 1), &winsockdata); + + if (r) + Error ("Winsock initialization failed."); + + } + + // connect a socket to the server + + draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (draw_socket == -1) + Error ("draw_socket failed"); + + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + address.sin_port = GLSERV_PORT; + r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address)); + if (r == -1) + { + closesocket (draw_socket); + draw_socket = 0; + } +} + +void GLS_Winding (winding_t *w, int code) +{ + byte buf[1024]; + int i, j; + + if (!draw_socket) + return; + + ((int *)buf)[0] = w->numpoints; + ((int *)buf)[1] = code; + for (i=0 ; inumpoints ; i++) + for (j=0 ; j<3 ; j++) + ((float *)buf)[2+i*3+j] = w->p[i][j]; + + send (draw_socket, buf, w->numpoints*12+8, 0); +} + +void GLS_EndScene (void) +{ + closesocket (draw_socket); + draw_socket = 0; +} diff --git a/tools/quake2/extra/bsp/qbsp3/glfile.c b/tools/quake2/extra/bsp/qbsp3/glfile.c new file mode 100644 index 00000000..6d767772 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/glfile.c @@ -0,0 +1,149 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +int c_glfaces; + +int PortalVisibleSides (portal_t *p) +{ + int fcon, bcon; + + if (!p->onnode) + return 0; // outside + + fcon = p->nodes[0]->contents; + bcon = p->nodes[1]->contents; + + // same contents never create a face + if (fcon == bcon) + return 0; + + // FIXME: is this correct now? + if (!fcon) + return 1; + if (!bcon) + return 2; + return 0; +} + +void OutputWinding (winding_t *w, FILE *glview) +{ + static int level = 128; + vec_t light; + int i; + + fprintf (glview, "%i\n", w->numpoints); + level+=28; + light = (level&255)/255.0; + for (i=0 ; inumpoints ; i++) + { + fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n", + w->p[i][0], + w->p[i][1], + w->p[i][2], + light, + light, + light); + } + fprintf (glview, "\n"); +} + +/* +============= +OutputPortal +============= +*/ +void OutputPortal (portal_t *p, FILE *glview) +{ + winding_t *w; + int sides; + + sides = PortalVisibleSides (p); + if (!sides) + return; + + c_glfaces++; + + w = p->winding; + + if (sides == 2) // back side + w = ReverseWinding (w); + + OutputWinding (w, glview); + + if (sides == 2) + FreeWinding(w); +} + +/* +============= +WriteGLView_r +============= +*/ +void WriteGLView_r (node_t *node, FILE *glview) +{ + portal_t *p, *nextp; + + if (node->planenum != PLANENUM_LEAF) + { + WriteGLView_r (node->children[0], glview); + WriteGLView_r (node->children[1], glview); + return; + } + + // write all the portals + for (p=node->portals ; p ; p=nextp) + { + if (p->nodes[0] == node) + { + OutputPortal (p, glview); + nextp = p->next[0]; + } + else + nextp = p->next[1]; + } +} + +/* +============= +WriteGLView +============= +*/ +void WriteGLView (tree_t *tree, char *source) +{ + char name[1024]; + FILE *glview; + + c_glfaces = 0; + sprintf (name, "%s%s.gl",outbase, source); + printf ("Writing %s\n", name); + + glview = fopen (name, "w"); + if (!glview) + Error ("Couldn't open %s", name); + WriteGLView_r (tree->headnode, glview); + fclose (glview); + + printf ("%5i c_glfaces\n", c_glfaces); +} + diff --git a/tools/quake2/extra/bsp/qbsp3/leakfile.c b/tools/quake2/extra/bsp/qbsp3/leakfile.c new file mode 100644 index 00000000..53d48375 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/leakfile.c @@ -0,0 +1,100 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +/* +============================================================================== + +LEAF FILE GENERATION + +Save out name.line for qe3 to read +============================================================================== +*/ + + +/* +============= +LeakFile + +Finds the shortest possible chain of portals +that leads from the outside leaf to a specifically +occupied leaf +============= +*/ +void LeakFile (tree_t *tree) +{ + vec3_t mid; + FILE *linefile; + char filename[1024]; + node_t *node; + int count; + + if (!tree->outside_node.occupied) + return; + + qprintf ("--- LeakFile ---\n"); + + // + // write the points to the file + // + sprintf (filename, "%s.lin", source); + linefile = fopen (filename, "w"); + if (!linefile) + Error ("Couldn't open %s\n", filename); + + count = 0; + node = &tree->outside_node; + while (node->occupied > 1) + { + int next; + portal_t *p, *nextportal; + node_t *nextnode; + int s; + + // find the best portal exit + next = node->occupied; + for (p=node->portals ; p ; p = p->next[!s]) + { + s = (p->nodes[0] == node); + if (p->nodes[s]->occupied + && p->nodes[s]->occupied < next) + { + nextportal = p; + nextnode = p->nodes[s]; + next = nextnode->occupied; + } + } + node = nextnode; + WindingCenter (nextportal->winding, mid); + fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); + count++; + } + // add the occupant center + GetVectorForKey (node->occupant, "origin", mid); + + fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); + qprintf ("%5i point linefile\n", count+1); + + fclose (linefile); +} + diff --git a/tools/quake2/extra/bsp/qbsp3/makefile b/tools/quake2/extra/bsp/qbsp3/makefile new file mode 100644 index 00000000..7368e5b1 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/makefile @@ -0,0 +1,98 @@ + +CFLAGS = -c +LDFLAGS = +ODIR = baddir + +EXEBASE = qbsp3 +EXE = $(ODIR)/qbsp3 +all: $(EXE) + +_next: + make "CFLAGS = -c -g -I../../common -DDOUBLEVEC_T" "ODIR = next" + +_irix: + make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../../common -Xcpluscomm -DDOUBLEVEC_T" "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3" "ODIR = irix" + +_irixdebug: + make "CFLAGS = -c -O2 -g -I../../common -Xcpluscomm -DDOUBLEVEC_T" "LDFLAGS = -g" "ODIR = irix" + +_irixinst: + make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../../common -Xcpluscomm -DDOUBLEVEC_T" "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3" "ODIR = irix" + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + +_irixclean: + rm -f irix/*.o irix/$(EXEBASE) + +_osf: + make "CFLAGS = -c -O4 -I../../common -threads -DDOUBLEVEC_T" "LDFLAGS = -threads" "ODIR = osf" + +clean: + rm -f irix/*.o irix/$(EXEBASE) + +install: + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + + +FILES = $(ODIR)/brushbsp.o $(ODIR)/bspfile.o $(ODIR)/cmdlib.o $(ODIR)/faces.o $(ODIR)/nodraw.o $(ODIR)/glfile.o $(ODIR)/leakfile.o $(ODIR)/map.o $(ODIR)/mathlib.o $(ODIR)/polylib.o $(ODIR)/portals.o $(ODIR)/prtfile.o $(ODIR)/qbsp3.o $(ODIR)/scriplib.o $(ODIR)/textures.o $(ODIR)/threads.o $(ODIR)/tree.o $(ODIR)/writebsp.o $(ODIR)/csg.o + +$(EXE) : $(FILES) + cc -o $(EXE) $(LDFLAGS) $(FILES) -lm + +$(ODIR)/brushbsp.o : brushbsp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/faces.o : faces.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/nodraw.o : nodraw.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/glfile.o : glfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/leakfile.o : leakfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/map.o : map.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/portals.o : portals.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/prtfile.o : prtfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/qbsp3.o : qbsp3.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/tree.o : tree.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/textures.o : textures.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/writebsp.o : writebsp.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/csg.o : csg.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmdlib.o : ../../common/cmdlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/mathlib.o : ../../common/mathlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/polylib.o : ../../common/polylib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/scriplib.o : ../../common/scriplib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/threads.o : ../../common/threads.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/bspfile.o : ../../common/bspfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i diff --git a/tools/quake2/extra/bsp/qbsp3/map.c b/tools/quake2/extra/bsp/qbsp3/map.c new file mode 100644 index 00000000..232979c7 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/map.c @@ -0,0 +1,1017 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +extern qboolean onlyents; + +int nummapbrushes; +mapbrush_t mapbrushes[MAX_MAP_BRUSHES]; + +int nummapbrushsides; +side_t brushsides[MAX_MAP_SIDES]; +brush_texture_t side_brushtextures[MAX_MAP_SIDES]; + +int nummapplanes; +plane_t mapplanes[MAX_MAP_PLANES]; + +#define PLANE_HASHES 1024 +plane_t *planehash[PLANE_HASHES]; + +vec3_t map_mins, map_maxs; + +// undefine to make plane finding use linear sort +#define USE_HASHING + +void TestExpandBrushes (void); + +int c_boxbevels; +int c_edgebevels; + +int c_areaportals; + +int c_clipbrushes; + +/* +============================================================================= + +PLANE FINDING + +============================================================================= +*/ + + +/* +================= +PlaneTypeForNormal +================= +*/ +int PlaneTypeForNormal (vec3_t normal) +{ + vec_t ax, ay, az; + +// NOTE: should these have an epsilon around 1.0? + if (normal[0] == 1.0 || normal[0] == -1.0) + return PLANE_X; + if (normal[1] == 1.0 || normal[1] == -1.0) + return PLANE_Y; + if (normal[2] == 1.0 || normal[2] == -1.0) + return PLANE_Z; + + ax = fabs(normal[0]); + ay = fabs(normal[1]); + az = fabs(normal[2]); + + if (ax >= ay && ax >= az) + return PLANE_ANYX; + if (ay >= ax && ay >= az) + return PLANE_ANYY; + return PLANE_ANYZ; +} + +/* +================ +PlaneEqual +================ +*/ +#define NORMAL_EPSILON 0.00001 +#define DIST_EPSILON 0.01 +qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist) +{ +#if 1 + if ( + fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON + && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON + && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON + && fabs(p->dist - dist) < DIST_EPSILON ) + return true; +#else + if (p->normal[0] == normal[0] + && p->normal[1] == normal[1] + && p->normal[2] == normal[2] + && p->dist == dist) + return true; +#endif + return false; +} + +/* +================ +AddPlaneToHash +================ +*/ +void AddPlaneToHash (plane_t *p) +{ + int hash; + + hash = (int)fabs(p->dist) / 8; + hash &= (PLANE_HASHES-1); + + p->hash_chain = planehash[hash]; + planehash[hash] = p; +} + +/* +================ +CreateNewFloatPlane +================ +*/ +int CreateNewFloatPlane (vec3_t normal, vec_t dist) +{ + plane_t *p, temp; + + if (VectorLength(normal) < 0.5) + Error ("FloatPlane: bad normal"); + // create a new plane + if (nummapplanes+2 > MAX_MAP_PLANES) + Error ("MAX_MAP_PLANES"); + + p = &mapplanes[nummapplanes]; + VectorCopy (normal, p->normal); + p->dist = dist; + p->type = (p+1)->type = PlaneTypeForNormal (p->normal); + + VectorSubtract (vec3_origin, normal, (p+1)->normal); + (p+1)->dist = -dist; + + nummapplanes += 2; + + // allways put axial planes facing positive first + if (p->type < 3) + { + if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0) + { + // flip order + temp = *p; + *p = *(p+1); + *(p+1) = temp; + + AddPlaneToHash (p); + AddPlaneToHash (p+1); + return nummapplanes - 1; + } + } + + AddPlaneToHash (p); + AddPlaneToHash (p+1); + return nummapplanes - 2; +} + +/* +============== +SnapVector +============== +*/ +void SnapVector (vec3_t normal) +{ + int i; + + for (i=0 ; i<3 ; i++) + { + if ( fabs(normal[i] - 1) < NORMAL_EPSILON ) + { + VectorClear (normal); + normal[i] = 1; + break; + } + if ( fabs(normal[i] - -1) < NORMAL_EPSILON ) + { + VectorClear (normal); + normal[i] = -1; + break; + } + } +} + +/* +============== +SnapPlane +============== +*/ +void SnapPlane (vec3_t normal, vec_t *dist) +{ + SnapVector (normal); + + if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON) + *dist = Q_rint(*dist); +} + +/* +============= +FindFloatPlane + +============= +*/ +#ifndef USE_HASHING +int FindFloatPlane (vec3_t normal, vec_t dist) +{ + int i; + plane_t *p; + + SnapPlane (normal, &dist); + for (i=0, p=mapplanes ; ihash_chain) + { + if (PlaneEqual (p, normal, dist)) + return p-mapplanes; + } + } + + return CreateNewFloatPlane (normal, dist); +} +#endif + +/* +================ +PlaneFromPoints +================ +*/ +int PlaneFromPoints (int *p0, int *p1, int *p2) +{ + vec3_t t1, t2, normal; + vec_t dist; + + VectorSubtract (p0, p1, t1); + VectorSubtract (p2, p1, t2); + CrossProduct (t1, t2, normal); + VectorNormalize (normal, normal); + + dist = DotProduct (p0, normal); + + return FindFloatPlane (normal, dist); +} + + +//==================================================================== + + +/* +=========== +BrushContents +=========== +*/ +int BrushContents (mapbrush_t *b) +{ + int contents; + side_t *s; + int i; + int trans; + + s = &b->original_sides[0]; + contents = s->contents; + trans = texinfo[s->texinfo].flags; + for (i=1 ; inumsides ; i++, s++) + { + s = &b->original_sides[i]; + trans |= texinfo[s->texinfo].flags; + if (s->contents != contents) + { + printf ("Entity %i, Brush %i: mixed face contents\n" + , b->entitynum, b->brushnum); + break; + } + } + + // if any side is translucent, mark the contents + // and change solid to window + if ( trans & (SURF_TRANS33|SURF_TRANS66) ) + { + contents |= CONTENTS_TRANSLUCENT; + if (contents & CONTENTS_SOLID) + { + contents &= ~CONTENTS_SOLID; + contents |= CONTENTS_WINDOW; + } + } + + return contents; +} + + +//============================================================================ + +/* +================= +AddBrushBevels + +Adds any additional planes necessary to allow the brush to be expanded +against axial bounding boxes +================= +*/ +void AddBrushBevels (mapbrush_t *b) +{ + int axis, dir; + int i, j, k, l, order; + side_t sidetemp; + brush_texture_t tdtemp; + side_t *s, *s2; + vec3_t normal; + float dist; + winding_t *w, *w2; + vec3_t vec, vec2; + float d; + + // + // add the axial planes + // + order = 0; + for (axis=0 ; axis <3 ; axis++) + { + for (dir=-1 ; dir <= 1 ; dir+=2, order++) + { + // see if the plane is allready present + for (i=0, s=b->original_sides ; inumsides ; i++,s++) + { + if (mapplanes[s->planenum].normal[axis] == dir) + break; + } + + if (i == b->numsides) + { // add a new side + if (nummapbrushsides == MAX_MAP_BRUSHSIDES) + Error ("MAX_MAP_BRUSHSIDES"); + nummapbrushsides++; + b->numsides++; + VectorClear (normal); + normal[axis] = dir; + if (dir == 1) + dist = b->maxs[axis]; + else + dist = -b->mins[axis]; + s->planenum = FindFloatPlane (normal, dist); + s->texinfo = b->original_sides[0].texinfo; + s->contents = b->original_sides[0].contents; + s->bevel = true; + c_boxbevels++; + } + + // if the plane is not in it canonical order, swap it + if (i != order) + { + sidetemp = b->original_sides[order]; + b->original_sides[order] = b->original_sides[i]; + b->original_sides[i] = sidetemp; + + j = b->original_sides - brushsides; + tdtemp = side_brushtextures[j+order]; + side_brushtextures[j+order] = side_brushtextures[j+i]; + side_brushtextures[j+i] = tdtemp; + } + } + } + + // + // add the edge bevels + // + if (b->numsides == 6) + return; // pure axial + + // test the non-axial plane edges + for (i=6 ; inumsides ; i++) + { + s = b->original_sides + i; + w = s->winding; + if (!w) + continue; + for (j=0 ; jnumpoints ; j++) + { + k = (j+1)%w->numpoints; + VectorSubtract (w->p[j], w->p[k], vec); + if (VectorNormalize (vec, vec) < 0.5) + continue; + SnapVector (vec); + for (k=0 ; k<3 ; k++) + if ( vec[k] == -1 || vec[k] == 1) + break; // axial + if (k != 3) + continue; // only test non-axial edges + + // try the six possible slanted axials from this edge + for (axis=0 ; axis <3 ; axis++) + { + for (dir=-1 ; dir <= 1 ; dir+=2) + { + // construct a plane + VectorClear (vec2); + vec2[axis] = dir; + CrossProduct (vec, vec2, normal); + if (VectorNormalize (normal, normal) < 0.5) + continue; + dist = DotProduct (w->p[j], normal); + + // if all the points on all the sides are + // behind this plane, it is a proper edge bevel + for (k=0 ; knumsides ; k++) + { + // if this plane has allready been used, skip it + if (PlaneEqual (&mapplanes[b->original_sides[k].planenum] + , normal, dist) ) + break; + + w2 = b->original_sides[k].winding; + if (!w2) + continue; + for (l=0 ; lnumpoints ; l++) + { + d = DotProduct (w2->p[l], normal) - dist; + if (d > 0.1) + break; // point in front + } + if (l != w2->numpoints) + break; + } + + if (k != b->numsides) + continue; // wasn't part of the outer hull + // add this plane + if (nummapbrushsides == MAX_MAP_BRUSHSIDES) + Error ("MAX_MAP_BRUSHSIDES"); + nummapbrushsides++; + s2 = &b->original_sides[b->numsides]; + s2->planenum = FindFloatPlane (normal, dist); + s2->texinfo = b->original_sides[0].texinfo; + s2->contents = b->original_sides[0].contents; + s2->bevel = true; + c_edgebevels++; + b->numsides++; + } + } + } + } +} + + +/* +================ +MakeBrushWindings + +makes basewindigs for sides and mins / maxs for the brush +================ +*/ +qboolean MakeBrushWindings (mapbrush_t *ob) +{ + int i, j; + winding_t *w; + side_t *side; + plane_t *plane; + + ClearBounds (ob->mins, ob->maxs); + + for (i=0 ; inumsides ; i++) + { + plane = &mapplanes[ob->original_sides[i].planenum]; + w = BaseWindingForPlane (plane->normal, plane->dist); + for (j=0 ; jnumsides && w; j++) + { + if (i == j) + continue; + if (ob->original_sides[j].bevel) + continue; + plane = &mapplanes[ob->original_sides[j].planenum^1]; + ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON); + } + + side = &ob->original_sides[i]; + side->winding = w; + if (w) + { + side->visible = true; + for (j=0 ; jnumpoints ; j++) + AddPointToBounds (w->p[j], ob->mins, ob->maxs); + } + } + + for (i=0 ; i<3 ; i++) + { + if (ob->mins[0] < -4096 || ob->maxs[0] > 4096) + printf ("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum); + if (ob->mins[0] > 4096 || ob->maxs[0] < -4096) + printf ("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum); + } + + return true; +} + + +/* +================= +ParseBrush +================= +*/ +void ParseBrush (entity_t *mapent) +{ + mapbrush_t *b; + int i,j, k; + int mt; + side_t *side, *s2; + int planenum; + brush_texture_t td; + int planepts[3][3]; + + if (nummapbrushes == MAX_MAP_BRUSHES) + Error ("nummapbrushes == MAX_MAP_BRUSHES"); + + b = &mapbrushes[nummapbrushes]; + b->original_sides = &brushsides[nummapbrushsides]; + b->entitynum = num_entities-1; + b->brushnum = nummapbrushes - mapent->firstbrush; + + do + { + if (!GetToken (true)) + break; + if (!strcmp (token, "}") ) + break; + + if (nummapbrushsides == MAX_MAP_BRUSHSIDES) + Error ("MAX_MAP_BRUSHSIDES"); + side = &brushsides[nummapbrushsides]; + + // read the three point plane definition + for (i=0 ; i<3 ; i++) + { + if (i != 0) + GetToken (true); + if (strcmp (token, "(") ) + Error ("parsing brush"); + + for (j=0 ; j<3 ; j++) + { + GetToken (false); + planepts[i][j] = atoi(token); + } + + GetToken (false); + if (strcmp (token, ")") ) + Error ("parsing brush"); + + } + + + // + // read the texturedef + // + GetToken (false); + strcpy (td.name, token); + + GetToken (false); + td.shift[0] = atoi(token); + GetToken (false); + td.shift[1] = atoi(token); + GetToken (false); + td.rotate = atoi(token); + GetToken (false); + td.scale[0] = atof(token); + GetToken (false); + td.scale[1] = atof(token); + + // find default flags and values + mt = FindMiptex (td.name); + td.flags = textureref[mt].flags; + td.value = textureref[mt].value; + side->contents = textureref[mt].contents; + side->surf = td.flags = textureref[mt].flags; + + if (TokenAvailable()) + { + GetToken (false); + side->contents = atoi(token); + GetToken (false); + side->surf = td.flags = atoi(token); + GetToken (false); + td.value = atoi(token); + } + + // translucent objects are automatically classified as detail + if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) + side->contents |= CONTENTS_DETAIL; + if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) + side->contents |= CONTENTS_DETAIL; + if (fulldetail) + side->contents &= ~CONTENTS_DETAIL; + if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) + | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) + side->contents |= CONTENTS_SOLID; + + // hints and skips are never detail, and have no content + if (side->surf & (SURF_HINT|SURF_SKIP) ) + { + side->contents = 0; + side->surf &= ~CONTENTS_DETAIL; + } + + + // + // find the plane number + // + planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]); + if (planenum == -1) + { + printf ("Entity %i, Brush %i: plane with no normal\n" + , b->entitynum, b->brushnum); + continue; + } + + // + // see if the plane has been used already + // + for (k=0 ; knumsides ; k++) + { + s2 = b->original_sides + k; + if (s2->planenum == planenum) + { + printf ("Entity %i, Brush %i: duplicate plane\n" + , b->entitynum, b->brushnum); + break; + } + if ( s2->planenum == (planenum^1) ) + { + printf ("Entity %i, Brush %i: mirrored plane\n" + , b->entitynum, b->brushnum); + break; + } + } + if (k != b->numsides) + continue; // duplicated + + // + // keep this side + // + + side = b->original_sides + b->numsides; + side->planenum = planenum; + side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], + &td, vec3_origin); + + // save the td off in case there is an origin brush and we + // have to recalculate the texinfo + side_brushtextures[nummapbrushsides] = td; + + nummapbrushsides++; + b->numsides++; + } while (1); + + // get the content for the entire brush + b->contents = BrushContents (b); + + // allow detail brushes to be removed + if (nodetail && (b->contents & CONTENTS_DETAIL) ) + { + b->numsides = 0; + return; + } + + // allow water brushes to be removed + if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) + { + b->numsides = 0; + return; + } + + // create windings for sides and bounds for brush + MakeBrushWindings (b); + + // brushes that will not be visible at all will never be + // used as bsp splitters + if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) + { + c_clipbrushes++; + for (i=0 ; inumsides ; i++) + b->original_sides[i].texinfo = TEXINFO_NODE; + } + + // + // origin brushes are removed, but they set + // the rotation origin for the rest of the brushes + // in the entity. After the entire entity is parsed, + // the planenums and texinfos will be adjusted for + // the origin brush + // + if (b->contents & CONTENTS_ORIGIN) + { + char string[32]; + vec3_t origin; + + if (num_entities == 1) + { + Error ("Entity %i, Brush %i: origin brushes not allowed in world" + , b->entitynum, b->brushnum); + return; + } + + VectorAdd (b->mins, b->maxs, origin); + VectorScale (origin, 0.5, origin); + + sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); + SetKeyValue (&entities[b->entitynum], "origin", string); + + VectorCopy (origin, entities[b->entitynum].origin); + + // don't keep this brush + b->numsides = 0; + + return; + } + + AddBrushBevels (b); + + nummapbrushes++; + mapent->numbrushes++; +} + +/* +================ +MoveBrushesToWorld + +Takes all of the brushes from the current entity and +adds them to the world's brush list. + +Used by func_group and func_areaportal +================ +*/ +void MoveBrushesToWorld (entity_t *mapent) +{ + int newbrushes; + int worldbrushes; + mapbrush_t *temp; + int i; + + // this is pretty gross, because the brushes are expected to be + // in linear order for each entity + + newbrushes = mapent->numbrushes; + worldbrushes = entities[0].numbrushes; + + temp = malloc(newbrushes*sizeof(mapbrush_t)); + memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t)); + +#if 0 // let them keep their original brush numbers + for (i=0 ; inumbrushes = 0; +} + +/* +================ +ParseMapEntity +================ +*/ +qboolean ParseMapEntity (void) +{ + entity_t *mapent; + epair_t *e; + side_t *s; + int i, j; + int startbrush, startsides; + vec_t newdist; + mapbrush_t *b; + + if (!GetToken (true)) + return false; + + if (strcmp (token, "{") ) + Error ("ParseEntity: { not found"); + + if (num_entities == MAX_MAP_ENTITIES) + Error ("num_entities == MAX_MAP_ENTITIES"); + + startbrush = nummapbrushes; + startsides = nummapbrushsides; + + mapent = &entities[num_entities]; + num_entities++; + memset (mapent, 0, sizeof(*mapent)); + mapent->firstbrush = nummapbrushes; + mapent->numbrushes = 0; +// mapent->portalareas[0] = -1; +// mapent->portalareas[1] = -1; + + do + { + if (!GetToken (true)) + Error ("ParseEntity: EOF without closing brace"); + if (!strcmp (token, "}") ) + break; + if (!strcmp (token, "{") ) + ParseBrush (mapent); + else + { + e = ParseEpair (); + e->next = mapent->epairs; + mapent->epairs = e; + } + } while (1); + + GetVectorForKey (mapent, "origin", mapent->origin); + + // + // if there was an origin brush, offset all of the planes and texinfo + // + if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) + { + for (i=0 ; inumbrushes ; i++) + { + b = &mapbrushes[mapent->firstbrush + i]; + for (j=0 ; jnumsides ; j++) + { + s = &b->original_sides[j]; + newdist = mapplanes[s->planenum].dist - + DotProduct (mapplanes[s->planenum].normal, mapent->origin); + s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); + s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum], + &side_brushtextures[s-brushsides], mapent->origin); + } + MakeBrushWindings (b); + } + } + + // group entities are just for editor convenience + // toss all brushes into the world entity + if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) + { + MoveBrushesToWorld (mapent); + mapent->numbrushes = 0; + return true; + } + + // areaportal entities move their brushes, but don't eliminate + // the entity + if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) + { + char str[128]; + + if (mapent->numbrushes != 1) + Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1); + + b = &mapbrushes[nummapbrushes-1]; + b->contents = CONTENTS_AREAPORTAL; + c_areaportals++; + mapent->areaportalnum = c_areaportals; + // set the portal number as "style" + sprintf (str, "%i", c_areaportals); + SetKeyValue (mapent, "style", str); + MoveBrushesToWorld (mapent); + return true; + } + + return true; +} + +//=================================================================== + +/* +================ +LoadMapFile +================ +*/ +void LoadMapFile (char *filename) +{ + int i; + + qprintf ("--- LoadMapFile ---\n"); + + LoadScriptFile (filename); + + nummapbrushsides = 0; + num_entities = 0; + + while (ParseMapEntity ()) + { + } + + ClearBounds (map_mins, map_maxs); + for (i=0 ; i 4096) + continue; // no valid points + AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs); + AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs); + } + + qprintf ("%5i brushes\n", nummapbrushes); + qprintf ("%5i clipbrushes\n", c_clipbrushes); + qprintf ("%5i total sides\n", nummapbrushsides); + qprintf ("%5i boxbevels\n", c_boxbevels); + qprintf ("%5i edgebevels\n", c_edgebevels); + qprintf ("%5i entities\n", num_entities); + qprintf ("%5i planes\n", nummapplanes); + qprintf ("%5i areaportals\n", c_areaportals); + qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2], + map_maxs[0],map_maxs[1],map_maxs[2]); + +// TestExpandBrushes (); +} + + +//==================================================================== + + +/* +================ +TestExpandBrushes + +Expands all the brush planes and saves a new map out +================ +*/ +void TestExpandBrushes (void) +{ + FILE *f; + side_t *s; + int i, j, bn; + winding_t *w; + char *name = "expanded.map"; + mapbrush_t *brush; + vec_t dist; + + printf ("writing %s\n", name); + f = fopen (name, "wb"); + if (!f) + Error ("Can't write %s\b", name); + + fprintf (f, "{\n\"classname\" \"worldspawn\"\n"); + + for (bn=0 ; bnnumsides ; i++) + { + s = brush->original_sides + i; + dist = mapplanes[s->planenum].dist; + for (j=0 ; j<3 ; j++) + dist += fabs( 16 * mapplanes[s->planenum].normal[j] ); + + w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist); + + fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]); + fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]); + fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]); + + fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture); + FreeWinding (w); + } + fprintf (f, "}\n"); + } + fprintf (f, "}\n"); + + fclose (f); + + Error ("can't proceed after expanding brushes"); +} diff --git a/tools/quake2/extra/bsp/qbsp3/nodraw.c b/tools/quake2/extra/bsp/qbsp3/nodraw.c new file mode 100644 index 00000000..fd6959d8 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/nodraw.c @@ -0,0 +1,47 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +vec3_t draw_mins, draw_maxs; +qboolean drawflag; + +void Draw_ClearWindow (void) +{ +} + +//============================================================ + +#define GLSERV_PORT 25001 + + +void GLS_BeginScene (void) +{ +} + +void GLS_Winding (winding_t *w, int code) +{ +} + +void GLS_EndScene (void) +{ +} diff --git a/tools/quake2/extra/bsp/qbsp3/portals.c b/tools/quake2/extra/bsp/qbsp3/portals.c new file mode 100644 index 00000000..ef57caef --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/portals.c @@ -0,0 +1,1111 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + + +int c_active_portals; +int c_peak_portals; +int c_boundary; +int c_boundary_sides; + +/* +=========== +AllocPortal +=========== +*/ +portal_t *AllocPortal (void) +{ + portal_t *p; + + if (numthreads == 1) + c_active_portals++; + if (c_active_portals > c_peak_portals) + c_peak_portals = c_active_portals; + + p = malloc (sizeof(portal_t)); + memset (p, 0, sizeof(portal_t)); + + return p; +} + +void FreePortal (portal_t *p) +{ + if (p->winding) + FreeWinding (p->winding); + if (numthreads == 1) + c_active_portals--; + free (p); +} + +//============================================================== + +/* +============== +VisibleContents + +Returns the single content bit of the +strongest visible content present +============== +*/ +int VisibleContents (int contents) +{ + int i; + + for (i=1 ; i<=LAST_VISIBLE_CONTENTS ; i<<=1) + if (contents & i ) + return i; + + return 0; +} + + +/* +=============== +ClusterContents +=============== +*/ +int ClusterContents (node_t *node) +{ + int c1, c2, c; + + if (node->planenum == PLANENUM_LEAF) + return node->contents; + + c1 = ClusterContents(node->children[0]); + c2 = ClusterContents(node->children[1]); + c = c1|c2; + + // a cluster may include some solid detail areas, but + // still be seen into + if ( ! (c1&CONTENTS_SOLID) || ! (c2&CONTENTS_SOLID) ) + c &= ~CONTENTS_SOLID; + return c; +} + +/* +============= +Portal_VisFlood + +Returns true if the portal is empty or translucent, allowing +the PVS calculation to see through it. +The nodes on either side of the portal may actually be clusters, +not leafs, so all contents should be ored together +============= +*/ +qboolean Portal_VisFlood (portal_t *p) +{ + int c1, c2; + + if (!p->onnode) + return false; // to global outsideleaf + + c1 = ClusterContents(p->nodes[0]); + c2 = ClusterContents(p->nodes[1]); + + if (!VisibleContents (c1^c2)) + return true; + + if (c1 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL)) + c1 = 0; + if (c2 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL)) + c2 = 0; + + if ( (c1|c2) & CONTENTS_SOLID ) + return false; // can't see through solid + + if (! (c1 ^ c2)) + return true; // identical on both sides + + if (!VisibleContents (c1^c2)) + return true; + return false; +} + + +/* +=============== +Portal_EntityFlood + +The entity flood determines which areas are +"outside" on the map, which are then filled in. +Flowing from side s to side !s +=============== +*/ +qboolean Portal_EntityFlood (portal_t *p, int s) +{ + if (p->nodes[0]->planenum != PLANENUM_LEAF + || p->nodes[1]->planenum != PLANENUM_LEAF) + Error ("Portal_EntityFlood: not a leaf"); + + // can never cross to a solid + if ( (p->nodes[0]->contents & CONTENTS_SOLID) + || (p->nodes[1]->contents & CONTENTS_SOLID) ) + return false; + + // can flood through everything else + return true; +} + + +//============================================================================= + +int c_tinyportals; + +/* +============= +AddPortalToNodes +============= +*/ +void AddPortalToNodes (portal_t *p, node_t *front, node_t *back) +{ + if (p->nodes[0] || p->nodes[1]) + Error ("AddPortalToNode: allready included"); + + p->nodes[0] = front; + p->next[0] = front->portals; + front->portals = p; + + p->nodes[1] = back; + p->next[1] = back->portals; + back->portals = p; +} + + +/* +============= +RemovePortalFromNode +============= +*/ +void RemovePortalFromNode (portal_t *portal, node_t *l) +{ + portal_t **pp, *t; + +// remove reference to the current portal + pp = &l->portals; + while (1) + { + t = *pp; + if (!t) + Error ("RemovePortalFromNode: portal not in leaf"); + + if ( t == portal ) + break; + + if (t->nodes[0] == l) + pp = &t->next[0]; + else if (t->nodes[1] == l) + pp = &t->next[1]; + else + Error ("RemovePortalFromNode: portal not bounding leaf"); + } + + if (portal->nodes[0] == l) + { + *pp = portal->next[0]; + portal->nodes[0] = NULL; + } + else if (portal->nodes[1] == l) + { + *pp = portal->next[1]; + portal->nodes[1] = NULL; + } +} + +//============================================================================ + +void PrintPortal (portal_t *p) +{ + int i; + winding_t *w; + + w = p->winding; + for (i=0 ; inumpoints ; i++) + printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0] + , w->p[i][1], w->p[i][2]); +} + +/* +================ +MakeHeadnodePortals + +The created portals will face the global outside_node +================ +*/ +#define SIDESPACE 8 +void MakeHeadnodePortals (tree_t *tree) +{ + vec3_t bounds[2]; + int i, j, n; + portal_t *p, *portals[6]; + plane_t bplanes[6], *pl; + node_t *node; + + node = tree->headnode; + +// pad with some space so there will never be null volume leafs + for (i=0 ; i<3 ; i++) + { + bounds[0][i] = tree->mins[i] - SIDESPACE; + bounds[1][i] = tree->maxs[i] + SIDESPACE; + } + + tree->outside_node.planenum = PLANENUM_LEAF; + tree->outside_node.brushlist = NULL; + tree->outside_node.portals = NULL; + tree->outside_node.contents = 0; + + for (i=0 ; i<3 ; i++) + for (j=0 ; j<2 ; j++) + { + n = j*3 + i; + + p = AllocPortal (); + portals[n] = p; + + pl = &bplanes[n]; + memset (pl, 0, sizeof(*pl)); + if (j) + { + pl->normal[i] = -1; + pl->dist = -bounds[j][i]; + } + else + { + pl->normal[i] = 1; + pl->dist = bounds[j][i]; + } + p->plane = *pl; + p->winding = BaseWindingForPlane (pl->normal, pl->dist); + AddPortalToNodes (p, node, &tree->outside_node); + } + +// clip the basewindings by all the other planes + for (i=0 ; i<6 ; i++) + { + for (j=0 ; j<6 ; j++) + { + if (j == i) + continue; + ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON); + } + } +} + +//=================================================== + + +/* +================ +BaseWindingForNode +================ +*/ +#define BASE_WINDING_EPSILON 0.001 +#define SPLIT_WINDING_EPSILON 0.001 + +winding_t *BaseWindingForNode (node_t *node) +{ + winding_t *w; + node_t *n; + plane_t *plane; + vec3_t normal; + vec_t dist; + + w = BaseWindingForPlane (mapplanes[node->planenum].normal + , mapplanes[node->planenum].dist); + + // clip by all the parents + for (n=node->parent ; n && w ; ) + { + plane = &mapplanes[n->planenum]; + + if (n->children[0] == node) + { // take front + ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON); + } + else + { // take back + VectorSubtract (vec3_origin, plane->normal, normal); + dist = -plane->dist; + ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON); + } + node = n; + n = n->parent; + } + + return w; +} + +//============================================================ + +qboolean WindingIsTiny (winding_t *w); + +/* +================== +MakeNodePortal + +create the new portal by taking the full plane winding for the cutting plane +and clipping it by all of parents of this node +================== +*/ +void MakeNodePortal (node_t *node) +{ + portal_t *new_portal, *p; + winding_t *w; + vec3_t normal; + float dist; + int side; + + w = BaseWindingForNode (node); + + // clip the portal by all the other portals in the node + for (p = node->portals ; p && w; p = p->next[side]) + { + if (p->nodes[0] == node) + { + side = 0; + VectorCopy (p->plane.normal, normal); + dist = p->plane.dist; + } + else if (p->nodes[1] == node) + { + side = 1; + VectorSubtract (vec3_origin, p->plane.normal, normal); + dist = -p->plane.dist; + } + else + Error ("CutNodePortals_r: mislinked portal"); + + ChopWindingInPlace (&w, normal, dist, 0.1); + } + + if (!w) + { + return; + } + + if (WindingIsTiny (w)) + { + c_tinyportals++; + FreeWinding (w); + return; + } + + + new_portal = AllocPortal (); + new_portal->plane = mapplanes[node->planenum]; + new_portal->onnode = node; + new_portal->winding = w; + AddPortalToNodes (new_portal, node->children[0], node->children[1]); +} + + +/* +============== +SplitNodePortals + +Move or split the portals that bound node so that the node's +children have portals instead of node. +============== +*/ +void SplitNodePortals (node_t *node) +{ + portal_t *p, *next_portal, *new_portal; + node_t *f, *b, *other_node; + int side; + plane_t *plane; + winding_t *frontwinding, *backwinding; + + plane = &mapplanes[node->planenum]; + f = node->children[0]; + b = node->children[1]; + + for (p = node->portals ; p ; p = next_portal) + { + if (p->nodes[0] == node) + side = 0; + else if (p->nodes[1] == node) + side = 1; + else + Error ("CutNodePortals_r: mislinked portal"); + next_portal = p->next[side]; + + other_node = p->nodes[!side]; + RemovePortalFromNode (p, p->nodes[0]); + RemovePortalFromNode (p, p->nodes[1]); + +// +// cut the portal into two portals, one on each side of the cut plane +// + ClipWindingEpsilon (p->winding, plane->normal, plane->dist, + SPLIT_WINDING_EPSILON, &frontwinding, &backwinding); + + if (frontwinding && WindingIsTiny(frontwinding)) + { + FreeWinding (frontwinding); + frontwinding = NULL; + c_tinyportals++; + } + + if (backwinding && WindingIsTiny(backwinding)) + { + FreeWinding (backwinding); + backwinding = NULL; + c_tinyportals++; + } + + if (!frontwinding && !backwinding) + { // tiny windings on both sides + continue; + } + + if (!frontwinding) + { + FreeWinding (backwinding); + if (side == 0) + AddPortalToNodes (p, b, other_node); + else + AddPortalToNodes (p, other_node, b); + continue; + } + if (!backwinding) + { + FreeWinding (frontwinding); + if (side == 0) + AddPortalToNodes (p, f, other_node); + else + AddPortalToNodes (p, other_node, f); + continue; + } + + // the winding is split + new_portal = AllocPortal (); + *new_portal = *p; + new_portal->winding = backwinding; + FreeWinding (p->winding); + p->winding = frontwinding; + + if (side == 0) + { + AddPortalToNodes (p, f, other_node); + AddPortalToNodes (new_portal, b, other_node); + } + else + { + AddPortalToNodes (p, other_node, f); + AddPortalToNodes (new_portal, other_node, b); + } + } + + node->portals = NULL; +} + + +/* +================ +CalcNodeBounds +================ +*/ +void CalcNodeBounds (node_t *node) +{ + portal_t *p; + int s; + int i; + + // calc mins/maxs for both leafs and nodes + ClearBounds (node->mins, node->maxs); + for (p = node->portals ; p ; p = p->next[s]) + { + s = (p->nodes[1] == node); + for (i=0 ; iwinding->numpoints ; i++) + AddPointToBounds (p->winding->p[i], node->mins, node->maxs); + } +} + + +/* +================== +MakeTreePortals_r +================== +*/ +void MakeTreePortals_r (node_t *node) +{ + int i; + + CalcNodeBounds (node); + if (node->mins[0] >= node->maxs[0]) + { + printf ("WARNING: node without a volume\n"); + } + + for (i=0 ; i<3 ; i++) + { + if (node->mins[i] < -8000 || node->maxs[i] > 8000) + { + printf ("WARNING: node with unbounded volume\n"); + break; + } + } + if (node->planenum == PLANENUM_LEAF) + return; + + MakeNodePortal (node); + SplitNodePortals (node); + + MakeTreePortals_r (node->children[0]); + MakeTreePortals_r (node->children[1]); +} + +/* +================== +MakeTreePortals +================== +*/ +void MakeTreePortals (tree_t *tree) +{ + MakeHeadnodePortals (tree); + MakeTreePortals_r (tree->headnode); +} + +/* +========================================================= + +FLOOD ENTITIES + +========================================================= +*/ + +/* +============= +FloodPortals_r +============= +*/ +void FloodPortals_r (node_t *node, int dist) +{ + portal_t *p; + int s; + + node->occupied = dist; + + for (p=node->portals ; p ; p = p->next[s]) + { + s = (p->nodes[1] == node); + + if (p->nodes[!s]->occupied) + continue; + + if (!Portal_EntityFlood (p, s)) + continue; + + FloodPortals_r (p->nodes[!s], dist+1); + } +} + +/* +============= +PlaceOccupant +============= +*/ +qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant) +{ + node_t *node; + vec_t d; + plane_t *plane; + + // find the leaf to start in + node = headnode; + while (node->planenum != PLANENUM_LEAF) + { + plane = &mapplanes[node->planenum]; + d = DotProduct (origin, plane->normal) - plane->dist; + if (d >= 0) + node = node->children[0]; + else + node = node->children[1]; + } + + if (node->contents == CONTENTS_SOLID) + return false; + node->occupant = occupant; + + FloodPortals_r (node, 1); + + return true; +} + +/* +============= +FloodEntities + +Marks all nodes that can be reached by entites +============= +*/ +qboolean FloodEntities (tree_t *tree) +{ + int i; + vec3_t origin; + char *cl; + qboolean inside; + node_t *headnode; + + headnode = tree->headnode; + qprintf ("--- FloodEntities ---\n"); + inside = false; + tree->outside_node.occupied = 0; + + for (i=1 ; ioutside_node.occupied) + { + qprintf ("entity reached from outside -- no filling\n"); + } + + return (qboolean)(inside && !tree->outside_node.occupied); +} + +/* +========================================================= + +FLOOD AREAS + +========================================================= +*/ + +int c_areas; + +/* +============= +FloodAreas_r +============= +*/ +void FloodAreas_r (node_t *node) +{ + portal_t *p; + int s; + bspbrush_t *b; + entity_t *e; + + if (node->contents == CONTENTS_AREAPORTAL) + { + // this node is part of an area portal + b = node->brushlist; + e = &entities[b->original->entitynum]; + + // if the current area has allready touched this + // portal, we are done + if (e->portalareas[0] == c_areas || e->portalareas[1] == c_areas) + return; + + // note the current area as bounding the portal + if (e->portalareas[1]) + { + printf ("WARNING: areaportal entity %i touches > 2 areas\n", b->original->entitynum); + return; + } + if (e->portalareas[0]) + e->portalareas[1] = c_areas; + else + e->portalareas[0] = c_areas; + + return; + } + + if (node->area) + return; // allready got it + node->area = c_areas; + + for (p=node->portals ; p ; p = p->next[s]) + { + s = (p->nodes[1] == node); +#if 0 + if (p->nodes[!s]->occupied) + continue; +#endif + if (!Portal_EntityFlood (p, s)) + continue; + + FloodAreas_r (p->nodes[!s]); + } +} + +/* +============= +FindAreas_r + +Just decend the tree, and for each node that hasn't had an +area set, flood fill out from there +============= +*/ +void FindAreas_r (node_t *node) +{ + if (node->planenum != PLANENUM_LEAF) + { + FindAreas_r (node->children[0]); + FindAreas_r (node->children[1]); + return; + } + + if (node->area) + return; // allready got it + + if (node->contents & CONTENTS_SOLID) + return; + + if (!node->occupied) + return; // not reachable by entities + + // area portals are allways only flooded into, never + // out of + if (node->contents == CONTENTS_AREAPORTAL) + return; + + c_areas++; + FloodAreas_r (node); +} + +/* +============= +SetAreaPortalAreas_r + +Just decend the tree, and for each node that hasn't had an +area set, flood fill out from there +============= +*/ +void SetAreaPortalAreas_r (node_t *node) +{ + bspbrush_t *b; + entity_t *e; + + if (node->planenum != PLANENUM_LEAF) + { + SetAreaPortalAreas_r (node->children[0]); + SetAreaPortalAreas_r (node->children[1]); + return; + } + + if (node->contents == CONTENTS_AREAPORTAL) + { + if (node->area) + return; // allready set + + b = node->brushlist; + e = &entities[b->original->entitynum]; + node->area = e->portalareas[0]; + if (!e->portalareas[1]) + { + printf ("WARNING: areaportal entity %i doesn't touch two areas\n", b->original->entitynum); + return; + } + } +} + +/* +============= +EmitAreaPortals + +============= +*/ +void EmitAreaPortals (node_t *headnode) +{ + int i, j; + entity_t *e; + dareaportal_t *dp; + + if (c_areas > MAX_MAP_AREAS) + Error ("MAX_MAP_AREAS"); + numareas = c_areas+1; + numareaportals = 1; // leave 0 as an error + + for (i=1 ; i<=c_areas ; i++) + { + dareas[i].firstareaportal = numareaportals; + for (j=0 ; jareaportalnum) + continue; + dp = &dareaportals[numareaportals]; + if (e->portalareas[0] == i) + { + dp->portalnum = e->areaportalnum; + dp->otherarea = e->portalareas[1]; + numareaportals++; + } + else if (e->portalareas[1] == i) + { + dp->portalnum = e->areaportalnum; + dp->otherarea = e->portalareas[0]; + numareaportals++; + } + } + dareas[i].numareaportals = numareaportals - dareas[i].firstareaportal; + } + + qprintf ("%5i numareas\n", numareas); + qprintf ("%5i numareaportals\n", numareaportals); +} + +/* +============= +FloodAreas + +Mark each leaf with an area, bounded by CONTENTS_AREAPORTAL +============= +*/ +void FloodAreas (tree_t *tree) +{ + qprintf ("--- FloodAreas ---\n"); + FindAreas_r (tree->headnode); + SetAreaPortalAreas_r (tree->headnode); + qprintf ("%5i areas\n", c_areas); +} + +//====================================================== + +int c_outside; +int c_inside; +int c_solid; + +void FillOutside_r (node_t *node) +{ + if (node->planenum != PLANENUM_LEAF) + { + FillOutside_r (node->children[0]); + FillOutside_r (node->children[1]); + return; + } + + // anything not reachable by an entity + // can be filled away + if (!node->occupied) + { + if (node->contents != CONTENTS_SOLID) + { + c_outside++; + node->contents = CONTENTS_SOLID; + } + else + c_solid++; + } + else + c_inside++; + +} + +/* +============= +FillOutside + +Fill all nodes that can't be reached by entities +============= +*/ +void FillOutside (node_t *headnode) +{ + c_outside = 0; + c_inside = 0; + c_solid = 0; + qprintf ("--- FillOutside ---\n"); + FillOutside_r (headnode); + qprintf ("%5i solid leafs\n", c_solid); + qprintf ("%5i leafs filled\n", c_outside); + qprintf ("%5i inside leafs\n", c_inside); +} + + +//============================================================== + +/* +============ +FindPortalSide + +Finds a brush side to use for texturing the given portal +============ +*/ +void FindPortalSide (portal_t *p) +{ + int viscontents; + bspbrush_t *bb; + mapbrush_t *brush; + node_t *n; + int i,j; + int planenum; + side_t *side, *bestside; + float dot, bestdot; + plane_t *p1, *p2; + + // decide which content change is strongest + // solid > lava > water, etc + viscontents = VisibleContents (p->nodes[0]->contents ^ p->nodes[1]->contents); + if (!viscontents) + return; + + planenum = p->onnode->planenum; + bestside = NULL; + bestdot = 0; + + for (j=0 ; j<2 ; j++) + { + n = p->nodes[j]; + p1 = &mapplanes[p->onnode->planenum]; + for (bb=n->brushlist ; bb ; bb=bb->next) + { + brush = bb->original; + if ( !(brush->contents & viscontents) ) + continue; + for (i=0 ; inumsides ; i++) + { + side = &brush->original_sides[i]; + if (side->bevel) + continue; + if (side->texinfo == TEXINFO_NODE) + continue; // non-visible + if ((side->planenum&~1) == planenum) + { // exact match + bestside = &brush->original_sides[i]; + goto gotit; + } + // see how close the match is + p2 = &mapplanes[side->planenum&~1]; + dot = DotProduct (p1->normal, p2->normal); + if (dot > bestdot) + { + bestdot = dot; + bestside = side; + } + } + } + } + +gotit: + if (!bestside) + qprintf ("WARNING: side not found for portal\n"); + + p->sidefound = true; + p->side = bestside; +} + + +/* +=============== +MarkVisibleSides_r + +=============== +*/ +void MarkVisibleSides_r (node_t *node) +{ + portal_t *p; + int s; + + if (node->planenum != PLANENUM_LEAF) + { + MarkVisibleSides_r (node->children[0]); + MarkVisibleSides_r (node->children[1]); + return; + } + + // empty leafs are never boundary leafs + if (!node->contents) + return; + + // see if there is a visible face + for (p=node->portals ; p ; p = p->next[!s]) + { + s = (p->nodes[0] == node); + if (!p->onnode) + continue; // edge of world + if (!p->sidefound) + FindPortalSide (p); + if (p->side) + p->side->visible = true; + } + +} + +/* +============= +MarkVisibleSides + +============= +*/ +void MarkVisibleSides (tree_t *tree, int startbrush, int endbrush) +{ + int i, j; + mapbrush_t *mb; + int numsides; + + qprintf ("--- MarkVisibleSides ---\n"); + + // clear all the visible flags + for (i=startbrush ; inumsides; + for (j=0 ; joriginal_sides[j].visible = false; + } + + // set visible flags on the sides that are used by portals + MarkVisibleSides_r (tree->headnode); +} + diff --git a/tools/quake2/extra/bsp/qbsp3/prtfile.c b/tools/quake2/extra/bsp/qbsp3/prtfile.c new file mode 100644 index 00000000..2a5b08f4 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/prtfile.c @@ -0,0 +1,287 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +/* +============================================================================== + +PORTAL FILE GENERATION + +Save out name.prt for qvis to read +============================================================================== +*/ + + +#define PORTALFILE "PRT1" + +FILE *pf; +int num_visclusters; // clusters the player can be in +int num_visportals; + +void WriteFloat (FILE *f, vec_t v) +{ + if ( fabs(v - Q_rint(v)) < 0.001 ) + fprintf (f,"%i ",(int)Q_rint(v)); + else + fprintf (f,"%f ",v); +} + +/* +================= +WritePortalFile_r +================= +*/ +void WritePortalFile_r (node_t *node) +{ + int i, s; + portal_t *p; + winding_t *w; + vec3_t normal; + vec_t dist; + + // decision node + if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) + { + WritePortalFile_r (node->children[0]); + WritePortalFile_r (node->children[1]); + return; + } + + if (node->contents & CONTENTS_SOLID) + return; + + for (p = node->portals ; p ; p=p->next[s]) + { + w = p->winding; + s = (p->nodes[1] == node); + if (w && p->nodes[0] == node) + { + if (!Portal_VisFlood (p)) + continue; + // write out to the file + + // sometimes planes get turned around when they are very near + // the changeover point between different axis. interpret the + // plane the same way vis will, and flip the side orders if needed + // FIXME: is this still relevent? + WindingPlane (w, normal, &dist); + if ( DotProduct (p->plane.normal, normal) < 0.99 ) + { // backwards... + fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); + } + else + fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster); + for (i=0 ; inumpoints ; i++) + { + fprintf (pf,"("); + WriteFloat (pf, w->p[i][0]); + WriteFloat (pf, w->p[i][1]); + WriteFloat (pf, w->p[i][2]); + fprintf (pf,") "); + } + fprintf (pf,"\n"); + } + } + +} + +/* +================ +FillLeafNumbers_r + +All of the leafs under node will have the same cluster +================ +*/ +void FillLeafNumbers_r (node_t *node, int num) +{ + if (node->planenum == PLANENUM_LEAF) + { + if (node->contents & CONTENTS_SOLID) + node->cluster = -1; + else + node->cluster = num; + return; + } + node->cluster = num; + FillLeafNumbers_r (node->children[0], num); + FillLeafNumbers_r (node->children[1], num); +} + +/* +================ +NumberLeafs_r +================ +*/ +void NumberLeafs_r (node_t *node) +{ + portal_t *p; + + if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) + { // decision node + node->cluster = -99; + NumberLeafs_r (node->children[0]); + NumberLeafs_r (node->children[1]); + return; + } + + // either a leaf or a detail cluster + + if ( node->contents & CONTENTS_SOLID ) + { // solid block, viewpoint never inside + node->cluster = -1; + return; + } + + FillLeafNumbers_r (node, num_visclusters); + num_visclusters++; + + // count the portals + for (p = node->portals ; p ; ) + { + if (p->nodes[0] == node) // only write out from first leaf + { + if (Portal_VisFlood (p)) + num_visportals++; + p = p->next[0]; + } + else + p = p->next[1]; + } + +} + + +/* +================ +CreateVisPortals_r +================ +*/ +void CreateVisPortals_r (node_t *node) +{ + // stop as soon as we get to a detail_seperator, which + // means that everything below is in a single cluster + if (node->planenum == PLANENUM_LEAF || node->detail_seperator ) + return; + + MakeNodePortal (node); + SplitNodePortals (node); + + CreateVisPortals_r (node->children[0]); + CreateVisPortals_r (node->children[1]); +} + +/* +================ +FinishVisPortals_r +================ +*/ +void FinishVisPortals2_r (node_t *node) +{ + if (node->planenum == PLANENUM_LEAF) + return; + + MakeNodePortal (node); + SplitNodePortals (node); + + FinishVisPortals2_r (node->children[0]); + FinishVisPortals2_r (node->children[1]); +} + +void FinishVisPortals_r (node_t *node) +{ + if (node->planenum == PLANENUM_LEAF) + return; + + if (node->detail_seperator) + { + FinishVisPortals2_r (node); + return; + } + + FinishVisPortals_r (node->children[0]); + FinishVisPortals_r (node->children[1]); +} + + +int clusterleaf; +void SaveClusters_r (node_t *node) +{ + if (node->planenum == PLANENUM_LEAF) + { + dleafs[clusterleaf++].cluster = node->cluster; + return; + } + SaveClusters_r (node->children[0]); + SaveClusters_r (node->children[1]); +} + +/* +================ +WritePortalFile +================ +*/ +void WritePortalFile (tree_t *tree) +{ + char filename[1024]; + node_t *headnode; + + qprintf ("--- WritePortalFile ---\n"); + + headnode = tree->headnode; + num_visclusters = 0; + num_visportals = 0; + + FreeTreePortals_r (headnode); + + MakeHeadnodePortals (tree); + + CreateVisPortals_r (headnode); + +// set the cluster field in every leaf and count the total number of portals + + NumberLeafs_r (headnode); + +// write the file + sprintf (filename, "%s.prt", source); + printf ("writing %s\n", filename); + pf = fopen (filename, "w"); + if (!pf) + Error ("Error opening %s", filename); + + fprintf (pf, "%s\n", PORTALFILE); + fprintf (pf, "%i\n", num_visclusters); + fprintf (pf, "%i\n", num_visportals); + + qprintf ("%5i visclusters\n", num_visclusters); + qprintf ("%5i visportals\n", num_visportals); + + WritePortalFile_r (headnode); + + fclose (pf); + + // we need to store the clusters out now because ordering + // issues made us do this after writebsp... + clusterleaf = 1; + SaveClusters_r (headnode); +} + diff --git a/tools/quake2/extra/bsp/qbsp3/qbsp.h b/tools/quake2/extra/bsp/qbsp3/qbsp.h new file mode 100644 index 00000000..af032e43 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/qbsp.h @@ -0,0 +1,355 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "scriplib.h" +#include "polylib.h" +#include "threads.h" +#include "bspfile.h" + +#define MAX_BRUSH_SIDES 128 +#define CLIP_EPSILON 0.1 + +#define BOGUS_RANGE 8192 + +#define TEXINFO_NODE -1 // side is allready on a node + +typedef struct plane_s +{ + vec3_t normal; + vec_t dist; + int type; + struct plane_s *hash_chain; +} plane_t; + +typedef struct +{ + vec_t shift[2]; + vec_t rotate; + vec_t scale[2]; + char name[32]; + int flags; + int value; +} brush_texture_t; + +typedef struct side_s +{ + int planenum; + int texinfo; + winding_t *winding; + struct side_s *original; // bspbrush_t sides will reference the mapbrush_t sides + int contents; // from miptex + int surf; // from miptex + qboolean visible; // choose visble planes first + qboolean tested; // this plane allready checked as a split + qboolean bevel; // don't ever use for bsp splitting +} side_t; + +typedef struct brush_s +{ + int entitynum; + int brushnum; + + int contents; + + vec3_t mins, maxs; + + int numsides; + side_t *original_sides; +} mapbrush_t; + +#define PLANENUM_LEAF -1 + +#define MAXEDGES 20 + +typedef struct face_s +{ + struct face_s *next; // on node + + // the chain of faces off of a node can be merged or split, + // but each face_t along the way will remain in the chain + // until the entire tree is freed + struct face_s *merged; // if set, this face isn't valid anymore + struct face_s *split[2]; // if set, this face isn't valid anymore + + struct portal_s *portal; + int texinfo; + int planenum; + int contents; // faces in different contents can't merge + int outputnumber; + winding_t *w; + int numpoints; + qboolean badstartvert; // tjunctions cannot be fixed without a midpoint vertex + int vertexnums[MAXEDGES]; +} face_t; + + + +typedef struct bspbrush_s +{ + struct bspbrush_s *next; + vec3_t mins, maxs; + int side, testside; // side of node during construction + mapbrush_t *original; + int numsides; + side_t sides[6]; // variably sized +} bspbrush_t; + + + +#define MAX_NODE_BRUSHES 8 +typedef struct node_s +{ + // both leafs and nodes + int planenum; // -1 = leaf node + struct node_s *parent; + vec3_t mins, maxs; // valid after portalization + bspbrush_t *volume; // one for each leaf/node + + // nodes only + qboolean detail_seperator; // a detail brush caused the split + side_t *side; // the side that created the node + struct node_s *children[2]; + face_t *faces; + + // leafs only + bspbrush_t *brushlist; // fragments of all brushes in this leaf + int contents; // OR of all brush contents + int occupied; // 1 or greater can reach entity + entity_t *occupant; // for leak file testing + int cluster; // for portalfile writing + int area; // for areaportals + struct portal_s *portals; // also on nodes during construction +} node_t; + +typedef struct portal_s +{ + plane_t plane; + node_t *onnode; // NULL = outside box + node_t *nodes[2]; // [0] = front side of plane + struct portal_s *next[2]; + winding_t *winding; + + qboolean sidefound; // false if ->side hasn't been checked + side_t *side; // NULL = non-visible + face_t *face[2]; // output face in bsp file +} portal_t; + +typedef struct +{ + node_t *headnode; + node_t outside_node; + vec3_t mins, maxs; +} tree_t; + +extern int entity_num; + +extern plane_t mapplanes[MAX_MAP_PLANES]; +extern int nummapplanes; + +extern int nummapbrushes; +extern mapbrush_t mapbrushes[MAX_MAP_BRUSHES]; + +extern vec3_t map_mins, map_maxs; + +#define MAX_MAP_SIDES (MAX_MAP_BRUSHES*6) + +extern int nummapbrushsides; +extern side_t brushsides[MAX_MAP_SIDES]; + +extern qboolean noprune; +extern qboolean nodetail; +extern qboolean fulldetail; +extern qboolean nomerge; +extern qboolean nosubdiv; +extern qboolean nowater; +extern qboolean noweld; +extern qboolean noshare; +extern qboolean notjunc; + +extern vec_t microvolume; + +extern char outbase[32]; + +extern char source[1024]; + +void LoadMapFile (char *filename); +int FindFloatPlane (vec3_t normal, vec_t dist); + +//============================================================================= + +// textures.c + +typedef struct +{ + char name[64]; + int flags; + int value; + int contents; + char animname[64]; +} textureref_t; + +#define MAX_MAP_TEXTURES 1024 + +extern textureref_t textureref[MAX_MAP_TEXTURES]; + +int FindMiptex (char *name); + +int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin); + +//============================================================================= + +void FindGCD (int *v); + +mapbrush_t *Brush_LoadEntity (entity_t *ent); +int PlaneTypeForNormal (vec3_t normal); +qboolean MakeBrushPlanes (mapbrush_t *b); +int FindIntPlane (int *inormal, int *iorigin); +void CreateBrush (int brushnum); + + +//============================================================================= + +// draw.c + +extern vec3_t draw_mins, draw_maxs; +extern qboolean drawflag; + +void Draw_ClearWindow (void); +void DrawWinding (winding_t *w); + +void GLS_BeginScene (void); +void GLS_Winding (winding_t *w, int code); +void GLS_EndScene (void); + +//============================================================================= + +// csg + +bspbrush_t *MakeBspBrushList (int startbrush, int endbrush, + vec3_t clipmins, vec3_t clipmaxs); +bspbrush_t *ChopBrushes (bspbrush_t *head); +bspbrush_t *InitialBrushList (bspbrush_t *list); +bspbrush_t *OptimizedBrushList (bspbrush_t *list); + +void WriteBrushMap (char *name, bspbrush_t *list); + +//============================================================================= + +// brushbsp + +void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis); + +bspbrush_t *CopyBrush (bspbrush_t *brush); + +void SplitBrush (bspbrush_t *brush, int planenum, + bspbrush_t **front, bspbrush_t **back); + +tree_t *AllocTree (void); +node_t *AllocNode (void); +bspbrush_t *AllocBrush (int numsides); +int CountBrushList (bspbrush_t *brushes); +void FreeBrush (bspbrush_t *brushes); +vec_t BrushVolume (bspbrush_t *brush); + +void BoundBrush (bspbrush_t *brush); +void FreeBrushList (bspbrush_t *brushes); + +tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs); + +//============================================================================= + +// portals.c + +int VisibleContents (int contents); + +void MakeHeadnodePortals (tree_t *tree); +void MakeNodePortal (node_t *node); +void SplitNodePortals (node_t *node); + +qboolean Portal_VisFlood (portal_t *p); + +qboolean FloodEntities (tree_t *tree); +void FillOutside (node_t *headnode); +void FloodAreas (tree_t *tree); +void MarkVisibleSides (tree_t *tree, int start, int end); +void FreePortal (portal_t *p); +void EmitAreaPortals (node_t *headnode); + +void MakeTreePortals (tree_t *tree); + +//============================================================================= + +// glfile.c + +void OutputWinding (winding_t *w, FILE *glview); +void WriteGLView (tree_t *tree, char *source); + +//============================================================================= + +// leakfile.c + +void LeakFile (tree_t *tree); + +//============================================================================= + +// prtfile.c + +void WritePortalFile (tree_t *tree); + +//============================================================================= + +// writebsp.c + +void SetModelNumbers (void); +void SetLightStyles (void); + +void BeginBSPFile (void); +void WriteBSP (node_t *headnode); +void EndBSPFile (void); +void BeginModel (void); +void EndModel (void); + +//============================================================================= + +// faces.c + +void MakeFaces (node_t *headnode); +void FixTjuncs (node_t *headnode); +int GetEdge2 (int v1, int v2, face_t *f); + +face_t *AllocFace (void); +void FreeFace (face_t *f); + +void MergeNodeFaces (node_t *node); + +//============================================================================= + +// tree.c + +void FreeTree (tree_t *tree); +void FreeTree_r (node_t *node); +void PrintTree_r (node_t *node, int depth); +void FreeTreePortals_r (node_t *node); +void PruneNodes_r (node_t *node); +void PruneNodes (node_t *node); diff --git a/tools/quake2/extra/bsp/qbsp3/qbsp3.c b/tools/quake2/extra/bsp/qbsp3/qbsp3.c new file mode 100644 index 00000000..1cc5b907 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/qbsp3.c @@ -0,0 +1,537 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qbsp.h" + +extern float subdivide_size; + +char source[1024]; +char name[1024]; + +vec_t microvolume = 1.0; +qboolean noprune; +qboolean glview; +qboolean nodetail; +qboolean fulldetail; +qboolean onlyents; +qboolean nomerge; +qboolean nowater; +qboolean nofill; +qboolean nocsg; +qboolean noweld; +qboolean noshare; +qboolean nosubdiv; +qboolean notjunc; +qboolean noopt; +qboolean leaktest; +qboolean verboseentities; + +char outbase[32]; + +int block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7; + +int entity_num; + + +node_t *block_nodes[10][10]; + +/* +============ +BlockTree + +============ +*/ +node_t *BlockTree (int xl, int yl, int xh, int yh) +{ + node_t *node; + vec3_t normal; + float dist; + int mid; + + if (xl == xh && yl == yh) + { + node = block_nodes[xl+5][yl+5]; + if (!node) + { // return an empty leaf + node = AllocNode (); + node->planenum = PLANENUM_LEAF; + node->contents = 0; //CONTENTS_SOLID; + return node; + } + return node; + } + + // create a seperator along the largest axis + node = AllocNode (); + + if (xh - xl > yh - yl) + { // split x axis + mid = xl + (xh-xl)/2 + 1; + normal[0] = 1; + normal[1] = 0; + normal[2] = 0; + dist = mid*1024; + node->planenum = FindFloatPlane (normal, dist); + node->children[0] = BlockTree ( mid, yl, xh, yh); + node->children[1] = BlockTree ( xl, yl, mid-1, yh); + } + else + { + mid = yl + (yh-yl)/2 + 1; + normal[0] = 0; + normal[1] = 1; + normal[2] = 0; + dist = mid*1024; + node->planenum = FindFloatPlane (normal, dist); + node->children[0] = BlockTree ( xl, mid, xh, yh); + node->children[1] = BlockTree ( xl, yl, xh, mid-1); + } + + return node; +} + +/* +============ +ProcessBlock_Thread + +============ +*/ +int brush_start, brush_end; +void ProcessBlock_Thread (int blocknum) +{ + int xblock, yblock; + vec3_t mins, maxs; + bspbrush_t *brushes; + tree_t *tree; + node_t *node; + + yblock = block_yl + blocknum / (block_xh-block_xl+1); + xblock = block_xl + blocknum % (block_xh-block_xl+1); + + qprintf ("############### block %2i,%2i ###############\n", xblock, yblock); + + mins[0] = xblock*1024; + mins[1] = yblock*1024; + mins[2] = -4096; + maxs[0] = (xblock+1)*1024; + maxs[1] = (yblock+1)*1024; + maxs[2] = 4096; + + // the makelist and chopbrushes could be cached between the passes... + brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs); + if (!brushes) + { + node = AllocNode (); + node->planenum = PLANENUM_LEAF; + node->contents = CONTENTS_SOLID; + block_nodes[xblock+5][yblock+5] = node; + return; + } + + if (!nocsg) + brushes = ChopBrushes (brushes); + + tree = BrushBSP (brushes, mins, maxs); + + block_nodes[xblock+5][yblock+5] = tree->headnode; +} + +/* +============ +ProcessWorldModel + +============ +*/ +void ProcessWorldModel (void) +{ + entity_t *e; + tree_t *tree; + qboolean leaked; + qboolean optimize; + + e = &entities[entity_num]; + + brush_start = e->firstbrush; + brush_end = brush_start + e->numbrushes; + leaked = false; + + // + // perform per-block operations + // + if (block_xh * 1024 > map_maxs[0]) + block_xh = floor(map_maxs[0]/1024.0); + if ( (block_xl+1) * 1024 < map_mins[0]) + block_xl = floor(map_mins[0]/1024.0); + if (block_yh * 1024 > map_maxs[1]) + block_yh = floor(map_maxs[1]/1024.0); + if ( (block_yl+1) * 1024 < map_mins[1]) + block_yl = floor(map_mins[1]/1024.0); + + if (block_xl <-4) + block_xl = -4; + if (block_yl <-4) + block_yl = -4; + if (block_xh > 3) + block_xh = 3; + if (block_yh > 3) + block_yh = 3; + + for (optimize = false ; optimize <= true ; optimize++) + { + qprintf ("--------------------------------------------\n"); + + RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1), + !verbose, ProcessBlock_Thread); + + // + // build the division tree + // oversizing the blocks guarantees that all the boundaries + // will also get nodes. + // + + qprintf ("--------------------------------------------\n"); + + tree = AllocTree (); + tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1); + + tree->mins[0] = (block_xl)*1024; + tree->mins[1] = (block_yl)*1024; + tree->mins[2] = map_mins[2] - 8; + + tree->maxs[0] = (block_xh+1)*1024; + tree->maxs[1] = (block_yh+1)*1024; + tree->maxs[2] = map_maxs[2] + 8; + + // + // perform the global operations + // + MakeTreePortals (tree); + + if (FloodEntities (tree)) + FillOutside (tree->headnode); + else + { + printf ("**** leaked ****\n"); + leaked = true; + LeakFile (tree); + if (leaktest) + { + printf ("--- MAP LEAKED ---\n"); + exit (0); + } + } + + MarkVisibleSides (tree, brush_start, brush_end); + if (noopt || leaked) + break; + if (!optimize) + { + FreeTree (tree); + } + } + + FloodAreas (tree); + if (glview) + WriteGLView (tree, source); + MakeFaces (tree->headnode); + FixTjuncs (tree->headnode); + + if (!noprune) + PruneNodes (tree->headnode); + + WriteBSP (tree->headnode); + + if (!leaked) + WritePortalFile (tree); + + FreeTree (tree); +} + +/* +============ +ProcessSubModel + +============ +*/ +void ProcessSubModel (void) +{ + entity_t *e; + int start, end; + tree_t *tree; + bspbrush_t *list; + vec3_t mins, maxs; + + e = &entities[entity_num]; + + start = e->firstbrush; + end = start + e->numbrushes; + + mins[0] = mins[1] = mins[2] = -4096; + maxs[0] = maxs[1] = maxs[2] = 4096; + list = MakeBspBrushList (start, end, mins, maxs); + if (!nocsg) + list = ChopBrushes (list); + tree = BrushBSP (list, mins, maxs); + MakeTreePortals (tree); + MarkVisibleSides (tree, start, end); + MakeFaces (tree->headnode); + FixTjuncs (tree->headnode); + WriteBSP (tree->headnode); + FreeTree (tree); +} + +/* +============ +ProcessModels +============ +*/ +void ProcessModels (void) +{ + BeginBSPFile (); + + for (entity_num=0 ; entity_num< num_entities ; entity_num++) + { + if (!entities[entity_num].numbrushes) + continue; + + qprintf ("############### model %i ###############\n", nummodels); + BeginModel (); + if (entity_num == 0) + ProcessWorldModel (); + else + ProcessSubModel (); + EndModel (); + + if (!verboseentities) + verbose = false; // don't bother printing submodels + } + + EndBSPFile (); +} + + +/* +============ +main +============ +*/ +int main (int argc, char **argv) +{ + int i; + double start, end; + char path[1024]; + + printf ("---- qbsp3 ----\n"); + + for (i=1 ; ivalue); + textureref[i].flags = LittleLong (mt->flags); + textureref[i].contents = LittleLong (mt->contents); + strcpy (textureref[i].animname, mt->animname); + free (mt); + } + nummiptex++; + + if (textureref[i].animname[0]) + FindMiptex (textureref[i].animname); + + return i; +} + + +/* +================== +textureAxisFromPlane +================== +*/ +vec3_t baseaxis[18] = +{ +{0,0,1}, {1,0,0}, {0,-1,0}, // floor +{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling +{1,0,0}, {0,1,0}, {0,0,-1}, // west wall +{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall +{0,1,0}, {1,0,0}, {0,0,-1}, // south wall +{0,-1,0}, {1,0,0}, {0,0,-1} // north wall +}; + +void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv) +{ + int bestaxis; + vec_t dot,best; + int i; + + best = 0; + bestaxis = 0; + + for (i=0 ; i<6 ; i++) + { + dot = DotProduct (pln->normal, baseaxis[i*3]); + if (dot > best) + { + best = dot; + bestaxis = i; + } + } + + VectorCopy (baseaxis[bestaxis*3+1], xv); + VectorCopy (baseaxis[bestaxis*3+2], yv); +} + + + + +int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin) +{ + vec3_t vecs[2]; + int sv, tv; + vec_t ang, sinv, cosv; + vec_t ns, nt; + texinfo_t tx, *tc; + int i, j, k; + float shift[2]; + brush_texture_t anim; + int mt; + + if (!bt->name[0]) + return 0; + + memset (&tx, 0, sizeof(tx)); + strcpy (tx.texture, bt->name); + + TextureAxisFromPlane(plane, vecs[0], vecs[1]); + + shift[0] = DotProduct (origin, vecs[0]); + shift[1] = DotProduct (origin, vecs[1]); + + if (!bt->scale[0]) + bt->scale[0] = 1; + if (!bt->scale[1]) + bt->scale[1] = 1; + + +// rotate axis + if (bt->rotate == 0) + { sinv = 0 ; cosv = 1; } + else if (bt->rotate == 90) + { sinv = 1 ; cosv = 0; } + else if (bt->rotate == 180) + { sinv = 0 ; cosv = -1; } + else if (bt->rotate == 270) + { sinv = -1 ; cosv = 0; } + else + { + ang = bt->rotate / 180 * Q_PI; + sinv = sin(ang); + cosv = cos(ang); + } + + if (vecs[0][0]) + sv = 0; + else if (vecs[0][1]) + sv = 1; + else + sv = 2; + + if (vecs[1][0]) + tv = 0; + else if (vecs[1][1]) + tv = 1; + else + tv = 2; + + for (i=0 ; i<2 ; i++) + { + ns = cosv * vecs[i][sv] - sinv * vecs[i][tv]; + nt = sinv * vecs[i][sv] + cosv * vecs[i][tv]; + vecs[i][sv] = ns; + vecs[i][tv] = nt; + } + + for (i=0 ; i<2 ; i++) + for (j=0 ; j<3 ; j++) + tx.vecs[i][j] = vecs[i][j] / bt->scale[i]; + + tx.vecs[0][3] = bt->shift[0] + shift[0]; + tx.vecs[1][3] = bt->shift[1] + shift[1]; + tx.flags = bt->flags; + tx.value = bt->value; + + // + // find the texinfo + // + tc = texinfo; + for (i=0 ; iflags != tx.flags) + continue; + if (tc->value != tx.value) + continue; + for (j=0 ; j<2 ; j++) + { + if (strcmp (tc->texture, tx.texture)) + goto skip; + for (k=0 ; k<4 ; k++) + { + if (tc->vecs[j][k] != tx.vecs[j][k]) + goto skip; + } + } + return i; +skip:; + } + *tc = tx; + numtexinfo++; + + // load the next animation + mt = FindMiptex (bt->name); + if (textureref[mt].animname[0]) + { + anim = *bt; + strcpy (anim.name, textureref[mt].animname); + tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin); + } + else + tc->nexttexinfo = -1; + + + return i; +} diff --git a/tools/quake2/extra/bsp/qbsp3/tree.c b/tools/quake2/extra/bsp/qbsp3/tree.c new file mode 100644 index 00000000..a6c1f34c --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/tree.c @@ -0,0 +1,219 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "qbsp.h" + +extern int c_nodes; + +void RemovePortalFromNode (portal_t *portal, node_t *l); + +node_t *NodeForPoint (node_t *node, vec3_t origin) +{ + plane_t *plane; + vec_t d; + + while (node->planenum != PLANENUM_LEAF) + { + plane = &mapplanes[node->planenum]; + d = DotProduct (origin, plane->normal) - plane->dist; + if (d >= 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return node; +} + + + +/* +============= +FreeTreePortals_r +============= +*/ +void FreeTreePortals_r (node_t *node) +{ + portal_t *p, *nextp; + int s; + + // free children + if (node->planenum != PLANENUM_LEAF) + { + FreeTreePortals_r (node->children[0]); + FreeTreePortals_r (node->children[1]); + } + + // free portals + for (p=node->portals ; p ; p=nextp) + { + s = (p->nodes[1] == node); + nextp = p->next[s]; + + RemovePortalFromNode (p, p->nodes[!s]); + FreePortal (p); + } + node->portals = NULL; +} + +/* +============= +FreeTree_r +============= +*/ +void FreeTree_r (node_t *node) +{ + face_t *f, *nextf; + + // free children + if (node->planenum != PLANENUM_LEAF) + { + FreeTree_r (node->children[0]); + FreeTree_r (node->children[1]); + } + + // free bspbrushes + FreeBrushList (node->brushlist); + + // free faces + for (f=node->faces ; f ; f=nextf) + { + nextf = f->next; + FreeFace (f); + } + + // free the node + if (node->volume) + FreeBrush (node->volume); + + if (numthreads == 1) + c_nodes--; + free (node); +} + + +/* +============= +FreeTree +============= +*/ +void FreeTree (tree_t *tree) +{ + FreeTreePortals_r (tree->headnode); + FreeTree_r (tree->headnode); + free (tree); +} + +//=============================================================== + +void PrintTree_r (node_t *node, int depth) +{ + int i; + plane_t *plane; + bspbrush_t *bb; + + for (i=0 ; iplanenum == PLANENUM_LEAF) + { + if (!node->brushlist) + printf ("NULL\n"); + else + { + for (bb=node->brushlist ; bb ; bb=bb->next) + printf ("%i ", bb->original->brushnum); + printf ("\n"); + } + return; + } + + plane = &mapplanes[node->planenum]; + printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum, + plane->normal[0], plane->normal[1], plane->normal[2], + plane->dist); + PrintTree_r (node->children[0], depth+1); + PrintTree_r (node->children[1], depth+1); +} + +/* +========================================================= + +NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED + +========================================================= +*/ + +int c_pruned; + +/* +============ +PruneNodes_r +============ +*/ +void PruneNodes_r (node_t *node) +{ + bspbrush_t *b, *next; + + if (node->planenum == PLANENUM_LEAF) + return; + PruneNodes_r (node->children[0]); + PruneNodes_r (node->children[1]); + + if ( (node->children[0]->contents & CONTENTS_SOLID) + && (node->children[1]->contents & CONTENTS_SOLID) ) + { + if (node->faces) + Error ("node->faces seperating CONTENTS_SOLID"); + if (node->children[0]->faces || node->children[1]->faces) + Error ("!node->faces with children"); + + // FIXME: free stuff + node->planenum = PLANENUM_LEAF; + node->contents = CONTENTS_SOLID; + node->detail_seperator = false; + + if (node->brushlist) + Error ("PruneNodes: node->brushlist"); + + // combine brush lists + node->brushlist = node->children[1]->brushlist; + + for (b=node->children[0]->brushlist ; b ; b=next) + { + next = b->next; + b->next = node->brushlist; + node->brushlist = b; + } + + c_pruned++; + } +} + + +void PruneNodes (node_t *node) +{ + qprintf ("--- PruneNodes ---\n"); + c_pruned = 0; + PruneNodes_r (node); + qprintf ("%5i pruned nodes\n", c_pruned); +} + +//=========================================================== diff --git a/tools/quake2/extra/bsp/qbsp3/writebsp.c b/tools/quake2/extra/bsp/qbsp3/writebsp.c new file mode 100644 index 00000000..cc5c3266 --- /dev/null +++ b/tools/quake2/extra/bsp/qbsp3/writebsp.c @@ -0,0 +1,590 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "qbsp.h" + +int c_nofaces; +int c_facenodes; + + +/* +========================================================= + +ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES + +========================================================= +*/ + +int planeused[MAX_MAP_PLANES]; + +/* +============ +EmitPlanes + +There is no oportunity to discard planes, because all of the original +brushes will be saved in the map. +============ +*/ +void EmitPlanes (void) +{ + int i; + dplane_t *dp; + plane_t *mp; + int planetranslate[MAX_MAP_PLANES]; + + mp = mapplanes; + for (i=0 ; inormal, dp->normal); + dp->dist = mp->dist; + dp->type = mp->type; + numplanes++; + } +} + + +//======================================================== + +void EmitMarkFace (dleaf_t *leaf_p, face_t *f) +{ + int i; + int facenum; + + while (f->merged) + f = f->merged; + + if (f->split[0]) + { + EmitMarkFace (leaf_p, f->split[0]); + EmitMarkFace (leaf_p, f->split[1]); + return; + } + + facenum = f->outputnumber; + if (facenum == -1) + return; // degenerate face + + if (facenum < 0 || facenum >= numfaces) + Error ("Bad leafface"); + for (i=leaf_p->firstleafface ; i= MAX_MAP_LEAFFACES) + Error ("MAX_MAP_LEAFFACES"); + + dleaffaces[numleaffaces] = facenum; + numleaffaces++; + } + +} + + +/* +================== +EmitLeaf +================== +*/ +void EmitLeaf (node_t *node) +{ + dleaf_t *leaf_p; + portal_t *p; + int s; + face_t *f; + bspbrush_t *b; + int i; + int brushnum; + + // emit a leaf + if (numleafs >= MAX_MAP_LEAFS) + Error ("MAX_MAP_LEAFS"); + + leaf_p = &dleafs[numleafs]; + numleafs++; + + leaf_p->contents = node->contents; + leaf_p->cluster = node->cluster; + leaf_p->area = node->area; + + // + // write bounding box info + // + VectorCopy (node->mins, leaf_p->mins); + VectorCopy (node->maxs, leaf_p->maxs); + + // + // write the leafbrushes + // + leaf_p->firstleafbrush = numleafbrushes; + for (b=node->brushlist ; b ; b=b->next) + { + if (numleafbrushes >= MAX_MAP_LEAFBRUSHES) + Error ("MAX_MAP_LEAFBRUSHES"); + + brushnum = b->original - mapbrushes; + for (i=leaf_p->firstleafbrush ; inumleafbrushes = numleafbrushes - leaf_p->firstleafbrush; + + // + // write the leaffaces + // + if (leaf_p->contents & CONTENTS_SOLID) + return; // no leaffaces in solids + + leaf_p->firstleafface = numleaffaces; + + for (p = node->portals ; p ; p = p->next[s]) + { + s = (p->nodes[1] == node); + f = p->face[s]; + if (!f) + continue; // not a visible portal + + EmitMarkFace (leaf_p, f); + } + + leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface; +} + + +/* +================== +EmitFace +================== +*/ +void EmitFace (face_t *f) +{ + dface_t *df; + int i; + int e; + + f->outputnumber = -1; + + if (f->numpoints < 3) + { + return; // degenerated + } + if (f->merged || f->split[0] || f->split[1]) + { + return; // not a final face + } + + // save output number so leaffaces can use + f->outputnumber = numfaces; + + if (numfaces >= MAX_MAP_FACES) + Error ("numfaces == MAX_MAP_FACES"); + df = &dfaces[numfaces]; + numfaces++; + + // planenum is used by qlight, but not quake + df->planenum = f->planenum & (~1); + df->side = f->planenum & 1; + + df->firstedge = numsurfedges; + df->numedges = f->numpoints; + df->texinfo = f->texinfo; + for (i=0 ; inumpoints ; i++) + { +// e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f); + e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f); + if (numsurfedges >= MAX_MAP_SURFEDGES) + Error ("numsurfedges == MAX_MAP_SURFEDGES"); + dsurfedges[numsurfedges] = e; + numsurfedges++; + } +} + +/* +============ +EmitDrawingNode_r +============ +*/ +int EmitDrawNode_r (node_t *node) +{ + dnode_t *n; + face_t *f; + int i; + + if (node->planenum == PLANENUM_LEAF) + { + EmitLeaf (node); + return -numleafs; + } + + // emit a node + if (numnodes == MAX_MAP_NODES) + Error ("MAX_MAP_NODES"); + n = &dnodes[numnodes]; + numnodes++; + + VectorCopy (node->mins, n->mins); + VectorCopy (node->maxs, n->maxs); + + planeused[node->planenum]++; + planeused[node->planenum^1]++; + + if (node->planenum & 1) + Error ("WriteDrawNodes_r: odd planenum"); + n->planenum = node->planenum; + n->firstface = numfaces; + + if (!node->faces) + c_nofaces++; + else + c_facenodes++; + + for (f=node->faces ; f ; f=f->next) + EmitFace (f); + + n->numfaces = numfaces - n->firstface; + + + // + // recursively output the other nodes + // + for (i=0 ; i<2 ; i++) + { + if (node->children[i]->planenum == PLANENUM_LEAF) + { + n->children[i] = -(numleafs + 1); + EmitLeaf (node->children[i]); + } + else + { + n->children[i] = numnodes; + EmitDrawNode_r (node->children[i]); + } + } + + return n - dnodes; +} + +//========================================================= + + +/* +============ +WriteBSP +============ +*/ +void WriteBSP (node_t *headnode) +{ + int oldfaces; + + c_nofaces = 0; + c_facenodes = 0; + + qprintf ("--- WriteBSP ---\n"); + + oldfaces = numfaces; + dmodels[nummodels].headnode = EmitDrawNode_r (headnode); + EmitAreaPortals (headnode); + + qprintf ("%5i nodes with faces\n", c_facenodes); + qprintf ("%5i nodes without faces\n", c_nofaces); + qprintf ("%5i faces\n", numfaces-oldfaces); +} + +//=========================================================== + +/* +============ +SetModelNumbers +============ +*/ +void SetModelNumbers (void) +{ + int i; + int models; + char value[10]; + + models = 1; + for (i=1 ; icontents = b->contents; + db->firstside = numbrushsides; + db->numsides = b->numsides; + for (j=0 ; jnumsides ; j++) + { + if (numbrushsides == MAX_MAP_BRUSHSIDES) + Error ("MAX_MAP_BRUSHSIDES"); + cp = &dbrushsides[numbrushsides]; + numbrushsides++; + cp->planenum = b->original_sides[j].planenum; + cp->texinfo = b->original_sides[j].texinfo; + } + + // add any axis planes not contained in the brush to bevel off corners + for (x=0 ; x<3 ; x++) + for (s=-1 ; s<=1 ; s+=2) + { + // add the plane + VectorCopy (vec3_origin, normal); + normal[x] = s; + if (s == -1) + dist = -b->mins[x]; + else + dist = b->maxs[x]; + planenum = FindFloatPlane (normal, dist); + for (i=0 ; inumsides ; i++) + if (b->original_sides[i].planenum == planenum) + break; + if (i == b->numsides) + { + if (numbrushsides >= MAX_MAP_BRUSHSIDES) + Error ("MAX_MAP_BRUSHSIDES"); + + dbrushsides[numbrushsides].planenum = planenum; + dbrushsides[numbrushsides].texinfo = + dbrushsides[numbrushsides-1].texinfo; + numbrushsides++; + db->numsides++; + } + } + + } + +} + +//=========================================================== + +/* +================== +BeginBSPFile +================== +*/ +void BeginBSPFile (void) +{ + // these values may actually be initialized + // if the file existed when loaded, so clear them explicitly + nummodels = 0; + numfaces = 0; + numnodes = 0; + numbrushsides = 0; + numvertexes = 0; + numleaffaces = 0; + numleafbrushes = 0; + numsurfedges = 0; + + // edge 0 is not used, because 0 can't be negated + numedges = 1; + + // leave vertex 0 as an error + numvertexes = 1; + + // leave leaf 0 as an error + numleafs = 1; + dleafs[0].contents = CONTENTS_SOLID; +} + + +/* +============ +EndBSPFile +============ +*/ +void EndBSPFile (void) +{ + char path[1024]; + int len; + byte *buf; + + + EmitBrushes (); + EmitPlanes (); + UnparseEntities (); + + // load the pop +#if 0 + sprintf (path, "%s/pics/pop.lmp", gamedir); + len = LoadFile (path, &buf); + memcpy (dpop, buf, sizeof(dpop)); + free (buf); +#endif + + // write the map + sprintf (path, "%s.bsp", source); + printf ("Writing %s\n", path); + WriteBSPFile (path); +} + + +/* +================== +BeginModel +================== +*/ +int firstmodleaf; +extern int firstmodeledge; +extern int firstmodelface; +void BeginModel (void) +{ + dmodel_t *mod; + int start, end; + mapbrush_t *b; + int j; + entity_t *e; + vec3_t mins, maxs; + + if (nummodels == MAX_MAP_MODELS) + Error ("MAX_MAP_MODELS"); + mod = &dmodels[nummodels]; + + mod->firstface = numfaces; + + firstmodleaf = numleafs; + firstmodeledge = numedges; + firstmodelface = numfaces; + + // + // bound the brushes + // + e = &entities[entity_num]; + + start = e->firstbrush; + end = start + e->numbrushes; + ClearBounds (mins, maxs); + + for (j=start ; jnumsides) + continue; // not a real brush (origin brush) + AddPointToBounds (b->mins, mins, maxs); + AddPointToBounds (b->maxs, mins, maxs); + } + + VectorCopy (mins, mod->mins); + VectorCopy (maxs, mod->maxs); +} + + +/* +================== +EndModel +================== +*/ +void EndModel (void) +{ + dmodel_t *mod; + + mod = &dmodels[nummodels]; + + mod->numfaces = numfaces - mod->firstface; + + nummodels++; +} + diff --git a/tools/quake2/extra/bsp/qrad3/lightmap.c b/tools/quake2/extra/bsp/qrad3/lightmap.c new file mode 100644 index 00000000..e6a5aaaa --- /dev/null +++ b/tools/quake2/extra/bsp/qrad3/lightmap.c @@ -0,0 +1,1316 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "qrad.h" + +#define MAX_LSTYLES 256 + +typedef struct +{ + dface_t *faces[2]; + qboolean coplanar; +} edgeshare_t; + +edgeshare_t edgeshare[MAX_MAP_EDGES]; + +int facelinks[MAX_MAP_FACES]; +int planelinks[2][MAX_MAP_PLANES]; + +/* +============ +LinkPlaneFaces +============ +*/ +void LinkPlaneFaces (void) +{ + int i; + dface_t *f; + + f = dfaces; + for (i=0 ; iside][f->planenum]; + planelinks[f->side][f->planenum] = i; + } +} + +/* +============ +PairEdges +============ +*/ +void PairEdges (void) +{ + int i, j, k; + dface_t *f; + edgeshare_t *e; + + f = dfaces; + for (i=0 ; inumedges ; j++) + { + k = dsurfedges[f->firstedge + j]; + if (k < 0) + { + e = &edgeshare[-k]; + e->faces[1] = f; + } + else + { + e = &edgeshare[k]; + e->faces[0] = f; + } + + if (e->faces[0] && e->faces[1]) + { + // determine if coplanar + if (e->faces[0]->planenum == e->faces[1]->planenum) + e->coplanar = true; + } + } + } +} + +/* +================================================================= + + POINT TRIANGULATION + +================================================================= +*/ + +typedef struct triedge_s +{ + int p0, p1; + vec3_t normal; + vec_t dist; + struct triangle_s *tri; +} triedge_t; + +typedef struct triangle_s +{ + triedge_t *edges[3]; +} triangle_t; + +#define MAX_TRI_POINTS 1024 +#define MAX_TRI_EDGES (MAX_TRI_POINTS*6) +#define MAX_TRI_TRIS (MAX_TRI_POINTS*2) + +typedef struct +{ + int numpoints; + int numedges; + int numtris; + dplane_t *plane; + triedge_t *edgematrix[MAX_TRI_POINTS][MAX_TRI_POINTS]; + patch_t *points[MAX_TRI_POINTS]; + triedge_t edges[MAX_TRI_EDGES]; + triangle_t tris[MAX_TRI_TRIS]; +} triangulation_t; + +/* +=============== +AllocTriangulation +=============== +*/ +triangulation_t *AllocTriangulation (dplane_t *plane) +{ + triangulation_t *t; + + t = malloc(sizeof(triangulation_t)); + t->numpoints = 0; + t->numedges = 0; + t->numtris = 0; + + t->plane = plane; + +// memset (t->edgematrix, 0, sizeof(t->edgematrix)); + + return t; +} + +/* +=============== +FreeTriangulation +=============== +*/ +void FreeTriangulation (triangulation_t *tr) +{ + free (tr); +} + + +triedge_t *FindEdge (triangulation_t *trian, int p0, int p1) +{ + triedge_t *e, *be; + vec3_t v1; + vec3_t normal; + vec_t dist; + + if (trian->edgematrix[p0][p1]) + return trian->edgematrix[p0][p1]; + + if (trian->numedges > MAX_TRI_EDGES-2) + Error ("trian->numedges > MAX_TRI_EDGES-2"); + + VectorSubtract (trian->points[p1]->origin, trian->points[p0]->origin, v1); + VectorNormalize (v1, v1); + CrossProduct (v1, trian->plane->normal, normal); + dist = DotProduct (trian->points[p0]->origin, normal); + + e = &trian->edges[trian->numedges]; + e->p0 = p0; + e->p1 = p1; + e->tri = NULL; + VectorCopy (normal, e->normal); + e->dist = dist; + trian->numedges++; + trian->edgematrix[p0][p1] = e; + + be = &trian->edges[trian->numedges]; + be->p0 = p1; + be->p1 = p0; + be->tri = NULL; + VectorSubtract (vec3_origin, normal, be->normal); + be->dist = -dist; + trian->numedges++; + trian->edgematrix[p1][p0] = be; + + return e; +} + +triangle_t *AllocTriangle (triangulation_t *trian) +{ + triangle_t *t; + + if (trian->numtris >= MAX_TRI_TRIS) + Error ("trian->numtris >= MAX_TRI_TRIS"); + + t = &trian->tris[trian->numtris]; + trian->numtris++; + + return t; +} + +/* +============ +TriEdge_r +============ +*/ +void TriEdge_r (triangulation_t *trian, triedge_t *e) +{ + int i, bestp; + vec3_t v1, v2; + vec_t *p0, *p1, *p; + vec_t best, ang; + triangle_t *nt; + + if (e->tri) + return; // allready connected by someone + + // find the point with the best angle + p0 = trian->points[e->p0]->origin; + p1 = trian->points[e->p1]->origin; + best = 1.1; + for (i=0 ; i< trian->numpoints ; i++) + { + p = trian->points[i]->origin; + // a 0 dist will form a degenerate triangle + if (DotProduct(p, e->normal) - e->dist < 0) + continue; // behind edge + VectorSubtract (p0, p, v1); + VectorSubtract (p1, p, v2); + if (!VectorNormalize (v1,v1)) + continue; + if (!VectorNormalize (v2,v2)) + continue; + ang = DotProduct (v1, v2); + if (ang < best) + { + best = ang; + bestp = i; + } + } + if (best >= 1) + return; // edge doesn't match anything + + // make a new triangle + nt = AllocTriangle (trian); + nt->edges[0] = e; + nt->edges[1] = FindEdge (trian, e->p1, bestp); + nt->edges[2] = FindEdge (trian, bestp, e->p0); + for (i=0 ; i<3 ; i++) + nt->edges[i]->tri = nt; + TriEdge_r (trian, FindEdge (trian, bestp, e->p1)); + TriEdge_r (trian, FindEdge (trian, e->p0, bestp)); +} + +/* +============ +TriangulatePoints +============ +*/ +void TriangulatePoints (triangulation_t *trian) +{ + vec_t d, bestd; + vec3_t v1; + int bp1, bp2, i, j; + vec_t *p1, *p2; + triedge_t *e, *e2; + + if (trian->numpoints < 2) + return; + + // find the two closest points + bestd = 9999; + for (i=0 ; inumpoints ; i++) + { + p1 = trian->points[i]->origin; + for (j=i+1 ; jnumpoints ; j++) + { + p2 = trian->points[j]->origin; + VectorSubtract (p2, p1, v1); + d = VectorLength (v1); + if (d < bestd) + { + bestd = d; + bp1 = i; + bp2 = j; + } + } + } + + e = FindEdge (trian, bp1, bp2); + e2 = FindEdge (trian, bp2, bp1); + TriEdge_r (trian, e); + TriEdge_r (trian, e2); +} + +/* +=============== +AddPointToTriangulation +=============== +*/ +void AddPointToTriangulation (patch_t *patch, triangulation_t *trian) +{ + int pnum; + + pnum = trian->numpoints; + if (pnum == MAX_TRI_POINTS) + Error ("trian->numpoints == MAX_TRI_POINTS"); + trian->points[pnum] = patch; + trian->numpoints++; +} + +/* +=============== +LerpTriangle +=============== +*/ +void LerpTriangle (triangulation_t *trian, triangle_t *t, vec3_t point, vec3_t color) +{ + patch_t *p1, *p2, *p3; + vec3_t base, d1, d2; + float x, y, x1, y1, x2, y2; + + p1 = trian->points[t->edges[0]->p0]; + p2 = trian->points[t->edges[1]->p0]; + p3 = trian->points[t->edges[2]->p0]; + + VectorCopy (p1->totallight, base); + VectorSubtract (p2->totallight, base, d1); + VectorSubtract (p3->totallight, base, d2); + + x = DotProduct (point, t->edges[0]->normal) - t->edges[0]->dist; + y = DotProduct (point, t->edges[2]->normal) - t->edges[2]->dist; + + x1 = 0; + y1 = DotProduct (p2->origin, t->edges[2]->normal) - t->edges[2]->dist; + + x2 = DotProduct (p3->origin, t->edges[0]->normal) - t->edges[0]->dist; + y2 = 0; + + if (fabs(y1)edges[i]; + d = DotProduct (e->normal, point) - e->dist; + if (d < 0) + return false; // not inside + } + + return true; +} + +/* +=============== +SampleTriangulation +=============== +*/ +void SampleTriangulation (vec3_t point, triangulation_t *trian, vec3_t color) +{ + triangle_t *t; + triedge_t *e; + vec_t d, best; + patch_t *p0, *p1; + vec3_t v1, v2; + int i, j; + + if (trian->numpoints == 0) + { + VectorClear (color); + return; + } + if (trian->numpoints == 1) + { + VectorCopy (trian->points[0]->totallight, color); + return; + } + + // search for triangles + for (t = trian->tris, j=0 ; j < trian->numtris ; t++, j++) + { + if (!PointInTriangle (point, t)) + continue; + + // this is it + LerpTriangle (trian, t, point, color); + return; + } + + // search for exterior edge + for (e=trian->edges, j=0 ; j< trian->numedges ; e++, j++) + { + if (e->tri) + continue; // not an exterior edge + + d = DotProduct (point, e->normal) - e->dist; + if (d < 0) + continue; // not in front of edge + + p0 = trian->points[e->p0]; + p1 = trian->points[e->p1]; + + VectorSubtract (p1->origin, p0->origin, v1); + VectorNormalize (v1, v1); + VectorSubtract (point, p0->origin, v2); + d = DotProduct (v2, v1); + if (d < 0) + continue; + if (d > 1) + continue; + for (i=0 ; i<3 ; i++) + color[i] = p0->totallight[i] + d * (p1->totallight[i] - p0->totallight[i]); + return; + } + + // search for nearest point + best = 99999; + p1 = NULL; + for (j=0 ; jnumpoints ; j++) + { + p0 = trian->points[j]; + VectorSubtract (point, p0->origin, v1); + d = VectorLength (v1); + if (d < best) + { + best = d; + p1 = p0; + } + } + + if (!p1) + Error ("SampleTriangulation: no points"); + + VectorCopy (p1->totallight, color); +} + +/* +================================================================= + + LIGHTMAP SAMPLE GENERATION + +================================================================= +*/ + + +#define SINGLEMAP (64*64*4) + +typedef struct +{ + vec_t facedist; + vec3_t facenormal; + + int numsurfpt; + vec3_t surfpt[SINGLEMAP]; + + vec3_t modelorg; // for origined bmodels + + vec3_t texorg; + vec3_t worldtotex[2]; // s = (world - texorg) . worldtotex[0] + vec3_t textoworld[2]; // world = texorg + s * textoworld[0] + + vec_t exactmins[2], exactmaxs[2]; + + int texmins[2], texsize[2]; + int surfnum; + dface_t *face; +} lightinfo_t; + + +/* +================ +CalcFaceExtents + +Fills in s->texmins[] and s->texsize[] +also sets exactmins[] and exactmaxs[] +================ +*/ +void CalcFaceExtents (lightinfo_t *l) +{ + dface_t *s; + vec_t mins[2], maxs[2], val; + int i,j, e; + dvertex_t *v; + texinfo_t *tex; + vec3_t vt; + + s = l->face; + + mins[0] = mins[1] = 999999; + maxs[0] = maxs[1] = -99999; + + tex = &texinfo[s->texinfo]; + + for (i=0 ; inumedges ; i++) + { + e = dsurfedges[s->firstedge+i]; + if (e >= 0) + v = dvertexes + dedges[e].v[0]; + else + v = dvertexes + dedges[-e].v[1]; + +// VectorAdd (v->point, l->modelorg, vt); + VectorCopy (v->point, vt); + + for (j=0 ; j<2 ; j++) + { + val = DotProduct (vt, tex->vecs[j]) + tex->vecs[j][3]; + if (val < mins[j]) + mins[j] = val; + if (val > maxs[j]) + maxs[j] = val; + } + } + + for (i=0 ; i<2 ; i++) + { + l->exactmins[i] = mins[i]; + l->exactmaxs[i] = maxs[i]; + + mins[i] = floor(mins[i]/16); + maxs[i] = ceil(maxs[i]/16); + + l->texmins[i] = mins[i]; + l->texsize[i] = maxs[i] - mins[i]; + if (l->texsize[0] * l->texsize[1] > SINGLEMAP/4) // div 4 for extrasamples + Error ("Surface to large to map"); + } +} + +/* +================ +CalcFaceVectors + +Fills in texorg, worldtotex. and textoworld +================ +*/ +void CalcFaceVectors (lightinfo_t *l) +{ + texinfo_t *tex; + int i, j; + vec3_t texnormal; + vec_t distscale; + vec_t dist, len; + int w, h; + + tex = &texinfo[l->face->texinfo]; + +// convert from float to double + for (i=0 ; i<2 ; i++) + for (j=0 ; j<3 ; j++) + l->worldtotex[i][j] = tex->vecs[i][j]; + +// calculate a normal to the texture axis. points can be moved along this +// without changing their S/T + texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2] + - tex->vecs[1][2]*tex->vecs[0][1]; + texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0] + - tex->vecs[1][0]*tex->vecs[0][2]; + texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1] + - tex->vecs[1][1]*tex->vecs[0][0]; + VectorNormalize (texnormal, texnormal); + +// flip it towards plane normal + distscale = DotProduct (texnormal, l->facenormal); + if (!distscale) + { + qprintf ("WARNING: Texture axis perpendicular to face\n"); + distscale = 1; + } + if (distscale < 0) + { + distscale = -distscale; + VectorSubtract (vec3_origin, texnormal, texnormal); + } + +// distscale is the ratio of the distance along the texture normal to +// the distance along the plane normal + distscale = 1/distscale; + + for (i=0 ; i<2 ; i++) + { + len = VectorLength (l->worldtotex[i]); + dist = DotProduct (l->worldtotex[i], l->facenormal); + dist *= distscale; + VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]); + VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]); + } + + +// calculate texorg on the texture plane + for (i=0 ; i<3 ; i++) + l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i]; + +// project back to the face plane + dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1; + dist *= distscale; + VectorMA (l->texorg, -dist, texnormal, l->texorg); + + // compensate for org'd bmodels + VectorAdd (l->texorg, l->modelorg, l->texorg); + + // total sample count + h = l->texsize[1]+1; + w = l->texsize[0]+1; + l->numsurfpt = w * h; +} + +/* +================= +CalcPoints + +For each texture aligned grid point, back project onto the plane +to get the world xyz value of the sample point +================= +*/ +void CalcPoints (lightinfo_t *l, float sofs, float tofs) +{ + int i; + int s, t, j; + int w, h, step; + vec_t starts, startt, us, ut; + vec_t *surf; + vec_t mids, midt; + vec3_t facemid; + dleaf_t *leaf; + + surf = l->surfpt[0]; + mids = (l->exactmaxs[0] + l->exactmins[0])/2; + midt = (l->exactmaxs[1] + l->exactmins[1])/2; + + for (j=0 ; j<3 ; j++) + facemid[j] = l->texorg[j] + l->textoworld[0][j]*mids + l->textoworld[1][j]*midt; + + h = l->texsize[1]+1; + w = l->texsize[0]+1; + l->numsurfpt = w * h; + + starts = l->texmins[0]*16; + startt = l->texmins[1]*16; + step = 16; + + + for (t=0 ; ttexorg[j] + l->textoworld[0][j]*us + + l->textoworld[1][j]*ut; + + leaf = PointInLeaf (surf); + if (leaf->contents != CONTENTS_SOLID) + { + if (!TestLine_r (0, facemid, surf)) + break; // got it + } + + // nudge it + if (i & 1) + { + if (us > mids) + { + us -= 8; + if (us < mids) + us = mids; + } + else + { + us += 8; + if (us > mids) + us = mids; + } + } + else + { + if (ut > midt) + { + ut -= 8; + if (ut < midt) + ut = midt; + } + else + { + ut += 8; + if (ut > midt) + ut = midt; + } + } + } + } + } + +} + + +//============================================================== + + + +#define MAX_STYLES 32 +typedef struct +{ + int numsamples; + float *origins; + int numstyles; + int stylenums[MAX_STYLES]; + float *samples[MAX_STYLES]; +} facelight_t; + +directlight_t *directlights[MAX_MAP_LEAFS]; +facelight_t facelight[MAX_MAP_FACES]; +int numdlights; + +/* +================== +FindTargetEntity +================== +*/ +entity_t *FindTargetEntity (char *target) +{ + int i; + char *n; + + for (i=0 ; itotallight[0] < DIRECT_LIGHT + && p->totallight[1] < DIRECT_LIGHT + && p->totallight[2] < DIRECT_LIGHT) + continue; + + numdlights++; + dl = malloc(sizeof(directlight_t)); + memset (dl, 0, sizeof(*dl)); + + VectorCopy (p->origin, dl->origin); + + leaf = PointInLeaf (dl->origin); + cluster = leaf->cluster; + dl->next = directlights[cluster]; + directlights[cluster] = dl; + + dl->type = emit_surface; + VectorCopy (p->plane->normal, dl->normal); + + dl->intensity = ColorNormalize (p->totallight, dl->color); + dl->intensity *= p->area * direct_scale; + VectorClear (p->totallight); // all sent now + } + + // + // entities + // + for (i=0 ; iorigin); + dl->style = FloatForKey (e, "_style"); + if (!dl->style) + dl->style = FloatForKey (e, "style"); + if (dl->style < 0 || dl->style >= MAX_LSTYLES) + dl->style = 0; + + leaf = PointInLeaf (dl->origin); + cluster = leaf->cluster; + + dl->next = directlights[cluster]; + directlights[cluster] = dl; + + intensity = FloatForKey (e, "light"); + if (!intensity) + intensity = FloatForKey (e, "_light"); + if (!intensity) + intensity = 300; + _color = ValueForKey (e, "_color"); + if (_color && _color[1]) + { + sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); + ColorNormalize (dl->color, dl->color); + } + else + dl->color[0] = dl->color[1] = dl->color[2] = 1.0; + dl->intensity = intensity*entity_scale; + dl->type = emit_point; + + target = ValueForKey (e, "target"); + + if (!strcmp (name, "light_spot") || target[0]) + { + dl->type = emit_spotlight; + dl->stopdot = FloatForKey (e, "_cone"); + if (!dl->stopdot) + dl->stopdot = 10; + dl->stopdot = cos(dl->stopdot/180*3.14159); + if (target[0]) + { // point towards target + e2 = FindTargetEntity (target); + if (!e2) + printf ("WARNING: light at (%i %i %i) has missing target\n", + (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); + else + { + GetVectorForKey (e2, "origin", dest); + VectorSubtract (dest, dl->origin, dl->normal); + VectorNormalize (dl->normal, dl->normal); + } + } + else + { // point down angle + angle = FloatForKey (e, "angle"); + if (angle == ANGLE_UP) + { + dl->normal[0] = dl->normal[1] = 0; + dl->normal[2] = 1; + } + else if (angle == ANGLE_DOWN) + { + dl->normal[0] = dl->normal[1] = 0; + dl->normal[2] = -1; + } + else + { + dl->normal[2] = 0; + dl->normal[0] = cos (angle/180*3.14159); + dl->normal[1] = sin (angle/180*3.14159); + } + } + } + } + + qprintf ("%i direct lights\n", numdlights); +} + +/* +============= +GatherSampleLight + +Lightscale is the normalizer for multisampling +============= +*/ +void GatherSampleLight (vec3_t pos, vec3_t normal, + float **styletable, int offset, int mapsize, float lightscale) +{ + int i; + directlight_t *l; + byte pvs[(MAX_MAP_LEAFS+7)/8]; + vec3_t delta; + float dot, dot2; + float dist; + float scale; + float *dest; + + // get the PVS for the pos to limit the number of checks + if (!PvsForOrigin (pos, pvs)) + { + return; + } + + for (i = 0 ; inumclusters ; i++) + { + if ( ! (pvs[ i>>3] & (1<<(i&7))) ) + continue; + + for (l=directlights[i] ; l ; l=l->next) + { + VectorSubtract (l->origin, pos, delta); + dist = VectorNormalize (delta, delta); + dot = DotProduct (delta, normal); + if (dot <= 0.001) + continue; // behind sample surface + + switch (l->type) + { + case emit_point: + // linear falloff + scale = (l->intensity - dist) * dot; + break; + + case emit_surface: + dot2 = -DotProduct (delta, l->normal); + if (dot2 <= 0.001) + goto skipadd; // behind light surface + scale = (l->intensity / (dist*dist) ) * dot * dot2; + break; + + case emit_spotlight: + // linear falloff + dot2 = -DotProduct (delta, l->normal); + if (dot2 <= l->stopdot) + goto skipadd; // outside light cone + scale = (l->intensity - dist) * dot; + break; + default: + Error ("Bad l->type"); + } + + if (TestLine_r (0, pos, l->origin)) + continue; // occluded + + if (scale <= 0) + continue; + + // if this style doesn't have a table yet, allocate one + if (!styletable[l->style]) + { + styletable[l->style] = malloc (mapsize); + memset (styletable[l->style], 0, mapsize); + } + + dest = styletable[l->style] + offset; + // add some light to it + VectorMA (dest, scale*lightscale, l->color, dest); + +skipadd: ; + } + } + +} + +/* +============= +AddSampleToPatch + +Take the sample's collected light and +add it back into the apropriate patch +for the radiosity pass. + +The sample is added to all patches that might include +any part of it. They are counted and averaged, so it +doesn't generate extra light. +============= +*/ +void AddSampleToPatch (vec3_t pos, vec3_t color, int facenum) +{ + patch_t *patch; + vec3_t mins, maxs; + int i; + + if (numbounce == 0) + return; + if (color[0] + color[1] + color[2] < 3) + return; + + for (patch = face_patches[facenum] ; patch ; patch=patch->next) + { + // see if the point is in this patch (roughly) + WindingBounds (patch->winding, mins, maxs); + for (i=0 ; i<3 ; i++) + { + if (mins[i] > pos[i] + 16) + goto nextpatch; + if (maxs[i] < pos[i] - 16) + goto nextpatch; + } + + // add the sample to the patch + patch->samples++; + VectorAdd (patch->samplelight, color, patch->samplelight); +nextpatch:; + } + +} + + +/* +============= +BuildFacelights +============= +*/ +float sampleofs[5][2] = +{ {0,0}, {-0.25, -0.25}, {0.25, -0.25}, {0.25, 0.25}, {-0.25, 0.25} }; + + +void BuildFacelights (int facenum) +{ + dface_t *f; + lightinfo_t l[5]; + float *styletable[MAX_LSTYLES]; + int i, j; + float *spot; + patch_t *patch; + int numsamples; + int tablesize; + facelight_t *fl; + + f = &dfaces[facenum]; + + if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) ) + return; // non-lit texture + + memset (styletable,0, sizeof(styletable)); + + if (extrasamples) + numsamples = 5; + else + numsamples = 1; + for (i=0 ; iplanenum].normal, l[i].facenormal); + l[i].facedist = dplanes[f->planenum].dist; + if (f->side) + { + VectorSubtract (vec3_origin, l[i].facenormal, l[i].facenormal); + l[i].facedist = -l[i].facedist; + } + + // get the origin offset for rotating bmodels + VectorCopy (face_offset[facenum], l[i].modelorg); + + CalcFaceVectors (&l[i]); + CalcFaceExtents (&l[i]); + CalcPoints (&l[i], sampleofs[i][0], sampleofs[i][1]); + } + + tablesize = l[0].numsurfpt * sizeof(vec3_t); + styletable[0] = malloc(tablesize); + memset (styletable[0], 0, tablesize); + + fl = &facelight[facenum]; + fl->numsamples = l[0].numsurfpt; + fl->origins = malloc (tablesize); + memcpy (fl->origins, l[0].surfpt, tablesize); + + for (i=0 ; inext) + { + if (patch->samples) + { + VectorScale (patch->samplelight, 1.0/patch->samples, patch->samplelight); + } + else + { +// printf ("patch with no samples\n"); + } + } + + for (i=0 ; inumstyles == MAX_STYLES) + break; + fl->samples[fl->numstyles] = styletable[i]; + fl->stylenums[fl->numstyles] = i; + fl->numstyles++; + } + + // the light from DIRECT_LIGHTS is sent out, but the + // texture itself should still be full bright + + if (face_patches[facenum]->baselight[0] >= DIRECT_LIGHT || + face_patches[facenum]->baselight[1] >= DIRECT_LIGHT || + face_patches[facenum]->baselight[2] >= DIRECT_LIGHT + ) + { + spot = fl->samples[0]; + for (i=0 ; ibaselight, spot); + } + } +} + + +/* +============= +FinalLightFace + +Add the indirect lighting on top of the direct +lighting and save into final map format +============= +*/ +void FinalLightFace (int facenum) +{ + dface_t *f; + int i, j, k, st; + vec3_t lb; + patch_t *patch; + triangulation_t *trian; + facelight_t *fl; + float minlight; + float max, newmax; + byte *dest; + int pfacenum; + vec3_t facemins, facemaxs; + + f = &dfaces[facenum]; + fl = &facelight[facenum]; + + if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) ) + return; // non-lit texture + + ThreadLock (); + f->lightofs = lightdatasize; + lightdatasize += fl->numstyles*(fl->numsamples*3); + +// add green sentinals between lightmaps +#if 0 +lightdatasize += 64*3; +for (i=0 ; i<64 ; i++) +dlightdata[lightdatasize-(i+1)*3 + 1] = 255; +#endif + + if (lightdatasize > MAX_MAP_LIGHTING) + Error ("MAX_MAP_LIGHTING"); + ThreadUnlock (); + + f->styles[0] = 0; + f->styles[1] = f->styles[2] = f->styles[3] = 0xff; + + // + // set up the triangulation + // + if (numbounce > 0) + { + ClearBounds (facemins, facemaxs); + for (i=0 ; inumedges ; i++) + { + int ednum; + + ednum = dsurfedges[f->firstedge+i]; + if (ednum >= 0) + AddPointToBounds (dvertexes[dedges[ednum].v[0]].point, + facemins, facemaxs); + else + AddPointToBounds (dvertexes[dedges[-ednum].v[1]].point, + facemins, facemaxs); + } + + trian = AllocTriangulation (&dplanes[f->planenum]); + + // for all faces on the plane, add the nearby patches + // to the triangulation + for (pfacenum = planelinks[f->side][f->planenum] + ; pfacenum ; pfacenum = facelinks[pfacenum]) + { + for (patch = face_patches[pfacenum] ; patch ; patch=patch->next) + { + for (i=0 ; i < 3 ; i++) + { + if (facemins[i] - patch->origin[i] > subdiv*2) + break; + if (patch->origin[i] - facemaxs[i] > subdiv*2) + break; + } + if (i != 3) + continue; // not needed for this face + AddPointToTriangulation (patch, trian); + } + } + for (i=0 ; inumpoints ; i++) + memset (trian->edgematrix[i], 0, trian->numpoints*sizeof(trian->edgematrix[0][0]) ); + TriangulatePoints (trian); + } + + // + // sample the triangulation + // + + // _minlight allows models that have faces that would not be + // illuminated to receive a mottled light pattern instead of + // black + minlight = FloatForKey (face_entity[facenum], "_minlight") * 128; + + dest = &dlightdata[f->lightofs]; + + if (fl->numstyles > MAXLIGHTMAPS) + { + fl->numstyles = MAXLIGHTMAPS; + printf ("face with too many lightstyles: (%f %f %f)\n", + face_patches[facenum]->origin[0], + face_patches[facenum]->origin[1], + face_patches[facenum]->origin[2] + ); + } + + for (st=0 ; stnumstyles ; st++) + { + f->styles[st] = fl->stylenums[st]; + for (j=0 ; jnumsamples ; j++) + { + VectorCopy ( (fl->samples[st]+j*3), lb); + if (numbounce > 0 && st == 0) + { + vec3_t add; + + SampleTriangulation (fl->origins + j*3, trian, add); + VectorAdd (lb, add, lb); + } + // add an ambient term if desired + lb[0] += ambient; + lb[1] += ambient; + lb[2] += ambient; + + VectorScale (lb, lightscale, lb); + + // we need to clamp without allowing hue to change + for (k=0 ; k<3 ; k++) + if (lb[k] < 1) + lb[k] = 1; + max = lb[0]; + if (lb[1] > max) + max = lb[1]; + if (lb[2] > max) + max = lb[2]; + newmax = max; + if (newmax < 0) + newmax = 0; // roundoff problems + if (newmax < minlight) + { + newmax = minlight + (rand()%48); + } + if (newmax > maxlight) + newmax = maxlight; + + for (k=0 ; k<3 ; k++) + { + *dest++ = lb[k]*newmax/max; + } + } + } + + if (numbounce > 0) + FreeTriangulation (trian); +} diff --git a/tools/quake2/extra/bsp/qrad3/makefile b/tools/quake2/extra/bsp/qrad3/makefile new file mode 100644 index 00000000..4fb26c14 --- /dev/null +++ b/tools/quake2/extra/bsp/qrad3/makefile @@ -0,0 +1,77 @@ + +CFLAGS = -c +LDFLAGS = +ODIR = baddir + +EXEBASE = qrad3 +EXE = $(ODIR)/qrad3 +all: $(EXE) + +_next: + make "CFLAGS = -c -g -I../../common" "ODIR = next" + +_irix: + make "CFLAGS = -c -Ofast=ip32_10k -I../../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + +_irixdebug: + make "CFLAGS = -c -g -I../../common -Xcpluscomm" "LDFLAGS = " "ODIR = irix" + +_irixinst: + make "CFLAGS = -c -Ofast=ip32_10k -I../../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + +_irixclean: + rm -f irix/*.o irix/$(EXEBASE) + +_osf: + make "CFLAGS = -c -O4 -I../../common -threads" "LDFLAGS = -threads" "ODIR = osf" + +clean: + rm -f irix/*.o irix/$(EXEBASE) + +install: + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + + +FILES = $(ODIR)/bspfile.o $(ODIR)/cmdlib.o $(ODIR)/lbmlib.o $(ODIR)/mathlib.o $(ODIR)/scriplib.o $(ODIR)/polylib.o $(ODIR)/qrad3.o $(ODIR)/threads.o $(ODIR)/trace.o $(ODIR)/lightmap.o $(ODIR)/patches.o + +$(EXE) : $(FILES) + cc -o $(EXE) $(LDFLAGS) $(FILES) -lm + +$(ODIR)/qrad3.o : qrad3.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/patches.o : patches.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/trace.o : trace.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/vismat.o : vismat.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/lightmap.o : lightmap.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmdlib.o : ../../common/cmdlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/lbmlib.o : ../../common/lbmlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/mathlib.o : ../../common/mathlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/polylib.o : ../../common/polylib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/scriplib.o : ../../common/scriplib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/threads.o : ../../common/threads.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/bspfile.o : ../../common/bspfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i diff --git a/tools/quake2/extra/bsp/qrad3/patches.c b/tools/quake2/extra/bsp/qrad3/patches.c new file mode 100644 index 00000000..fbae0c32 --- /dev/null +++ b/tools/quake2/extra/bsp/qrad3/patches.c @@ -0,0 +1,515 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qrad.h" + +vec3_t texture_reflectivity[MAX_MAP_TEXINFO]; + +/* +=================================================================== + + TEXTURE LIGHT VALUES + +=================================================================== +*/ + +/* +====================== +CalcTextureReflectivity +====================== +*/ +void CalcTextureReflectivity (void) +{ + int i; + int j, k, texels; + int color[3]; + int texel; + byte *palette; + char path[1024]; + float r, scale; + miptex_t *mt; + + sprintf (path, "%spics/colormap.pcx", gamedir); + + // get the game palette + Load256Image (path, NULL, &palette, NULL, NULL); + + // allways set index 0 even if no textures + texture_reflectivity[0][0] = 0.5; + texture_reflectivity[0][1] = 0.5; + texture_reflectivity[0][2] = 0.5; + + for (i=0 ; iwidth)*LittleLong(mt->height); + color[0] = color[1] = color[2] = 0; + + for (j=0 ; joffsets[0]) + j]; + for (k=0 ; k<3 ; k++) + color[k] += palette[texel*3+k]; + } + + for (j=0 ; j<3 ; j++) + { + r = color[j]/texels/255.0; + texture_reflectivity[i][j] = r; + } + // scale the reflectivity up, because the textures are + // so dim + scale = ColorNormalize (texture_reflectivity[i], + texture_reflectivity[i]); + if (scale < 0.5) + { + scale *= 2; + VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]); + } +#if 0 +texture_reflectivity[i][0] = 0.5; +texture_reflectivity[i][1] = 0.5; +texture_reflectivity[i][2] = 0.5; +#endif + } +} + +/* +======================================================================= + +MAKE FACES + +======================================================================= +*/ + +/* +============= +WindingFromFace +============= +*/ +winding_t *WindingFromFace (dface_t *f) +{ + int i; + int se; + dvertex_t *dv; + int v; + winding_t *w; + + w = AllocWinding (f->numedges); + w->numpoints = f->numedges; + + for (i=0 ; inumedges ; i++) + { + se = dsurfedges[f->firstedge + i]; + if (se < 0) + v = dedges[-se].v[1]; + else + v = dedges[se].v[0]; + + dv = &dvertexes[v]; + VectorCopy (dv->point, w->p[i]); + } + + RemoveColinearPoints (w); + + return w; +} + +/* +============= +BaseLightForFace +============= +*/ +void BaseLightForFace (dface_t *f, vec3_t color) +{ + texinfo_t *tx; + + // + // check for light emited by texture + // + tx = &texinfo[f->texinfo]; + if (!(tx->flags & SURF_LIGHT) || tx->value == 0) + { + VectorClear (color); + return; + } + + VectorScale (texture_reflectivity[f->texinfo], tx->value, color); +} + +qboolean IsSky (dface_t *f) +{ + texinfo_t *tx; + + tx = &texinfo[f->texinfo]; + if (tx->flags & SURF_SKY) + return true; + return false; +} + +/* +============= +MakePatchForFace +============= +*/ +float totalarea; +void MakePatchForFace (int fn, winding_t *w) +{ + dface_t *f; + float area; + patch_t *patch; + dplane_t *pl; + int i; + vec3_t color; + dleaf_t *leaf; + + f = &dfaces[fn]; + + area = WindingArea (w); + totalarea += area; + + patch = &patches[num_patches]; + if (num_patches == MAX_PATCHES) + Error ("num_patches == MAX_PATCHES"); + patch->next = face_patches[fn]; + face_patches[fn] = patch; + + patch->winding = w; + + if (f->side) + patch->plane = &backplanes[f->planenum]; + else + patch->plane = &dplanes[f->planenum]; + if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) + { // origin offset faces must create new planes + if (numplanes + fakeplanes >= MAX_MAP_PLANES) + Error ("numplanes + fakeplanes >= MAX_MAP_PLANES"); + pl = &dplanes[numplanes + fakeplanes]; + fakeplanes++; + + *pl = *(patch->plane); + pl->dist += DotProduct (face_offset[fn], pl->normal); + patch->plane = pl; + } + + WindingCenter (w, patch->origin); + VectorAdd (patch->origin, patch->plane->normal, patch->origin); + leaf = PointInLeaf(patch->origin); + patch->cluster = leaf->cluster; + if (patch->cluster == -1) + qprintf ("patch->cluster == -1\n"); + + patch->area = area; + if (patch->area <= 1) + patch->area = 1; + patch->sky = IsSky (f); + + VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity); + + // non-bmodel patches can emit light + if (fn < dmodels[0].numfaces) + { + BaseLightForFace (f, patch->baselight); + + ColorNormalize (patch->reflectivity, color); + + for (i=0 ; i<3 ; i++) + patch->baselight[i] *= color[i]; + + VectorCopy (patch->baselight, patch->totallight); + } + num_patches++; +} + + +entity_t *EntityForModel (int modnum) +{ + int i; + char *s; + char name[16]; + + sprintf (name, "*%i", modnum); + // search the entities for one using modnum + for (i=0 ; inumfaces ; j++) + { + fn = mod->firstface + j; + face_entity[fn] = ent; + VectorCopy (origin, face_offset[fn]); + f = &dfaces[fn]; + w = WindingFromFace (f); + for (k=0 ; knumpoints ; k++) + { + VectorAdd (w->p[k], origin, w->p[k]); + } + MakePatchForFace (fn, w); + } + } + + qprintf ("%i sqaure feet\n", (int)(totalarea/64)); +} + +/* +======================================================================= + +SUBDIVIDE + +======================================================================= +*/ + +void FinishSplit (patch_t *patch, patch_t *newp) +{ + dleaf_t *leaf; + + VectorCopy (patch->baselight, newp->baselight); + VectorCopy (patch->totallight, newp->totallight); + VectorCopy (patch->reflectivity, newp->reflectivity); + newp->plane = patch->plane; + newp->sky = patch->sky; + + patch->area = WindingArea (patch->winding); + newp->area = WindingArea (newp->winding); + + if (patch->area <= 1) + patch->area = 1; + if (newp->area <= 1) + newp->area = 1; + + WindingCenter (patch->winding, patch->origin); + VectorAdd (patch->origin, patch->plane->normal, patch->origin); + leaf = PointInLeaf(patch->origin); + patch->cluster = leaf->cluster; + if (patch->cluster == -1) + qprintf ("patch->cluster == -1\n"); + + WindingCenter (newp->winding, newp->origin); + VectorAdd (newp->origin, newp->plane->normal, newp->origin); + leaf = PointInLeaf(newp->origin); + newp->cluster = leaf->cluster; + if (newp->cluster == -1) + qprintf ("patch->cluster == -1\n"); +} + +/* +============= +SubdividePatch + +Chops the patch only if its local bounds exceed the max size +============= +*/ +void SubdividePatch (patch_t *patch) +{ + winding_t *w, *o1, *o2; + vec3_t mins, maxs, total; + vec3_t split; + vec_t dist; + int i, j; + vec_t v; + patch_t *newp; + + w = patch->winding; + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; + for (i=0 ; inumpoints ; i++) + { + for (j=0 ; j<3 ; j++) + { + v = w->p[i][j]; + if (v < mins[j]) + mins[j] = v; + if (v > maxs[j]) + maxs[j] = v; + } + } + VectorSubtract (maxs, mins, total); + for (i=0 ; i<3 ; i++) + if (total[i] > (subdiv+1) ) + break; + if (i == 3) + { + // no splitting needed + return; + } + + // + // split the winding + // + VectorCopy (vec3_origin, split); + split[i] = 1; + dist = (mins[i] + maxs[i])*0.5; + ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2); + + // + // create a new patch + // + if (num_patches == MAX_PATCHES) + Error ("MAX_PATCHES"); + newp = &patches[num_patches]; + num_patches++; + + newp->next = patch->next; + patch->next = newp; + + patch->winding = o1; + newp->winding = o2; + + FinishSplit (patch, newp); + + SubdividePatch (patch); + SubdividePatch (newp); +} + + +/* +============= +DicePatch + +Chops the patch by a global grid +============= +*/ +void DicePatch (patch_t *patch) +{ + winding_t *w, *o1, *o2; + vec3_t mins, maxs; + vec3_t split; + vec_t dist; + int i; + patch_t *newp; + + w = patch->winding; + WindingBounds (w, mins, maxs); + for (i=0 ; i<3 ; i++) + if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv)) + break; + if (i == 3) + { + // no splitting needed + return; + } + + // + // split the winding + // + VectorCopy (vec3_origin, split); + split[i] = 1; + dist = subdiv*(1+floor((mins[i]+1)/subdiv)); + ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2); + + // + // create a new patch + // + if (num_patches == MAX_PATCHES) + Error ("MAX_PATCHES"); + newp = &patches[num_patches]; + num_patches++; + + newp->next = patch->next; + patch->next = newp; + + patch->winding = o1; + newp->winding = o2; + + FinishSplit (patch, newp); + + DicePatch (patch); + DicePatch (newp); +} + + +/* +============= +SubdividePatches +============= +*/ +void SubdividePatches (void) +{ + int i, num; + + if (subdiv < 1) + return; + + num = num_patches; // because the list will grow + for (i=0 ; i +#endif + +typedef enum +{ + emit_surface, + emit_point, + emit_spotlight +} emittype_t; + + + +typedef struct directlight_s +{ + struct directlight_s *next; + emittype_t type; + + float intensity; + int style; + vec3_t origin; + vec3_t color; + vec3_t normal; // for surfaces and spotlights + float stopdot; // for spotlights +} directlight_t; + + +// the sum of all tranfer->transfer values for a given patch +// should equal exactly 0x10000, showing that all radiance +// reaches other patches +typedef struct +{ + unsigned short patch; + unsigned short transfer; +} transfer_t; + + +#define MAX_PATCHES 65000 // larger will cause 32 bit overflows + +typedef struct patch_s +{ + winding_t *winding; + struct patch_s *next; // next in face + int numtransfers; + transfer_t *transfers; + + int cluster; // for pvs checking + vec3_t origin; + dplane_t *plane; + + qboolean sky; + + vec3_t totallight; // accumulated by radiosity + // does NOT include light + // accounted for by direct lighting + float area; + + // illuminance * reflectivity = radiosity + vec3_t reflectivity; + vec3_t baselight; // emissivity only + + // each style 0 lightmap sample in the patch will be + // added up to get the average illuminance of the entire patch + vec3_t samplelight; + int samples; // for averaging direct light +} patch_t; + +extern patch_t *face_patches[MAX_MAP_FACES]; +extern entity_t *face_entity[MAX_MAP_FACES]; +extern vec3_t face_offset[MAX_MAP_FACES]; // for rotating bmodels +extern patch_t patches[MAX_PATCHES]; +extern unsigned num_patches; + +extern int leafparents[MAX_MAP_LEAFS]; +extern int nodeparents[MAX_MAP_NODES]; + +extern float lightscale; + + +void MakeShadowSplits (void); + +//============================================== + + +void BuildVisMatrix (void); +qboolean CheckVisBit (unsigned p1, unsigned p2); + +//============================================== + +extern float ambient, maxlight; + +void LinkPlaneFaces (void); + +extern qboolean extrasamples; +extern int numbounce; + +extern directlight_t *directlights[MAX_MAP_LEAFS]; + +extern byte nodehit[MAX_MAP_NODES]; + +void BuildLightmaps (void); + +void BuildFacelights (int facenum); + +void FinalLightFace (int facenum); + +qboolean PvsForOrigin (vec3_t org, byte *pvs); + +int TestLine_r (int node, vec3_t start, vec3_t stop); + +void CreateDirectLights (void); + +dleaf_t *PointInLeaf (vec3_t point); + + +extern dplane_t backplanes[MAX_MAP_PLANES]; +extern int fakeplanes; // created planes for origin offset + +extern float subdiv; + +extern float direct_scale; +extern float entity_scale; + +int PointInLeafnum (vec3_t point); +void MakeTnodes (dmodel_t *bm); +void MakePatches (void); +void SubdividePatches (void); +void PairEdges (void); +void CalcTextureReflectivity (void); diff --git a/tools/quake2/extra/bsp/qrad3/qrad3.c b/tools/quake2/extra/bsp/qrad3/qrad3.c new file mode 100644 index 00000000..9c7caddc --- /dev/null +++ b/tools/quake2/extra/bsp/qrad3/qrad3.c @@ -0,0 +1,717 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qrad.h" + + + +/* + +NOTES +----- + +every surface must be divided into at least two patches each axis + +*/ + +patch_t *face_patches[MAX_MAP_FACES]; +entity_t *face_entity[MAX_MAP_FACES]; +patch_t patches[MAX_PATCHES]; +unsigned num_patches; + +vec3_t radiosity[MAX_PATCHES]; // light leaving a patch +vec3_t illumination[MAX_PATCHES]; // light arriving at a patch + +vec3_t face_offset[MAX_MAP_FACES]; // for rotating bmodels +dplane_t backplanes[MAX_MAP_PLANES]; + +char inbase[32], outbase[32]; + +int fakeplanes; // created planes for origin offset + +int numbounce = 8; +qboolean extrasamples; + +float subdiv = 64; +qboolean dumppatches; + +void BuildLightmaps (void); +int TestLine (vec3_t start, vec3_t stop); + +int junk; + +float ambient = 0; +float maxlight = 196; + +float lightscale = 1.0; + +qboolean glview; + +qboolean nopvs; + +char source[1024]; + +float direct_scale = 0.4; +float entity_scale = 1.0; + +/* +=================================================================== + +MISC + +=================================================================== +*/ + + +/* +============= +MakeBackplanes +============= +*/ +void MakeBackplanes (void) +{ + int i; + + for (i=0 ; ichildren[i]; + if (j < 0) + leafparents[-j - 1] = nodenum; + else + MakeParents (j, nodenum); + } +} + + +/* +=================================================================== + +TRANSFER SCALES + +=================================================================== +*/ + +int PointInLeafnum (vec3_t point) +{ + int nodenum; + vec_t dist; + dnode_t *node; + dplane_t *plane; + + nodenum = 0; + while (nodenum >= 0) + { + node = &dnodes[nodenum]; + plane = &dplanes[node->planenum]; + dist = DotProduct (point, plane->normal) - plane->dist; + if (dist > 0) + nodenum = node->children[0]; + else + nodenum = node->children[1]; + } + + return -nodenum - 1; +} + + +dleaf_t *PointInLeaf (vec3_t point) +{ + int num; + + num = PointInLeafnum (point); + return &dleafs[num]; +} + + +qboolean PvsForOrigin (vec3_t org, byte *pvs) +{ + dleaf_t *leaf; + + if (!visdatasize) + { + memset (pvs, 255, (numleafs+7)/8 ); + return true; + } + + leaf = PointInLeaf (org); + if (leaf->cluster == -1) + return false; // in solid leaf + + DecompressVis (dvisdata + dvis->bitofs[leaf->cluster][DVIS_PVS], pvs); + return true; +} + + +/* +============= +MakeTransfers + +============= +*/ +int total_transfer; + +void MakeTransfers (int i) +{ + int j; + vec3_t delta; + vec_t dist, scale; + float trans; + int itrans; + patch_t *patch, *patch2; + float total; + dplane_t plane; + vec3_t origin; + float transfers[MAX_PATCHES], *all_transfers; + int s; + int itotal; + byte pvs[(MAX_MAP_LEAFS+7)/8]; + int cluster; + + patch = patches + i; + total = 0; + + VectorCopy (patch->origin, origin); + plane = *patch->plane; + + if (!PvsForOrigin (patch->origin, pvs)) + return; + + // find out which patch2s will collect light + // from patch + + all_transfers = transfers; + patch->numtransfers = 0; + for (j=0, patch2 = patches ; jcluster; + if (cluster == -1) + continue; + if ( ! ( pvs[cluster>>3] & (1<<(cluster&7)) ) ) + continue; // not in pvs + } + + // calculate vector + VectorSubtract (patch2->origin, origin, delta); + dist = VectorNormalize (delta, delta); + if (!dist) + continue; // should never happen + + // reletive angles + scale = DotProduct (delta, plane.normal); + scale *= -DotProduct (delta, patch2->plane->normal); + if (scale <= 0) + continue; + + // check exact tramsfer + if (TestLine_r (0, patch->origin, patch2->origin) ) + continue; + + trans = scale * patch2->area / (dist*dist); + + if (trans < 0) + trans = 0; // rounding errors... + + transfers[j] = trans; + if (trans > 0) + { + total += trans; + patch->numtransfers++; + } + } + + // copy the transfers out and normalize + // total should be somewhere near PI if everything went right + // because partial occlusion isn't accounted for, and nearby + // patches have underestimated form factors, it will usually + // be higher than PI + if (patch->numtransfers) + { + transfer_t *t; + + if (patch->numtransfers < 0 || patch->numtransfers > MAX_PATCHES) + Error ("Weird numtransfers"); + s = patch->numtransfers * sizeof(transfer_t); + patch->transfers = malloc (s); + if (!patch->transfers) + Error ("Memory allocation failure"); + + // + // normalize all transfers so all of the light + // is transfered to the surroundings + // + t = patch->transfers; + itotal = 0; + for (j=0 ; jtransfer = itrans; + t->patch = j; + t++; + } + } + + // don't bother locking around this. not that important. + total_transfer += patch->numtransfers; +} + + +/* +============= +FreeTransfers +============= +*/ +void FreeTransfers (void) +{ + int i; + + for (i=0 ; iwinding; + fprintf (out, "%i\n", w->numpoints); + for (i=0 ; inumpoints ; i++) + { + fprintf (out, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n", + w->p[i][0], + w->p[i][1], + w->p[i][2], + patch->totallight[0], + patch->totallight[1], + patch->totallight[2]); + } + fprintf (out, "\n"); + } + + fclose (out); +} + +/* +============= +WriteGlView +============= +*/ +void WriteGlView (void) +{ + char name[1024]; + FILE *f; + int i, j; + patch_t *p; + winding_t *w; + + strcpy (name, source); + StripExtension (name); + strcat (name, ".glr"); + + f = fopen (name, "w"); + if (!f) + Error ("Couldn't open %s", f); + + for (j=0 ; jwinding; + fprintf (f, "%i\n", w->numpoints); + for (i=0 ; inumpoints ; i++) + { + fprintf (f, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n", + w->p[i][0], + w->p[i][1], + w->p[i][2], + p->totallight[0]/128, + p->totallight[1]/128, + p->totallight[2]/128); + } + fprintf (f, "\n"); + } + + fclose (f); +} + + +//============================================================== + +/* +============= +CollectLight +============= +*/ +float CollectLight (void) +{ + int i, j; + patch_t *patch; + vec_t total; + + total = 0; + + for (i=0, patch=patches ; isky) + { + VectorClear (radiosity[i]); + VectorClear (illumination[i]); + continue; + } + + for (j=0 ; j<3 ; j++) + { + patch->totallight[j] += illumination[i][j] / patch->area; + radiosity[i][j] = illumination[i][j] * patch->reflectivity[j]; + } + + total += radiosity[i][0] + radiosity[i][1] + radiosity[i][2]; + VectorClear (illumination[i]); + } + + return total; +} + + +/* +============= +ShootLight + +Send light out to other patches + Run multi-threaded +============= +*/ +void ShootLight (int patchnum) +{ + int k, l; + transfer_t *trans; + int num; + patch_t *patch; + vec3_t send; + + // this is the amount of light we are distributing + // prescale it so that multiplying by the 16 bit + // transfer values gives a proper output value + for (k=0 ; k<3 ; k++) + send[k] = radiosity[patchnum][k] / 0x10000; + patch = &patches[patchnum]; + + trans = patch->transfers; + num = patch->numtransfers; + + for (k=0 ; kpatch][l] += send[l]*trans->transfer; + } +} + +/* +============= +BounceLight +============= +*/ +void BounceLight (void) +{ + int i, j; + float added; + char name[64]; + patch_t *p; + + for (i=0 ; itotallight[j] = p->samplelight[j]; + radiosity[i][j] = p->samplelight[j] * p->reflectivity[j] * p->area; + } + } + + for (i=0 ; itotallight[0] < 0 || patch->totallight[1] < 0 || patch->totallight[2] < 0) + Error ("negative patch totallight\n"); + } +} + +/* +============= +RadWorld +============= +*/ +void RadWorld (void) +{ + if (numnodes == 0 || numfaces == 0) + Error ("Empty map"); + MakeBackplanes (); + MakeParents (0, -1); + MakeTnodes (&dmodels[0]); + + // turn each face into a single patch + MakePatches (); + + // subdivide patches to a maximum dimension + SubdividePatches (); + + // create directlights out of patches and lights + CreateDirectLights (); + + // build initial facelights + RunThreadsOnIndividual (numfaces, true, BuildFacelights); + + if (numbounce > 0) + { + // build transfer lists + RunThreadsOnIndividual (num_patches, true, MakeTransfers); + qprintf ("transfer lists: %5.1f megs\n" + , (float)total_transfer * sizeof(transfer_t) / (1024*1024)); + + // spread light around + BounceLight (); + + FreeTransfers (); + + CheckPatches (); + } + + if (glview) + WriteGlView (); + + // blend bounced light into direct light and save + PairEdges (); + LinkPlaneFaces (); + + lightdatasize = 0; + RunThreadsOnIndividual (numfaces, true, FinalLightFace); +} + + +/* +======== +main + +light modelfile +======== +*/ +int main (int argc, char **argv) +{ + int i; + double start, end; + char name[1024]; + + printf ("----- Radiosity ----\n"); + + verbose = false; + + for (i=1 ; i 255) + maxlight = 255; + + if (i != argc - 1) + Error ("usage: qrad [-v] [-chop num] [-scale num] [-ambient num] [-maxlight num] [-threads num] bspfile"); + + start = I_FloatTime (); + + SetQdirFromPath (argv[i]); + strcpy (source, ExpandArg(argv[i])); + StripExtension (source); + DefaultExtension (source, ".bsp"); + +// ReadLightFile (); + + sprintf (name, "%s%s", inbase, source); + printf ("reading %s\n", name); + LoadBSPFile (name); + ParseEntities (); + CalcTextureReflectivity (); + + if (!visdatasize) + { + printf ("No vis information, direct lighting only.\n"); + numbounce = 0; + ambient = 0.1; + } + + RadWorld (); + + sprintf (name, "%s%s", outbase, source); + printf ("writing %s\n", name); + WriteBSPFile (name); + + end = I_FloatTime (); + printf ("%5.0f seconds elapsed\n", end-start); + + return 0; +} + diff --git a/tools/quake2/extra/bsp/qrad3/trace.c b/tools/quake2/extra/bsp/qrad3/trace.c new file mode 100644 index 00000000..bb5f4949 --- /dev/null +++ b/tools/quake2/extra/bsp/qrad3/trace.c @@ -0,0 +1,295 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "bspfile.h" + +#define ON_EPSILON 0.1 + +typedef struct tnode_s +{ + int type; + vec3_t normal; + float dist; + int children[2]; + int pad; +} tnode_t; + +tnode_t *tnodes, *tnode_p; + +/* +============== +MakeTnode + +Converts the disk node structure into the efficient tracing structure +============== +*/ +void MakeTnode (int nodenum) +{ + tnode_t *t; + dplane_t *plane; + int i; + dnode_t *node; + + t = tnode_p++; + + node = dnodes + nodenum; + plane = dplanes + node->planenum; + + t->type = plane->type; + VectorCopy (plane->normal, t->normal); + t->dist = plane->dist; + + for (i=0 ; i<2 ; i++) + { + if (node->children[i] < 0) + t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31); + else + { + t->children[i] = tnode_p - tnodes; + MakeTnode (node->children[i]); + } + } + +} + + +/* +============= +MakeTnodes + +Loads the node structure out of a .bsp file to be used for light occlusion +============= +*/ +void MakeTnodes (dmodel_t *bm) +{ + // 32 byte align the structs + tnodes = malloc( (numnodes+1) * sizeof(tnode_t)); + tnodes = (tnode_t *)(((int)tnodes + 31)&~31); + tnode_p = tnodes; + + MakeTnode (0); +} + + +//========================================================== + + +int TestLine_r (int node, vec3_t start, vec3_t stop) +{ + tnode_t *tnode; + float front, back; + vec3_t mid; + float frac; + int side; + int r; + + if (node & (1<<31)) + return node & ~(1<<31); // leaf node + + tnode = &tnodes[node]; + switch (tnode->type) + { + case PLANE_X: + front = start[0] - tnode->dist; + back = stop[0] - tnode->dist; + break; + case PLANE_Y: + front = start[1] - tnode->dist; + back = stop[1] - tnode->dist; + break; + case PLANE_Z: + front = start[2] - tnode->dist; + back = stop[2] - tnode->dist; + break; + default: + front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist; + back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist; + break; + } + + if (front >= -ON_EPSILON && back >= -ON_EPSILON) + return TestLine_r (tnode->children[0], start, stop); + + if (front < ON_EPSILON && back < ON_EPSILON) + return TestLine_r (tnode->children[1], start, stop); + + side = front < 0; + + frac = front / (front-back); + + mid[0] = start[0] + (stop[0] - start[0])*frac; + mid[1] = start[1] + (stop[1] - start[1])*frac; + mid[2] = start[2] + (stop[2] - start[2])*frac; + + r = TestLine_r (tnode->children[side], start, mid); + if (r) + return r; + return TestLine_r (tnode->children[!side], mid, stop); +} + +int TestLine (vec3_t start, vec3_t stop) +{ + return TestLine_r (0, start, stop); +} + +/* +============================================================================== + +LINE TRACING + +The major lighting operation is a point to point visibility test, performed +by recursive subdivision of the line by the BSP tree. + +============================================================================== +*/ + +typedef struct +{ + vec3_t backpt; + int side; + int node; +} tracestack_t; + + +/* +============== +TestLine +============== +*/ +qboolean _TestLine (vec3_t start, vec3_t stop) +{ + int node; + float front, back; + tracestack_t *tstack_p; + int side; + float frontx,fronty, frontz, backx, backy, backz; + tracestack_t tracestack[64]; + tnode_t *tnode; + + frontx = start[0]; + fronty = start[1]; + frontz = start[2]; + backx = stop[0]; + backy = stop[1]; + backz = stop[2]; + + tstack_p = tracestack; + node = 0; + + while (1) + { + if (node == CONTENTS_SOLID) + { +#if 0 + float d1, d2, d3; + + d1 = backx - frontx; + d2 = backy - fronty; + d3 = backz - frontz; + + if (d1*d1 + d2*d2 + d3*d3 > 1) +#endif + return false; // DONE! + } + + while (node < 0) + { + // pop up the stack for a back side + tstack_p--; + if (tstack_p < tracestack) + return true; + node = tstack_p->node; + + // set the hit point for this plane + + frontx = backx; + fronty = backy; + frontz = backz; + + // go down the back side + + backx = tstack_p->backpt[0]; + backy = tstack_p->backpt[1]; + backz = tstack_p->backpt[2]; + + node = tnodes[tstack_p->node].children[!tstack_p->side]; + } + + tnode = &tnodes[node]; + + switch (tnode->type) + { + case PLANE_X: + front = frontx - tnode->dist; + back = backx - tnode->dist; + break; + case PLANE_Y: + front = fronty - tnode->dist; + back = backy - tnode->dist; + break; + case PLANE_Z: + front = frontz - tnode->dist; + back = backz - tnode->dist; + break; + default: + front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist; + back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist; + break; + } + + if (front > -ON_EPSILON && back > -ON_EPSILON) +// if (front > 0 && back > 0) + { + node = tnode->children[0]; + continue; + } + + if (front < ON_EPSILON && back < ON_EPSILON) +// if (front <= 0 && back <= 0) + { + node = tnode->children[1]; + continue; + } + + side = front < 0; + + front = front / (front-back); + + tstack_p->node = node; + tstack_p->side = side; + tstack_p->backpt[0] = backx; + tstack_p->backpt[1] = backy; + tstack_p->backpt[2] = backz; + + tstack_p++; + + backx = frontx + front*(backx-frontx); + backy = fronty + front*(backy-fronty); + backz = frontz + front*(backz-frontz); + + node = tnode->children[side]; + } +} + + diff --git a/tools/quake2/extra/bsp/qvis3/flow.c b/tools/quake2/extra/bsp/qvis3/flow.c new file mode 100644 index 00000000..66af998e --- /dev/null +++ b/tools/quake2/extra/bsp/qvis3/flow.c @@ -0,0 +1,788 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "vis.h" + +/* + + each portal will have a list of all possible to see from first portal + + if (!thread->portalmightsee[portalnum]) + + portal mightsee + + for p2 = all other portals in leaf + get sperating planes + for all portals that might be seen by p2 + mark as unseen if not present in seperating plane + flood fill a new mightsee + save as passagemightsee + + + void CalcMightSee (leaf_t *leaf, +*/ + +int CountBits (byte *bits, int numbits) +{ + int i; + int c; + + c = 0; + for (i=0 ; i>3] & (1<<(i&7)) ) + c++; + + return c; +} + +int c_fullskip; +int c_portalskip, c_leafskip; +int c_vistest, c_mighttest; + +int c_chop, c_nochop; + +int active; + +void CheckStack (leaf_t *leaf, threaddata_t *thread) +{ + pstack_t *p, *p2; + + for (p=thread->pstack_head.next ; p ; p=p->next) + { +// printf ("="); + if (p->leaf == leaf) + Error ("CheckStack: leaf recursion"); + for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next) + if (p2->leaf == p->leaf) + Error ("CheckStack: late leaf recursion"); + } +// printf ("\n"); +} + + +winding_t *AllocStackWinding (pstack_t *stack) +{ + int i; + + for (i=0 ; i<3 ; i++) + { + if (stack->freewindings[i]) + { + stack->freewindings[i] = 0; + return &stack->windings[i]; + } + } + + Error ("AllocStackWinding: failed"); + + return NULL; +} + +void FreeStackWinding (winding_t *w, pstack_t *stack) +{ + int i; + + i = w - stack->windings; + + if (i<0 || i>2) + return; // not from local + + if (stack->freewindings[i]) + Error ("FreeStackWinding: allready free"); + stack->freewindings[i] = 1; +} + +/* +============== +ChopWinding + +============== +*/ +winding_t *ChopWinding (winding_t *in, pstack_t *stack, plane_t *split) +{ + vec_t dists[128]; + int sides[128]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *neww; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->points[i], split->normal); + dot -= split->dist; + dists[i] = dot; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + + if (!counts[1]) + return in; // completely on front side + + if (!counts[0]) + { + FreeStackWinding (in, stack); + return NULL; + } + + sides[i] = sides[0]; + dists[i] = dists[0]; + + neww = AllocStackWinding (stack); + + neww->numpoints = 0; + + for (i=0 ; inumpoints ; i++) + { + p1 = in->points[i]; + + if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) + { + FreeStackWinding (neww, stack); + return in; // can't chop -- fall back to original + } + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) + { + FreeStackWinding (neww, stack); + return in; // can't chop -- fall back to original + } + + // generate a split point + p2 = in->points[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (split->normal[j] == 1) + mid[j] = split->dist; + else if (split->normal[j] == -1) + mid[j] = -split->dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, neww->points[neww->numpoints]); + neww->numpoints++; + } + +// free the original winding + FreeStackWinding (in, stack); + + return neww; +} + + +/* +============== +ClipToSeperators + +Source, pass, and target are an ordering of portals. + +Generates seperating planes canidates by taking two points from source and one +point from pass, and clips target by them. + +If target is totally clipped away, that portal can not be seen through. + +Normal clip keeps target on the same side as pass, which is correct if the +order goes source, pass, target. If the order goes pass, source, target then +flipclip should be set. +============== +*/ +winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack) +{ + int i, j, k, l; + plane_t plane; + vec3_t v1, v2; + float d; + vec_t length; + int counts[3]; + qboolean fliptest; + +// check all combinations + for (i=0 ; inumpoints ; i++) + { + l = (i+1)%source->numpoints; + VectorSubtract (source->points[l] , source->points[i], v1); + + // fing a vertex of pass that makes a plane that puts all of the + // vertexes of pass on the front side and all of the vertexes of + // source on the back side + for (j=0 ; jnumpoints ; j++) + { + VectorSubtract (pass->points[j], source->points[i], v2); + + plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; + plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; + plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; + + // if points don't make a valid plane, skip it + + length = plane.normal[0] * plane.normal[0] + + plane.normal[1] * plane.normal[1] + + plane.normal[2] * plane.normal[2]; + + if (length < ON_EPSILON) + continue; + + length = 1/sqrt(length); + + plane.normal[0] *= length; + plane.normal[1] *= length; + plane.normal[2] *= length; + + plane.dist = DotProduct (pass->points[j], plane.normal); + + // + // find out which side of the generated seperating plane has the + // source portal + // +#if 1 + fliptest = false; + for (k=0 ; knumpoints ; k++) + { + if (k == i || k == l) + continue; + d = DotProduct (source->points[k], plane.normal) - plane.dist; + if (d < -ON_EPSILON) + { // source is on the negative side, so we want all + // pass and target on the positive side + fliptest = false; + break; + } + else if (d > ON_EPSILON) + { // source is on the positive side, so we want all + // pass and target on the negative side + fliptest = true; + break; + } + } + if (k == source->numpoints) + continue; // planar with source portal +#else + fliptest = flipclip; +#endif + // + // flip the normal if the source portal is backwards + // + if (fliptest) + { + VectorSubtract (vec3_origin, plane.normal, plane.normal); + plane.dist = -plane.dist; + } +#if 1 + // + // if all of the pass portal points are now on the positive side, + // this is the seperating plane + // + counts[0] = counts[1] = counts[2] = 0; + for (k=0 ; knumpoints ; k++) + { + if (k==j) + continue; + d = DotProduct (pass->points[k], plane.normal) - plane.dist; + if (d < -ON_EPSILON) + break; + else if (d > ON_EPSILON) + counts[0]++; + else + counts[2]++; + } + if (k != pass->numpoints) + continue; // points on negative side, not a seperating plane + + if (!counts[0]) + continue; // planar with seperating plane +#else + k = (j+1)%pass->numpoints; + d = DotProduct (pass->points[k], plane.normal) - plane.dist; + if (d < -ON_EPSILON) + continue; + k = (j+pass->numpoints-1)%pass->numpoints; + d = DotProduct (pass->points[k], plane.normal) - plane.dist; + if (d < -ON_EPSILON) + continue; +#endif + // + // flip the normal if we want the back side + // + if (flipclip) + { + VectorSubtract (vec3_origin, plane.normal, plane.normal); + plane.dist = -plane.dist; + } + + // + // clip target by the seperating plane + // + target = ChopWinding (target, stack, &plane); + if (!target) + return NULL; // target is not visible + } + } + + return target; +} + + + +/* +================== +RecursiveLeafFlow + +Flood fill through the leafs +If src_portal is NULL, this is the originating leaf +================== +*/ +void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack) +{ + pstack_t stack; + portal_t *p; + plane_t backplane; + leaf_t *leaf; + int i, j; + long *test, *might, *vis, more; + int pnum; + + thread->c_chains++; + + leaf = &leafs[leafnum]; +// CheckStack (leaf, thread); + + prevstack->next = &stack; + + stack.next = NULL; + stack.leaf = leaf; + stack.portal = NULL; + + might = (long *)stack.mightsee; + vis = (long *)thread->base->portalvis; + +// check all portals for flowing into other leafs + for (i=0 ; inumportals ; i++) + { + p = leaf->portals[i]; + pnum = p - portals; + + if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) + { + continue; // can't possibly see it + } + + // if the portal can't see anything we haven't allready seen, skip it + if (p->status == stat_done) + { + test = (long *)p->portalvis; + } + else + { + test = (long *)p->portalflood; + } + + more = 0; + for (j=0 ; jmightsee)[j] & test[j]; + more |= (might[j] & ~vis[j]); + } + + if (!more && + (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) ) + { // can't see anything new + continue; + } + + // get plane of portal, point normal into the neighbor leaf + stack.portalplane = p->plane; + VectorSubtract (vec3_origin, p->plane.normal, backplane.normal); + backplane.dist = -p->plane.dist; + +// c_portalcheck++; + + stack.portal = p; + stack.next = NULL; + stack.freewindings[0] = 1; + stack.freewindings[1] = 1; + stack.freewindings[2] = 1; + +#if 1 +{ +float d; + + d = DotProduct (p->origin, thread->pstack_head.portalplane.normal); + d -= thread->pstack_head.portalplane.dist; + if (d < -p->radius) + { + continue; + } + else if (d > p->radius) + { + stack.pass = p->winding; + } + else + { + stack.pass = ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); + if (!stack.pass) + continue; + } +} +#else + stack.pass = ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); + if (!stack.pass) + continue; +#endif + + +#if 1 +{ +float d; + + d = DotProduct (thread->base->origin, p->plane.normal); + d -= p->plane.dist; + if (d > p->radius) + { + continue; + } + else if (d < -p->radius) + { + stack.source = prevstack->source; + } + else + { + stack.source = ChopWinding (prevstack->source, &stack, &backplane); + if (!stack.source) + continue; + } +} +#else + stack.source = ChopWinding (prevstack->source, &stack, &backplane); + if (!stack.source) + continue; +#endif + + if (!prevstack->pass) + { // the second leaf can only be blocked if coplanar + + // mark the portal as visible + thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); + + RecursiveLeafFlow (p->leaf, thread, &stack); + continue; + } + + stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack); + if (!stack.pass) + continue; + + stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack); + if (!stack.pass) + continue; + + // mark the portal as visible + thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); + + // flow through it for real + RecursiveLeafFlow (p->leaf, thread, &stack); + } +} + + +/* +=============== +PortalFlow + +generates the portalvis bit vector +=============== +*/ +void PortalFlow (int portalnum) +{ + threaddata_t data; + int i; + portal_t *p; + int c_might, c_can; + + p = sorted_portals[portalnum]; + p->status = stat_working; + + c_might = CountBits (p->portalflood, numportals*2); + + memset (&data, 0, sizeof(data)); + data.base = p; + + data.pstack_head.portal = p; + data.pstack_head.source = p->winding; + data.pstack_head.portalplane = p->plane; + for (i=0 ; iportalflood)[i]; + RecursiveLeafFlow (p->leaf, &data, &data.pstack_head); + + p->status = stat_done; + + c_can = CountBits (p->portalvis, numportals*2); + + qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", + (int)(p - portals), c_might, c_can, data.c_chains); +} + + +/* +=============================================================================== + +This is a rough first-order aproximation that is used to trivially reject some +of the final calculations. + + +Calculates portalfront and portalflood bit vectors + +thinking about: + +typedef struct passage_s +{ + struct passage_s *next; + struct portal_s *to; + stryct sep_s *seperators; + byte *mightsee; +} passage_t; + +typedef struct portal_s +{ + struct passage_s *passages; + int leaf; // leaf portal faces into +} portal_s; + +leaf = portal->leaf +clear +for all portals + + +calc portal visibility + clear bit vector + for all passages + passage visibility + + +for a portal to be visible to a passage, it must be on the front of +all seperating planes, and both portals must be behind the mew portal + +=============================================================================== +*/ + +int c_flood, c_vis; + + +/* +================== +SimpleFlood + +================== +*/ +void SimpleFlood (portal_t *srcportal, int leafnum) +{ + int i; + leaf_t *leaf; + portal_t *p; + int pnum; + + leaf = &leafs[leafnum]; + + for (i=0 ; inumportals ; i++) + { + p = leaf->portals[i]; + pnum = p - portals; + if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) ) + continue; + + if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) ) + continue; + + srcportal->portalflood[pnum>>3] |= (1<<(pnum&7)); + + SimpleFlood (srcportal, p->leaf); + } +} + +/* +============== +BasePortalVis +============== +*/ +void BasePortalVis (int portalnum) +{ + int j, k; + portal_t *tp, *p; + float d; + winding_t *w; + + p = portals+portalnum; + + p->portalfront = malloc (portalbytes); + memset (p->portalfront, 0, portalbytes); + + p->portalflood = malloc (portalbytes); + memset (p->portalflood, 0, portalbytes); + + p->portalvis = malloc (portalbytes); + memset (p->portalvis, 0, portalbytes); + + for (j=0, tp = portals ; jwinding; + for (k=0 ; knumpoints ; k++) + { + d = DotProduct (w->points[k], p->plane.normal) + - p->plane.dist; + if (d > ON_EPSILON) + break; + } + if (k == w->numpoints) + continue; // no points on front + + w = p->winding; + for (k=0 ; knumpoints ; k++) + { + d = DotProduct (w->points[k], tp->plane.normal) + - tp->plane.dist; + if (d < -ON_EPSILON) + break; + } + if (k == w->numpoints) + continue; // no points on front + + p->portalfront[j>>3] |= (1<<(j&7)); + } + + SimpleFlood (p, p->leaf); + + p->nummightsee = CountBits (p->portalflood, numportals*2); +// printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee); + c_flood += p->nummightsee; +} + + + + + +/* +=============================================================================== + +This is a second order aproximation + +Calculates portalvis bit vector + +WAAAAAAY too slow. + +=============================================================================== +*/ + +/* +================== +RecursiveLeafBitFlow + +================== +*/ +void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee) +{ + portal_t *p; + leaf_t *leaf; + int i, j; + long more; + int pnum; + byte newmight[MAX_PORTALS/8]; + + leaf = &leafs[leafnum]; + +// check all portals for flowing into other leafs + for (i=0 ; inumportals ; i++) + { + p = leaf->portals[i]; + pnum = p - portals; + + // if some previous portal can't see it, skip + if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) ) + continue; + + // if this portal can see some portals we mightsee, recurse + more = 0; + for (j=0 ; jportalflood)[j]; + more |= ((long *)newmight)[j] & ~((long *)cansee)[j]; + } + + if (!more) + continue; // can't see anything new + + cansee[pnum>>3] |= (1<<(pnum&7)); + + RecursiveLeafBitFlow (p->leaf, newmight, cansee); + } +} + +/* +============== +BetterPortalVis +============== +*/ +void BetterPortalVis (int portalnum) +{ + portal_t *p; + + p = portals+portalnum; + + RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis); + + // build leaf vis information + p->nummightsee = CountBits (p->portalvis, numportals*2); + c_vis += p->nummightsee; +} + + diff --git a/tools/quake2/extra/bsp/qvis3/makefile b/tools/quake2/extra/bsp/qvis3/makefile new file mode 100644 index 00000000..57946de1 --- /dev/null +++ b/tools/quake2/extra/bsp/qvis3/makefile @@ -0,0 +1,62 @@ + +CFLAGS = -c +LDFLAGS = +ODIR = baddir + +EXEBASE = qvis3 +EXE = $(ODIR)/qvis3 +all: $(EXE) + +_next: + make "CFLAGS = -c -g -I../../common" "ODIR = next" + +_irix: + make "CFLAGS = -c -Ofast=ip32_10k -I../../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + +_irixinst: + make "CFLAGS = -c -Ofast=ip32_10k -I../../common -Xcpluscomm" "LDFLAGS = -Ofast=ip32_10k" "ODIR = irix" + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + +_irixclean: + rm -f irix/*.o irix/$(EXEBASE) + +_osf: + make "CFLAGS = -c -O4 -I../../common -threads" "LDFLAGS = -threads -lm" "ODIR = osf" + +clean: + rm -f irix/*.o irix/$(EXEBASE) + +install: + cp irix/$(EXEBASE) /limbo/quake2/bin_irix + + +FILES = $(ODIR)/bspfile.o $(ODIR)/cmdlib.o $(ODIR)/mathlib.o $(ODIR)/scriplib.o $(ODIR)/threads.o $(ODIR)/qvis3.o $(ODIR)/flow.o + +$(EXE) : $(FILES) + cc -o $(EXE) $(LDFLAGS) $(FILES) + +$(ODIR)/qvis3.o : qvis3.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/flow.o : flow.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmdlib.o : ../../common/cmdlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/mathlib.o : ../../common/mathlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/polylib.o : ../../common/polylib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/scriplib.o : ../../common/scriplib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/threads.o : ../../common/threads.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/bspfile.o : ../../common/bspfile.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i diff --git a/tools/quake2/extra/bsp/qvis3/qvis3.c b/tools/quake2/extra/bsp/qvis3/qvis3.c new file mode 100644 index 00000000..7cc87510 --- /dev/null +++ b/tools/quake2/extra/bsp/qvis3/qvis3.c @@ -0,0 +1,615 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "vis.h" +#include "threads.h" +#include "stdlib.h" + +int numportals; +int portalclusters; + +char inbase[32]; +char outbase[32]; + +portal_t *portals; +leaf_t *leafs; + +int c_portaltest, c_portalpass, c_portalcheck; + +byte *uncompressedvis; + +byte *vismap, *vismap_p, *vismap_end; // past visfile +int originalvismapsize; + +int leafbytes; // (portalclusters+63)>>3 +int leaflongs; + +int portalbytes, portallongs; + +qboolean fastvis; +qboolean nosort; + +int testlevel = 2; + +int totalvis; + +portal_t *sorted_portals[MAX_MAP_PORTALS*2]; + + +//============================================================================= + +void PlaneFromWinding (winding_t *w, plane_t *plane) +{ + vec3_t v1, v2; + +// calc plane + VectorSubtract (w->points[2], w->points[1], v1); + VectorSubtract (w->points[0], w->points[1], v2); + CrossProduct (v2, v1, plane->normal); + VectorNormalize (plane->normal, plane->normal); + plane->dist = DotProduct (w->points[0], plane->normal); +} + + +/* +================== +NewWinding +================== +*/ +winding_t *NewWinding (int points) +{ + winding_t *w; + int size; + + if (points > MAX_POINTS_ON_WINDING) + Error ("NewWinding: %i points", points); + + size = (int)((winding_t *)0)->points[points]; + w = malloc (size); + memset (w, 0, size); + + return w; +} + + + +void pw(winding_t *w) +{ + int i; + for (i=0 ; inumpoints ; i++) + printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]); +} + +void prl(leaf_t *l) +{ + int i; + portal_t *p; + plane_t pl; + + for (i=0 ; inumportals ; i++) + { + p = l->portals[i]; + pl = p->plane; + printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]); + } +} + + +//============================================================================= + +/* +============= +SortPortals + +Sorts the portals from the least complex, so the later ones can reuse +the earlier information. +============= +*/ +int PComp (const void *a, const void *b) +{ + if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee) + return 0; + if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee) + return -1; + return 1; +} +void SortPortals (void) +{ + int i; + + for (i=0 ; i>3] & (1<<(i&7)) ) + { + p = portals+i; + leafbits[p->leaf>>3] |= (1<<(p->leaf&7)); + } + } + + c_leafs = CountBits (leafbits, portalclusters); + + return c_leafs; +} + + +/* +=============== +ClusterMerge + +Merges the portal visibility for a leaf +=============== +*/ +void ClusterMerge (int leafnum) +{ + leaf_t *leaf; + byte portalvector[MAX_PORTALS/8]; + byte uncompressed[MAX_MAP_LEAFS/8]; + byte compressed[MAX_MAP_LEAFS/8]; + int i, j; + int numvis; + byte *dest; + portal_t *p; + int pnum; + + // OR together all the portalvis bits + + memset (portalvector, 0, portalbytes); + leaf = &leafs[leafnum]; + for (i=0 ; inumportals ; i++) + { + p = leaf->portals[i]; + if (p->status != stat_done) + Error ("portal not done"); + for (j=0 ; jportalvis)[j]; + pnum = p - portals; + portalvector[pnum>>3] |= 1<<(pnum&7); + } + + // convert portal bits to leaf bits + numvis = LeafVectorFromPortalVector (portalvector, uncompressed); + + if (uncompressed[leafnum>>3] & (1<<(leafnum&7))) + printf ("WARNING: Leaf portals saw into leaf\n"); + + uncompressed[leafnum>>3] |= (1<<(leafnum&7)); + numvis++; // count the leaf itself + + // save uncompressed for PHS calculation + memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes); + +// +// compress the bit string +// + qprintf ("cluster %4i : %4i visible\n", leafnum, numvis); + totalvis += numvis; + + i = CompressVis (uncompressed, compressed); + + dest = vismap_p; + vismap_p += i; + + if (vismap_p > vismap_end) + Error ("Vismap expansion overflow"); + + dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap; + + memcpy (dest, compressed, i); +} + + +/* +================== +CalcPortalVis +================== +*/ +void CalcPortalVis (void) +{ + int i; + +// fastvis just uses mightsee for a very loose bound + if (fastvis) + { + for (i=0 ; iwinding; + VectorCopy (vec3_origin, total); + for (i=0 ; inumpoints ; i++) + { + VectorAdd (total, w->points[i], total); + } + + for (i=0 ; i<3 ; i++) + total[i] /= w->numpoints; + + bestr = 0; + for (i=0 ; inumpoints ; i++) + { + VectorSubtract (w->points[i], total, dist); + r = VectorLength (dist); + if (r > bestr) + bestr = r; + } + VectorCopy (total, p->origin); + p->radius = bestr; +} + +/* +============ +LoadPortals +============ +*/ +void LoadPortals (char *name) +{ + int i, j; + portal_t *p; + leaf_t *l; + char magic[80]; + FILE *f; + int numpoints; + winding_t *w; + int leafnums[2]; + plane_t plane; + + if (!strcmp(name,"-")) + f = stdin; + else + { + f = fopen(name, "r"); + if (!f) + Error ("LoadPortals: couldn't read %s\n",name); + } + + if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3) + Error ("LoadPortals: failed to read header"); + if (strcmp(magic,PORTALFILE)) + Error ("LoadPortals: not a portal file"); + + printf ("%4i portalclusters\n", portalclusters); + printf ("%4i numportals\n", numportals); + + // these counts should take advantage of 64 bit systems automatically + leafbytes = ((portalclusters+63)&~63)>>3; + leaflongs = leafbytes/sizeof(long); + + portalbytes = ((numportals*2+63)&~63)>>3; + portallongs = portalbytes/sizeof(long); + +// each file portal is split into two memory portals + portals = malloc(2*numportals*sizeof(portal_t)); + memset (portals, 0, 2*numportals*sizeof(portal_t)); + + leafs = malloc(portalclusters*sizeof(leaf_t)); + memset (leafs, 0, portalclusters*sizeof(leaf_t)); + + originalvismapsize = portalclusters*leafbytes; + uncompressedvis = malloc(originalvismapsize); + + vismap = vismap_p = dvisdata; + dvis->numclusters = portalclusters; + vismap_p = (byte *)&dvis->bitofs[portalclusters]; + + vismap_end = vismap + MAX_MAP_VISIBILITY; + + for (i=0, p=portals ; i MAX_POINTS_ON_WINDING) + Error ("LoadPortals: portal %i has too many points", i); + if ( (unsigned)leafnums[0] > portalclusters + || (unsigned)leafnums[1] > portalclusters) + Error ("LoadPortals: reading portal %i", i); + + w = p->winding = NewWinding (numpoints); + w->original = true; + w->numpoints = numpoints; + + for (j=0 ; jpoints[j][k] = v[k]; + } + fscanf (f, "\n"); + + // calc plane + PlaneFromWinding (w, &plane); + + // create forward portal + l = &leafs[leafnums[0]]; + if (l->numportals == MAX_PORTALS_ON_LEAF) + Error ("Leaf with too many portals"); + l->portals[l->numportals] = p; + l->numportals++; + + p->winding = w; + VectorSubtract (vec3_origin, plane.normal, p->plane.normal); + p->plane.dist = -plane.dist; + p->leaf = leafnums[1]; + SetPortalSphere (p); + p++; + + // create backwards portal + l = &leafs[leafnums[1]]; + if (l->numportals == MAX_PORTALS_ON_LEAF) + Error ("Leaf with too many portals"); + l->portals[l->numportals] = p; + l->numportals++; + + p->winding = NewWinding(w->numpoints); + p->winding->numpoints = w->numpoints; + for (j=0 ; jnumpoints ; j++) + { + VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); + } + + p->plane = plane; + p->leaf = leafnums[0]; + SetPortalSphere (p); + p++; + + } + + fclose (f); +} + + +/* +================ +CalcPHS + +Calculate the PHS (Potentially Hearable Set) +by ORing together all the PVS visible from a leaf +================ +*/ +void CalcPHS (void) +{ + int i, j, k, l, index; + int bitbyte; + long *dest, *src; + byte *scan; + int count; + byte uncompressed[MAX_MAP_LEAFS/8]; + byte compressed[MAX_MAP_LEAFS/8]; + + printf ("Building PHS...\n"); + + count = 0; + for (i=0 ; i= portalclusters) + Error ("Bad bit in PVS"); // pad bits should be 0 + src = (long *)(uncompressedvis + index*leafbytes); + dest = (long *)uncompressed; + for (l=0 ; l>3] & (1<<(j&7)) ) + count++; + + // + // compress the bit string + // + j = CompressVis (uncompressed, compressed); + + dest = (long *)vismap_p; + vismap_p += j; + + if (vismap_p > vismap_end) + Error ("Vismap expansion overflow"); + + dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap; + + memcpy (dest, compressed, j); + } + + printf ("Average clusters hearable: %i\n", count/portalclusters); +} + +/* +=========== +main +=========== +*/ +int main (int argc, char **argv) +{ + char portalfile[1024]; + char source[1024]; + char name[1024]; + int i; + double start, end; + + printf ("---- vis ----\n"); + + verbose = false; + for (i=1 ; i>3; + visrow = (dvis->numclusters + 7)>>3; + + for (j=0 ; j>3; + row = (dvis->numclusters+7)>>3; + out = decompressed; + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + if (!c) + Error ("DecompressVis: 0 repeat"); + in += 2; + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); +} + +//============================================================================= + +/* +============= +SwapBSPFile + +Byte swaps all data in a bsp file. +============= +*/ +void SwapBSPFile (qboolean todisk) +{ + int i, j; + dmodel_t *d; + + +// models + for (i=0 ; ifirstface = LittleLong (d->firstface); + d->numfaces = LittleLong (d->numfaces); + d->headnode = LittleLong (d->headnode); + + for (j=0 ; j<3 ; j++) + { + d->mins[j] = LittleFloat(d->mins[j]); + d->maxs[j] = LittleFloat(d->maxs[j]); + d->origin[j] = LittleFloat(d->origin[j]); + } + } + +// +// vertexes +// + for (i=0 ; inumclusters; + else + j = LittleLong(dvis->numclusters); + dvis->numclusters = LittleLong (dvis->numclusters); + for (i=0 ; ibitofs[i][0] = LittleLong (dvis->bitofs[i][0]); + dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]); + } +} + + +dheader_t *header; + +int CopyLump (int lump, void *dest, int size) +{ + int length, ofs; + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % size) + Error ("LoadBSPFile: odd lump size"); + + memcpy (dest, (byte *)header + ofs, length); + + return length / size; +} + +/* +============= +LoadBSPFile +============= +*/ +void LoadBSPFile (char *filename) +{ + int i; + +// +// load the file header +// + LoadFile (filename, (void **)&header); + +// swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + Error ("%s is not a IBSP file", filename); + if (header->version != BSPVERSION) + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + + nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t)); + numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t)); + numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t)); + numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t)); + numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t)); + numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t)); + numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t)); + numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0])); + numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0])); + numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0])); + numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t)); + numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t)); + numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t)); + numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t)); + numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t)); + + visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1); + lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1); + entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1); + + CopyLump (LUMP_POP, dpop, 1); + + free (header); // everything has been copied out + +// +// swap everything +// + SwapBSPFile (false); +} + + +/* +============= +LoadBSPFileTexinfo + +Only loads the texinfo lump, so qdata can scan for textures +============= +*/ +void LoadBSPFileTexinfo (char *filename) +{ + int i; + FILE *f; + int length, ofs; + + header = malloc(sizeof(dheader_t)); + + f = fopen (filename, "rb"); + fread (header, sizeof(dheader_t), 1, f); + +// swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->ident != IDBSPHEADER) + Error ("%s is not a IBSP file", filename); + if (header->version != BSPVERSION) + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + + + length = header->lumps[LUMP_TEXINFO].filelen; + ofs = header->lumps[LUMP_TEXINFO].fileofs; + + fseek (f, ofs, SEEK_SET); + fread (texinfo, length, 1, f); + fclose (f); + + numtexinfo = length / sizeof(texinfo_t); + + free (header); // everything has been copied out + + SwapBSPFile (false); +} + + +//============================================================================ + +FILE *wadfile; +dheader_t outheader; + +void AddLump (int lumpnum, void *data, int len) +{ + lump_t *lump; + + lump = &header->lumps[lumpnum]; + + lump->fileofs = LittleLong( ftell(wadfile) ); + lump->filelen = LittleLong(len); + SafeWrite (wadfile, data, (len+3)&~3); +} + +/* +============= +WriteBSPFile + +Swaps the bsp file in place, so it should not be referenced again +============= +*/ +void WriteBSPFile (char *filename) +{ + header = &outheader; + memset (header, 0, sizeof(dheader_t)); + + SwapBSPFile (true); + + header->ident = LittleLong (IDBSPHEADER); + header->version = LittleLong (BSPVERSION); + + wadfile = SafeOpenWrite (filename); + SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later + + AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t)); + AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t)); + AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t)); + AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t)); + AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t)); + AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t)); + AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t)); + AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t)); + AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0])); + AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0])); + AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0])); + AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t)); + AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t)); + AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t)); + AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t)); + + AddLump (LUMP_LIGHTING, dlightdata, lightdatasize); + AddLump (LUMP_VISIBILITY, dvisdata, visdatasize); + AddLump (LUMP_ENTITIES, dentdata, entdatasize); + AddLump (LUMP_POP, dpop, sizeof(dpop)); + + fseek (wadfile, 0, SEEK_SET); + SafeWrite (wadfile, header, sizeof(dheader_t)); + fclose (wadfile); +} + +//============================================================================ + +/* +============= +PrintBSPFileSizes + +Dumps info about current file +============= +*/ +void PrintBSPFileSizes (void) +{ + if (!num_entities) + ParseEntities (); + + printf ("%5i models %7i\n" + ,nummodels, (int)(nummodels*sizeof(dmodel_t))); + printf ("%5i brushes %7i\n" + ,numbrushes, (int)(numbrushes*sizeof(dbrush_t))); + printf ("%5i brushsides %7i\n" + ,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t))); + printf ("%5i planes %7i\n" + ,numplanes, (int)(numplanes*sizeof(dplane_t))); + printf ("%5i texinfo %7i\n" + ,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t))); + printf ("%5i entdata %7i\n", num_entities, entdatasize); + + printf ("\n"); + + printf ("%5i vertexes %7i\n" + ,numvertexes, (int)(numvertexes*sizeof(dvertex_t))); + printf ("%5i nodes %7i\n" + ,numnodes, (int)(numnodes*sizeof(dnode_t))); + printf ("%5i faces %7i\n" + ,numfaces, (int)(numfaces*sizeof(dface_t))); + printf ("%5i leafs %7i\n" + ,numleafs, (int)(numleafs*sizeof(dleaf_t))); + printf ("%5i leaffaces %7i\n" + ,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0]))); + printf ("%5i leafbrushes %7i\n" + ,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0]))); + printf ("%5i surfedges %7i\n" + ,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0]))); + printf ("%5i edges %7i\n" + ,numedges, (int)(numedges*sizeof(dedge_t))); + printf (" lightdata %7i\n", lightdatasize); + printf (" visdata %7i\n", visdatasize); +} + + +//============================================ + +int num_entities; +entity_t entities[MAX_MAP_ENTITIES]; + +void StripTrailing (char *e) +{ + char *s; + + s = e + strlen(e)-1; + while (s >= e && *s <= 32) + { + *s = 0; + s--; + } +} + +/* +================= +ParseEpair +================= +*/ +epair_t *ParseEpair (void) +{ + epair_t *e; + + e = malloc (sizeof(epair_t)); + memset (e, 0, sizeof(epair_t)); + + if (strlen(token) >= MAX_KEY-1) + Error ("ParseEpar: token too long"); + e->key = copystring(token); + GetToken (false); + if (strlen(token) >= MAX_VALUE-1) + Error ("ParseEpar: token too long"); + e->value = copystring(token); + + // strip trailing spaces + StripTrailing (e->key); + StripTrailing (e->value); + + return e; +} + + +/* +================ +ParseEntity +================ +*/ +qboolean ParseEntity (void) +{ + epair_t *e; + entity_t *mapent; + + if (!GetToken (true)) + return false; + + if (strcmp (token, "{") ) + Error ("ParseEntity: { not found"); + + if (num_entities == MAX_MAP_ENTITIES) + Error ("num_entities == MAX_MAP_ENTITIES"); + + mapent = &entities[num_entities]; + num_entities++; + + do + { + if (!GetToken (true)) + Error ("ParseEntity: EOF without closing brace"); + if (!strcmp (token, "}") ) + break; + e = ParseEpair (); + e->next = mapent->epairs; + mapent->epairs = e; + } while (1); + + return true; +} + +/* +================ +ParseEntities + +Parses the dentdata string into entities +================ +*/ +void ParseEntities (void) +{ + num_entities = 0; + ParseFromMemory (dentdata, entdatasize); + + while (ParseEntity ()) + { + } +} + + +/* +================ +UnparseEntities + +Generates the dentdata string from all the entities +================ +*/ +void UnparseEntities (void) +{ + char *buf, *end; + epair_t *ep; + char line[2048]; + int i; + char key[1024], value[1024]; + + buf = dentdata; + end = buf; + *end = 0; + + for (i=0 ; inext) + { + strcpy (key, ep->key); + StripTrailing (key); + strcpy (value, ep->value); + StripTrailing (value); + + sprintf (line, "\"%s\" \"%s\"\n", key, value); + strcat (end, line); + end += strlen(line); + } + strcat (end,"}\n"); + end += 2; + + if (end > buf + MAX_MAP_ENTSTRING) + Error ("Entity text too long"); + } + entdatasize = end - buf + 1; +} + +void PrintEntity (entity_t *ent) +{ + epair_t *ep; + + printf ("------- entity %p -------\n", ent); + for (ep=ent->epairs ; ep ; ep=ep->next) + { + printf ("%s = %s\n", ep->key, ep->value); + } + +} + +void SetKeyValue (entity_t *ent, char *key, char *value) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + { + free (ep->value); + ep->value = copystring(value); + return; + } + ep = malloc (sizeof(*ep)); + ep->next = ent->epairs; + ent->epairs = ep; + ep->key = copystring(key); + ep->value = copystring(value); +} + +char *ValueForKey (entity_t *ent, char *key) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + return ep->value; + return ""; +} + +vec_t FloatForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atof(k); +} + +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) +{ + char *k; + double v1, v2, v3; + + k = ValueForKey (ent, key); +// scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = v3 = 0; + sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); + vec[0] = v1; + vec[1] = v2; + vec[2] = v3; +} + + diff --git a/tools/quake2/extra/common/bspfile.h b/tools/quake2/extra/common/bspfile.h new file mode 100644 index 00000000..11eeb031 --- /dev/null +++ b/tools/quake2/extra/common/bspfile.h @@ -0,0 +1,129 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qfiles.h" + + +extern int nummodels; +extern dmodel_t dmodels[MAX_MAP_MODELS]; + +extern int visdatasize; +extern byte dvisdata[MAX_MAP_VISIBILITY]; +extern dvis_t *dvis; + +extern int lightdatasize; +extern byte dlightdata[MAX_MAP_LIGHTING]; + +extern int entdatasize; +extern char dentdata[MAX_MAP_ENTSTRING]; + +extern int numleafs; +extern dleaf_t dleafs[MAX_MAP_LEAFS]; + +extern int numplanes; +extern dplane_t dplanes[MAX_MAP_PLANES]; + +extern int numvertexes; +extern dvertex_t dvertexes[MAX_MAP_VERTS]; + +extern int numnodes; +extern dnode_t dnodes[MAX_MAP_NODES]; + +extern int numtexinfo; +extern texinfo_t texinfo[MAX_MAP_TEXINFO]; + +extern int numfaces; +extern dface_t dfaces[MAX_MAP_FACES]; + +extern int numedges; +extern dedge_t dedges[MAX_MAP_EDGES]; + +extern int numleaffaces; +extern unsigned short dleaffaces[MAX_MAP_LEAFFACES]; + +extern int numleafbrushes; +extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES]; + +extern int numsurfedges; +extern int dsurfedges[MAX_MAP_SURFEDGES]; + +extern int numareas; +extern darea_t dareas[MAX_MAP_AREAS]; + +extern int numareaportals; +extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS]; + +extern int numbrushes; +extern dbrush_t dbrushes[MAX_MAP_BRUSHES]; + +extern int numbrushsides; +extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; + +extern byte dpop[256]; + +void DecompressVis (byte *in, byte *decompressed); +int CompressVis (byte *vis, byte *dest); + +void LoadBSPFile (char *filename); +void LoadBSPFileTexinfo (char *filename); // just for qdata +void WriteBSPFile (char *filename); +void PrintBSPFileSizes (void); + +//=============== + + +typedef struct epair_s +{ + struct epair_s *next; + char *key; + char *value; +} epair_t; + +typedef struct +{ + vec3_t origin; + int firstbrush; + int numbrushes; + epair_t *epairs; + +// only valid for func_areaportals + int areaportalnum; + int portalareas[2]; +} entity_t; + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities (void); +void UnparseEntities (void); + +void SetKeyValue (entity_t *ent, char *key, char *value); +char *ValueForKey (entity_t *ent, char *key); +// will return "" if not present + +vec_t FloatForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); + +epair_t *ParseEpair (void); + +void PrintEntity (entity_t *ent); + diff --git a/tools/quake2/extra/common/cmdlib.c b/tools/quake2/extra/common/cmdlib.c new file mode 100644 index 00000000..60f615a0 --- /dev/null +++ b/tools/quake2/extra/common/cmdlib.c @@ -0,0 +1,1055 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// cmdlib.c + +#include "cmdlib.h" +#include +#include + +#ifdef WIN32 +#include +#endif + +#ifdef NeXT +#include +#endif + +#define BASEDIRNAME "quake2" +#define PATHSEPERATOR '/' + +// set these before calling CheckParm +int myargc; +char **myargv; + +char com_token[1024]; +qboolean com_eof; + +qboolean archive; +char archivedir[1024]; + + +/* +=================== +ExpandWildcards + +Mimic unix command line expansion +=================== +*/ +#define MAX_EX_ARGC 1024 +int ex_argc; +char *ex_argv[MAX_EX_ARGC]; +#ifdef _WIN32 +#include "io.h" +void ExpandWildcards (int *argc, char ***argv) +{ + struct _finddata_t fileinfo; + int handle; + int i; + char filename[1024]; + char filebase[1024]; + char *path; + + ex_argc = 0; + for (i=0 ; i<*argc ; i++) + { + path = (*argv)[i]; + if ( path[0] == '-' + || ( !strstr(path, "*") && !strstr(path, "?") ) ) + { + ex_argv[ex_argc++] = path; + continue; + } + + handle = _findfirst (path, &fileinfo); + if (handle == -1) + return; + + ExtractFilePath (path, filebase); + + do + { + sprintf (filename, "%s%s", filebase, fileinfo.name); + ex_argv[ex_argc++] = copystring (filename); + } while (_findnext( handle, &fileinfo ) != -1); + + _findclose (handle); + } + + *argc = ex_argc; + *argv = ex_argv; +} +#else +void ExpandWildcards (int *argc, char ***argv) +{ +} +#endif + +#ifdef WIN_ERROR +#include +/* +================= +Error + +For abnormal program terminations in windowed apps +================= +*/ +void Error (char *error, ...) +{ + va_list argptr; + char text[1024]; + char text2[1024]; + int err; + + err = GetLastError (); + + va_start (argptr,error); + vsprintf (text, error,argptr); + va_end (argptr); + + sprintf (text2, "%s\nGetLastError() = %i", text, err); + MessageBox(NULL, text2, "Error", 0 /* MB_OK */ ); + + exit (1); +} + +#else +/* +================= +Error + +For abnormal program terminations in console apps +================= +*/ +void Error (char *error, ...) +{ + va_list argptr; + + printf ("\n************ ERROR ************\n"); + + va_start (argptr,error); + vprintf (error,argptr); + va_end (argptr); + printf ("\n"); + + exit (1); +} +#endif + +// only printf if in verbose mode +qboolean verbose = false; +void qprintf (char *format, ...) +{ + va_list argptr; + + if (!verbose) + return; + + va_start (argptr,format); + vprintf (format,argptr); + va_end (argptr); +} + + +/* + +qdir will hold the path up to the quake directory, including the slash + + f:\quake\ + /raid/quake/ + +gamedir will hold qdir + the game directory (id1, id2, etc) + + */ + +char qdir[1024]; +char gamedir[1024]; + +void SetQdirFromPath (char *path) +{ + char temp[1024]; + char *c; + int len; + + if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) + { // path is partial + Q_getwd (temp); + strcat (temp, path); + path = temp; + } + + // search for "quake2" in path + + len = strlen(BASEDIRNAME); + for (c=path+strlen(path)-1 ; c != path ; c--) + if (!Q_strncasecmp (c, BASEDIRNAME, len)) + { + strncpy (qdir, path, c+len+1-path); + qprintf ("qdir: %s\n", qdir); + c += len+1; + while (*c) + { + if (*c == '/' || *c == '\\') + { + strncpy (gamedir, path, c+1-path); + qprintf ("gamedir: %s\n", gamedir); + return; + } + c++; + } + Error ("No gamedir in %s", path); + return; + } + Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path); +} + +char *ExpandArg (char *path) +{ + static char full[1024]; + + if (path[0] != '/' && path[0] != '\\' && path[1] != ':') + { + Q_getwd (full); + strcat (full, path); + } + else + strcpy (full, path); + return full; +} + +char *ExpandPath (char *path) +{ + static char full[1024]; + if (!qdir) + Error ("ExpandPath called without qdir set"); + if (path[0] == '/' || path[0] == '\\' || path[1] == ':') + return path; + sprintf (full, "%s%s", qdir, path); + return full; +} + +char *ExpandPathAndArchive (char *path) +{ + char *expanded; + char archivename[1024]; + + expanded = ExpandPath (path); + + if (archive) + { + sprintf (archivename, "%s/%s", archivedir, path); + QCopyFile (expanded, archivename); + } + return expanded; +} + + +char *copystring(char *s) +{ + char *b; + b = malloc(strlen(s)+1); + strcpy (b, s); + return b; +} + + + +/* +================ +I_FloatTime +================ +*/ +double I_FloatTime (void) +{ + time_t t; + + time (&t); + + return t; +#if 0 +// more precise, less portable + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000000.0; + } + + return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; +#endif +} + +void Q_getwd (char *out) +{ +#ifdef WIN32 + _getcwd (out, 256); + strcat (out, "\\"); +#else + getwd (out); + strcat (out, "/"); +#endif +} + + +void Q_mkdir (char *path) +{ +#ifdef WIN32 + if (_mkdir (path) != -1) + return; +#else + if (mkdir (path, 0777) != -1) + return; +#endif + if (errno != EEXIST) + Error ("mkdir %s: %s",path, strerror(errno)); +} + +/* +============ +FileTime + +returns -1 if not present +============ +*/ +int FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + + + +/* +============== +COM_Parse + +Parse a token out of a string +============== +*/ +char *COM_Parse (char *data) +{ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if (!data) + return NULL; + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') + { + if (c == 0) + { + com_eof = true; + return NULL; // end of file; + } + data++; + } + +// skip // comments + if (c=='/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if (c == '\"') + { + data++; + do + { + c = *data++; + if (c=='\"') + { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } while (1); + } + +// parse single characters + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + { + com_token[len] = c; + len++; + com_token[len] = 0; + return data+1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + break; + } while (c>32); + + com_token[len] = 0; + return data; +} + + +int Q_strncasecmp (char *s1, char *s2, int n) +{ + int c1, c2; + + do + { + c1 = *s1++; + c2 = *s2++; + + if (!n--) + return 0; // strings are equal until end point + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + } while (c1); + + return 0; // strings are equal +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return Q_strncasecmp (s1, s2, 99999); +} + + +char *strupr (char *start) +{ + char *in; + in = start; + while (*in) + { + *in = toupper(*in); + in++; + } + return start; +} + +char *strlower (char *start) +{ + char *in; + in = start; + while (*in) + { + *in = tolower(*in); + in++; + } + return start; +} + + +/* +============================================================================= + + MISC FUNCTIONS + +============================================================================= +*/ + + +/* +================= +CheckParm + +Checks for the given parameter in the program's command line arguments +Returns the argument number (1 to argc-1) or 0 if not present +================= +*/ +int CheckParm (char *check) +{ + int i; + + for (i = 1;i 0 && path[length] != PATHSEPERATOR) + length--; + path[length] = 0; +} + +void StripExtension (char *path) +{ + int length; + + length = strlen(path)-1; + while (length > 0 && path[length] != '.') + { + length--; + if (path[length] == '/') + return; // no extension + } + if (length) + path[length] = 0; +} + + +/* +==================== +Extract file parts +==================== +*/ +// FIXME: should include the slash, otherwise +// backing to an empty path will be wrong when appending a slash +void ExtractFilePath (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != '\\' && *(src-1) != '/') + src--; + + memcpy (dest, path, src-path); + dest[src-path] = 0; +} + +void ExtractFileBase (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != PATHSEPERATOR) + src--; + + while (*src && *src != '.') + { + *dest++ = *src++; + } + *dest = 0; +} + +void ExtractFileExtension (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a . or the start +// + while (src != path && *(src-1) != '.') + src--; + if (src == path) + { + *dest = 0; // no extension + return; + } + + strcpy (dest,src); +} + + +/* +============== +ParseNum / ParseHex +============== +*/ +int ParseHex (char *hex) +{ + char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + Error ("Bad hex number: %s",hex); + str++; + } + + return num; +} + + +int ParseNum (char *str) +{ + if (str[0] == '$') + return ParseHex (str+1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex (str+2); + return atol (str); +} + + + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +#ifdef _SGI_SOURCE +#define __BIG_ENDIAN__ +#endif + +#ifdef __BIG_ENDIAN__ + +short LittleShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short BigShort (short l) +{ + return l; +} + + +int LittleLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int BigLong (int l) +{ + return l; +} + + +float LittleFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float BigFloat (float l) +{ + return l; +} + + +#else + + +short BigShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short LittleShort (short l) +{ + return l; +} + + +int BigLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LittleLong (int l) +{ + return l; +} + +float BigFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float LittleFloat (float l) +{ + return l; +} + + +#endif + + +//======================================================= + + +// FIXME: byte swap? + +// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 +// and the initial and final xor values shown below... in other words, the +// CCITT standard CRC used by XMODEM + +#define CRC_INIT_VALUE 0xffff +#define CRC_XOR_VALUE 0x0000 + +static unsigned short crctable[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +void CRC_Init(unsigned short *crcvalue) +{ + *crcvalue = CRC_INIT_VALUE; +} + +void CRC_ProcessByte(unsigned short *crcvalue, byte data) +{ + *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; +} + +unsigned short CRC_Value(unsigned short crcvalue) +{ + return crcvalue ^ CRC_XOR_VALUE; +} +//============================================================================= + +/* +============ +CreatePath +============ +*/ +void CreatePath (char *path) +{ + char *ofs, c; + + if (path[1] == ':') + path += 2; + + for (ofs = path+1 ; *ofs ; ofs++) + { + c = *ofs; + if (c == '/' || c == '\\') + { // create the directory + *ofs = 0; + Q_mkdir (path); + *ofs = c; + } + } +} + + +/* +============ +QCopyFile + + Used to archive source files +============ +*/ +void QCopyFile (char *from, char *to) +{ + void *buffer; + int length; + + length = LoadFile (from, &buffer); + CreatePath (to); + SaveFile (to, buffer, length); + free (buffer); +} diff --git a/tools/quake2/extra/common/cmdlib.h b/tools/quake2/extra/common/cmdlib.h new file mode 100644 index 00000000..0045a09d --- /dev/null +++ b/tools/quake2/extra/common/cmdlib.h @@ -0,0 +1,145 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// cmdlib.h + +#ifndef __CMDLIB__ +#define __CMDLIB__ + +#ifdef _WIN32 +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#pragma warning(disable : 4018) // signed/unsigned mismatch +#pragma warning(disable : 4305) // truncate from double to float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __BYTEBOOL__ +#define __BYTEBOOL__ +typedef enum {false, true} qboolean; +typedef unsigned char byte; +#endif + +// the dec offsetof macro doesnt work very well... +#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) + + +// set these before calling CheckParm +extern int myargc; +extern char **myargv; + +char *strupr (char *in); +char *strlower (char *in); +int Q_strncasecmp (char *s1, char *s2, int n); +int Q_strcasecmp (char *s1, char *s2); +void Q_getwd (char *out); + +int Q_filelength (FILE *f); +int FileTime (char *path); + +void Q_mkdir (char *path); + +extern char qdir[1024]; +extern char gamedir[1024]; +void SetQdirFromPath (char *path); +char *ExpandArg (char *path); // from cmd line +char *ExpandPath (char *path); // from scripts +char *ExpandPathAndArchive (char *path); + + +double I_FloatTime (void); + +void Error (char *error, ...); +int CheckParm (char *check); + +FILE *SafeOpenWrite (char *filename); +FILE *SafeOpenRead (char *filename); +void SafeRead (FILE *f, void *buffer, int count); +void SafeWrite (FILE *f, void *buffer, int count); + +int LoadFile (char *filename, void **bufferptr); +int TryLoadFile (char *filename, void **bufferptr); +void SaveFile (char *filename, void *buffer, int count); +qboolean FileExists (char *filename); + +void DefaultExtension (char *path, char *extension); +void DefaultPath (char *path, char *basepath); +void StripFilename (char *path); +void StripExtension (char *path); + +void ExtractFilePath (char *path, char *dest); +void ExtractFileBase (char *path, char *dest); +void ExtractFileExtension (char *path, char *dest); + +int ParseNum (char *str); + +short BigShort (short l); +short LittleShort (short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + + +char *COM_Parse (char *data); + +extern char com_token[1024]; +extern qboolean com_eof; + +char *copystring(char *s); + + +void CRC_Init(unsigned short *crcvalue); +void CRC_ProcessByte(unsigned short *crcvalue, byte data); +unsigned short CRC_Value(unsigned short crcvalue); + +void CreatePath (char *path); +void QCopyFile (char *from, char *to); + +extern qboolean archive; +extern char archivedir[1024]; + + +extern qboolean verbose; +void qprintf (char *format, ...); + +void ExpandWildcards (int *argc, char ***argv); + + +// for compression routines +typedef struct +{ + byte *data; + int count; +} cblock_t; + + +#endif diff --git a/tools/quake2/extra/common/l3dslib.c b/tools/quake2/extra/common/l3dslib.c new file mode 100644 index 00000000..8441f4af --- /dev/null +++ b/tools/quake2/extra/common/l3dslib.c @@ -0,0 +1,301 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// +// l3dslib.c: library for loading triangles from an Alias triangle file +// + +#include +#include "cmdlib.h" +#include "mathlib.h" +#include "trilib.h" +#include "l3dslib.h" + +#define MAIN3DS 0x4D4D +#define EDIT3DS 0x3D3D // this is the start of the editor config +#define EDIT_OBJECT 0x4000 +#define OBJ_TRIMESH 0x4100 +#define TRI_VERTEXL 0x4110 +#define TRI_FACEL1 0x4120 + +#define MAXVERTS 2000 + +typedef struct { + int v[4]; +} tri; + +float fverts[MAXVERTS][3]; +tri tris[MAXTRIANGLES]; + +int bytesread, level, numtris, totaltris; +int vertsfound, trisfound; + +triangle_t *ptri; + + +// Alias stores triangles as 3 explicit vertices in .tri files, so even though we +// start out with a vertex pool and vertex indices for triangles, we have to convert +// to raw, explicit triangles +void StoreAliasTriangles (void) +{ + int i, j, k; + + if ((totaltris + numtris) > MAXTRIANGLES) + Error ("Error: Too many triangles"); + + for (i=0; i MAXVERTS) + Error ("Error: Too many vertices"); + + for (i=0 ; i MAXTRIANGLES) + Error ("Error: Too many triangles"); + + for (i=0 ; i 0) + { + w -= ParseChunk (input); + } + + retval = length; + goto Done; + + default: + // skip other chunks + while (w > 0) + { + t = w; + + if (t > BLOCK_SIZE) + t = BLOCK_SIZE; + + if (feof(input)) + Error ("Error: unexpected end of file"); + + fread (&temp, t, 1, input); + bytesread += t; + + w -= t; + } + + retval = length; + goto Done; + } + +Done: + level--; + return retval; +} + + +void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles) +{ + FILE *input; + short int tshort; + + bytesread = 0; + level = 0; + numtris = 0; + totaltris = 0; + vertsfound = 0; + trisfound = 0; + + if ((input = fopen(filename, "rb")) == 0) { + fprintf(stderr,"reader: could not open file '%s'\n", filename); + exit(0); + } + + fread(&tshort, sizeof(tshort), 1, input); + +// should only be MAIN3DS, but some files seem to start with EDIT3DS, with +// no MAIN3DS + if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) { + fprintf(stderr,"File is not a 3DS file.\n"); + exit(0); + } + +// back to top of file so we can parse the first chunk descriptor + fseek(input, 0, SEEK_SET); + + ptri = malloc (MAXTRIANGLES * sizeof(triangle_t)); + + *pptri = ptri; + +// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT | +// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks + ParseChunk (input); + + if (vertsfound || trisfound) + Error ("Incomplete triangle set"); + + *numtriangles = totaltris; + + fclose (input); +} + diff --git a/tools/quake2/extra/common/l3dslib.h b/tools/quake2/extra/common/l3dslib.h new file mode 100644 index 00000000..d28871f1 --- /dev/null +++ b/tools/quake2/extra/common/l3dslib.h @@ -0,0 +1,27 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// +// l3dslib.h: header file for loading triangles from a 3DS triangle file +// +void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles); + diff --git a/tools/quake2/extra/common/lbmlib.c b/tools/quake2/extra/common/lbmlib.c new file mode 100644 index 00000000..25793534 --- /dev/null +++ b/tools/quake2/extra/common/lbmlib.c @@ -0,0 +1,824 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// lbmlib.c + +#include "cmdlib.h" +#include "lbmlib.h" + + + +/* +============================================================================ + + LBM STUFF + +============================================================================ +*/ + + +typedef unsigned char UBYTE; +//conflicts with windows typedef short WORD; +typedef unsigned short UWORD; +typedef long LONG; + +typedef enum +{ + ms_none, + ms_mask, + ms_transcolor, + ms_lasso +} mask_t; + +typedef enum +{ + cm_none, + cm_rle1 +} compress_t; + +typedef struct +{ + UWORD w,h; + short x,y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE pad1; + UWORD transparentColor; + UBYTE xAspect,yAspect; + short pageWidth,pageHeight; +} bmhd_t; + +extern bmhd_t bmhd; // will be in native byte order + + + +#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) +#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) +#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) +#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) +#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) +#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) + + +bmhd_t bmhd; + +int Align (int l) +{ + if (l&1) + return l+1; + return l; +} + + + +/* +================ +LBMRLEdecompress + +Source must be evenly aligned! +================ +*/ +byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) +{ + int count; + byte b,rept; + + count = 0; + + do + { + rept = *source++; + + if (rept > 0x80) + { + rept = (rept^0xff)+2; + b = *source++; + memset(unpacked,b,rept); + unpacked += rept; + } + else if (rept < 0x80) + { + rept++; + memcpy(unpacked,source,rept); + unpacked += rept; + source += rept; + } + else + rept = 0; // rept of 0x80 is NOP + + count += rept; + + } while (countbpwidth) + Error ("Decompression exceeded width!\n"); + + + return source; +} + + +/* +================= +LoadLBM +================= +*/ +void LoadLBM (char *filename, byte **picture, byte **palette) +{ + byte *LBMbuffer, *picbuffer, *cmapbuffer; + int y; + byte *LBM_P, *LBMEND_P; + byte *pic_p; + byte *body_p; + + int formtype,formlength; + int chunktype,chunklength; + +// qiet compiler warnings + picbuffer = NULL; + cmapbuffer = NULL; + +// +// load the LBM +// + LoadFile (filename, (void **)&LBMbuffer); + +// +// parse the LBM header +// + LBM_P = LBMbuffer; + if ( *(int *)LBMbuffer != LittleLong(FORMID) ) + Error ("No FORM ID at start of file!\n"); + + LBM_P += 4; + formlength = BigLong( *(int *)LBM_P ); + LBM_P += 4; + LBMEND_P = LBM_P + Align(formlength); + + formtype = LittleLong(*(int *)LBM_P); + + if (formtype != ILBMID && formtype != PBMID) + Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff + ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); + + LBM_P += 4; + +// +// parse chunks +// + + while (LBM_P < LBMEND_P) + { + chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); + LBM_P += 4; + chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); + LBM_P += 4; + + switch ( chunktype ) + { + case BMHDID: + memcpy (&bmhd,LBM_P,sizeof(bmhd)); + bmhd.w = BigShort(bmhd.w); + bmhd.h = BigShort(bmhd.h); + bmhd.x = BigShort(bmhd.x); + bmhd.y = BigShort(bmhd.y); + bmhd.pageWidth = BigShort(bmhd.pageWidth); + bmhd.pageHeight = BigShort(bmhd.pageHeight); + break; + + case CMAPID: + cmapbuffer = malloc (768); + memset (cmapbuffer, 0, 768); + memcpy (cmapbuffer, LBM_P, chunklength); + break; + + case BODYID: + body_p = LBM_P; + + pic_p = picbuffer = malloc (bmhd.w*bmhd.h); + if (formtype == PBMID) + { + // + // unpack PBM + // + for (y=0 ; ydata; + + pcx->xmin = LittleShort(pcx->xmin); + pcx->ymin = LittleShort(pcx->ymin); + pcx->xmax = LittleShort(pcx->xmax); + pcx->ymax = LittleShort(pcx->ymax); + pcx->hres = LittleShort(pcx->hres); + pcx->vres = LittleShort(pcx->vres); + pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); + pcx->palette_type = LittleShort(pcx->palette_type); + + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8 + || pcx->xmax >= 640 + || pcx->ymax >= 480) + Error ("Bad pcx file %s", filename); + + if (palette) + { + *palette = malloc(768); + memcpy (*palette, (byte *)pcx + len - 768, 768); + } + + if (width) + *width = pcx->xmax+1; + if (height) + *height = pcx->ymax+1; + + if (!pic) + return; + + out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); + if (!out) + Error ("Skin_Cache: couldn't allocate"); + + *pic = out; + + pix = out; + + for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) + { + for (x=0 ; x<=pcx->xmax ; ) + { + dataByte = *raw++; + + if((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = *raw++; + } + else + runLength = 1; + + while(runLength-- > 0) + pix[x++] = dataByte; + } + + } + + if ( raw - (byte *)pcx > len) + Error ("PCX file %s was malformed", filename); + + free (pcx); +} + +/* +============== +WritePCXfile +============== +*/ +void WritePCXfile (char *filename, byte *data, + int width, int height, byte *palette) +{ + int i, j, length; + pcx_t *pcx; + byte *pack; + + pcx = malloc (width*height*2+1000); + memset (pcx, 0, sizeof(*pcx)); + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort((short)(width-1)); + pcx->ymax = LittleShort((short)(height-1)); + pcx->hres = LittleShort((short)width); + pcx->vres = LittleShort((short)height); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort((short)width); + pcx->palette_type = LittleShort(2); // not a grey scale + + // pack the image + pack = &pcx->data; + + for (i=0 ; i=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + else { // non run-length packet + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + } + breakOut:; + } + } + + fclose(fin); +} diff --git a/tools/quake2/extra/common/lbmlib.h b/tools/quake2/extra/common/lbmlib.h new file mode 100644 index 00000000..c90a6dd8 --- /dev/null +++ b/tools/quake2/extra/common/lbmlib.h @@ -0,0 +1,40 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// piclib.h + + +void LoadLBM (char *filename, byte **picture, byte **palette); +void WriteLBMfile (char *filename, byte *data, int width, int height + , byte *palette); +void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height); +void WritePCXfile (char *filename, byte *data, int width, int height + , byte *palette); + +// loads / saves either lbm or pcx, depending on extension +void Load256Image (char *name, byte **pixels, byte **palette, + int *width, int *height); +void Save256Image (char *name, byte *pixels, byte *palette, + int width, int height); + + +void LoadTGA (char *filename, byte **pixels, int *width, int *height); diff --git a/tools/quake2/extra/common/mathlib.c b/tools/quake2/extra/common/mathlib.c new file mode 100644 index 00000000..207027b3 --- /dev/null +++ b/tools/quake2/extra/common/mathlib.c @@ -0,0 +1,174 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// mathlib.c -- math primitives + +#include "cmdlib.h" +#include "mathlib.h" + +vec3_t vec3_origin = {0,0,0}; + + +double VectorLength(vec3_t v) +{ + int i; + double length; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); // FIXME + + return length; +} + +qboolean VectorCompare (vec3_t v1, vec3_t v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON) + return false; + + return true; +} + +vec_t Q_rint (vec_t in) +{ + return floor (in + 0.5); +} + +void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc) +{ + vc[0] = va[0] + scale*vb[0]; + vc[1] = va[1] + scale*vb[1]; + vc[2] = va[2] + scale*vb[2]; +} + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]-vb[0]; + out[1] = va[1]-vb[1]; + out[2] = va[2]-vb[2]; +} + +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]+vb[0]; + out[1] = va[1]+vb[1]; + out[2] = va[2]+vb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +void _VectorScale (vec3_t v, vec_t scale, vec3_t out) +{ + out[0] = v[0] * scale; + out[1] = v[1] * scale; + out[2] = v[2] * scale; +} + +vec_t VectorNormalize (vec3_t in, vec3_t out) +{ + vec_t length, ilength; + + length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]); + if (length == 0) + { + VectorClear (out); + return 0; + } + + ilength = 1.0/length; + out[0] = in[0]*ilength; + out[1] = in[1]*ilength; + out[2] = in[2]*ilength; + + return length; +} + +vec_t ColorNormalize (vec3_t in, vec3_t out) +{ + float max, scale; + + max = in[0]; + if (in[1] > max) + max = in[1]; + if (in[2] > max) + max = in[2]; + + if (max == 0) + return 0; + + scale = 1.0 / max; + + VectorScale (in, scale, out); + + return max; +} + + + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void ClearBounds (vec3_t mins, vec3_t maxs) +{ + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; +} + +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) +{ + int i; + vec_t val; + + for (i=0 ; i<3 ; i++) + { + val = v[i]; + if (val < mins[i]) + mins[i] = val; + if (val > maxs[i]) + maxs[i] = val; + } +} diff --git a/tools/quake2/extra/common/mathlib.h b/tools/quake2/extra/common/mathlib.h new file mode 100644 index 00000000..ee7fddee --- /dev/null +++ b/tools/quake2/extra/common/mathlib.h @@ -0,0 +1,77 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#ifndef __MATHLIB__ +#define __MATHLIB__ + +// mathlib.h + +#include + +#ifdef DOUBLEVEC_T +typedef double vec_t; +#else +typedef float vec_t; +#endif +typedef vec_t vec3_t[3]; + +#define SIDE_FRONT 0 +#define SIDE_ON 2 +#define SIDE_BACK 1 +#define SIDE_CROSS -2 + +#define Q_PI 3.14159265358979323846 + +extern vec3_t vec3_origin; + +#define EQUAL_EPSILON 0.001 + +qboolean VectorCompare (vec3_t v1, vec3_t v2); + +#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) +#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} +#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} +#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];} +#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];} +#define VectorClear(x) {x[0] = x[1] = x[2] = 0;} +#define VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];} + +vec_t Q_rint (vec_t in); +vec_t _DotProduct (vec3_t v1, vec3_t v2); +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); +void _VectorCopy (vec3_t in, vec3_t out); +void _VectorScale (vec3_t v, vec_t scale, vec3_t out); + +double VectorLength(vec3_t v); + +void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc); + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); +vec_t VectorNormalize (vec3_t in, vec3_t out); +vec_t ColorNormalize (vec3_t in, vec3_t out); +void VectorInverse (vec3_t v); + +void ClearBounds (vec3_t mins, vec3_t maxs); +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); + +#endif diff --git a/tools/quake2/extra/common/mdfour.c b/tools/quake2/extra/common/mdfour.c new file mode 100644 index 00000000..f5b9a29d --- /dev/null +++ b/tools/quake2/extra/common/mdfour.c @@ -0,0 +1,224 @@ +/* + mdfour.c + + An implementation of MD4 designed for use in the samba SMB + authentication protocol + + Copyright (C) 1997-1998 Andrew Tridgell + + This program is free software; you can redistribute it and/or + modify it under the terms of the 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id: mdfour.c,v 1.1 2002/08/23 22:03:27 abster Exp $ +*/ + +#include /* XoXus: needed for memset call */ +#include "mdfour.h" + +/* NOTE: This code makes no attempt to be fast! + + It assumes that a int is at least 32 bits long +*/ + +static struct mdfour *m; + +#define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z))) +#define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))) +#define H(X,Y,Z) ((X)^(Y)^(Z)) +#ifdef LARGE_INT32 +#define lshift(x,s) ((((x)<<(s))&0xFFFFFFFF) | (((x)>>(32-(s)))&0xFFFFFFFF)) +#else +#define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s)))) +#endif + +#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64(uint32 *M) +{ + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; + uint32 A,B,C,D; + + for (j=0;j<16;j++) + X[j] = M[j]; + + A = m->A; B = m->B; C = m->C; D = m->D; + AA = A; BB = B; CC = C; DD = D; + + ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); + ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); + ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); + ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); + ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); + ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); + ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); + ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); + + ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); + ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); + ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); + ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); + ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); + ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); + ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); + ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); + + ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); + ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); + ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); + ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); + ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); + ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); + ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); + ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); + + A += AA; B += BB; C += CC; D += DD; + +#ifdef LARGE_INT32 + A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; + C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; +#endif + + for (j=0;j<16;j++) + X[j] = 0; + + m->A = A; m->B = B; m->C = C; m->D = D; +} + +static void copy64(uint32 *M, unsigned char *in) +{ + int i; + + for (i=0;i<16;i++) + M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | + (in[i*4+1]<<8) | (in[i*4+0]<<0); +} + +static void copy4(unsigned char *out,uint32 x) +{ + out[0] = x&0xFF; + out[1] = (x>>8)&0xFF; + out[2] = (x>>16)&0xFF; + out[3] = (x>>24)&0xFF; +} + +void mdfour_begin(struct mdfour *md) +{ + md->A = 0x67452301; + md->B = 0xefcdab89; + md->C = 0x98badcfe; + md->D = 0x10325476; + md->totalN = 0; +} + + +static void mdfour_tail(unsigned char *in, int n) +{ + unsigned char buf[128]; + uint32 M[16]; + uint32 b; + + m->totalN += n; + + b = m->totalN * 8; + + memset(buf, 0, 128); + if (n) memcpy(buf, in, n); + buf[n] = 0x80; + + if (n <= 55) { + copy4(buf+56, b); + copy64(M, buf); + mdfour64(M); + } else { + copy4(buf+120, b); + copy64(M, buf); + mdfour64(M); + copy64(M, buf+64); + mdfour64(M); + } +} + +void mdfour_update(struct mdfour *md, unsigned char *in, int n) +{ + uint32 M[16]; + + if (n == 0) mdfour_tail(in, n); + + m = md; + + while (n >= 64) { + copy64(M, in); + mdfour64(M); + in += 64; + n -= 64; + m->totalN += 64; + } + + mdfour_tail(in, n); +} + + +void mdfour_result(struct mdfour *md, unsigned char *out) +{ + m = md; + + copy4(out, m->A); + copy4(out+4, m->B); + copy4(out+8, m->C); + copy4(out+12, m->D); +} + + +void mdfour(unsigned char *out, unsigned char *in, int n) +{ + struct mdfour md; + mdfour_begin(&md); + mdfour_update(&md, in, n); + mdfour_result(&md, out); +} + +/////////////////////////////////////////////////////////////// +// MD4-based checksum utility functions +// +// Copyright (C) 2000 Jeff Teunissen +// +// Author: Jeff Teunissen +// Date: 01 Jan 2000 + +unsigned Com_BlockChecksum (void *buffer, int length) +{ + int digest[4]; + unsigned val; + + mdfour ( (unsigned char *) digest, (unsigned char *) buffer, length ); + + val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; + + return val; +} + +void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf) +{ + mdfour ( outbuf, (unsigned char *) buffer, len ); +} + diff --git a/tools/quake2/extra/common/mdfour.h b/tools/quake2/extra/common/mdfour.h new file mode 100644 index 00000000..69ca6f78 --- /dev/null +++ b/tools/quake2/extra/common/mdfour.h @@ -0,0 +1,54 @@ +/* + mdfour.h + + an implementation of MD4 designed for use in the SMB authentication + protocol + + Copyright (C) Andrew Tridgell 1997-1998 + + This program is free software; you can redistribute it and/or + modify it under the terms of the 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA +*/ + +#ifndef _MDFOUR_H +#define _MDFOUR_H + +#ifndef int32 +#define int32 int +#endif + +#if SIZEOF_INT > 4 +#define LARGE_INT32 +#endif + +#ifndef uint32 +#define uint32 unsigned int32 +#endif + +struct mdfour { + uint32 A, B, C, D; + uint32 totalN; +}; + +void mdfour_begin(struct mdfour *md); // old: MD4Init +void mdfour_update(struct mdfour *md, unsigned char *in, int n); //old: MD4Update +void mdfour_result(struct mdfour *md, unsigned char *out); // old: MD4Final +void mdfour(unsigned char *out, unsigned char *in, int n); + +#endif // _MDFOUR_H + diff --git a/tools/quake2/extra/common/polylib.c b/tools/quake2/extra/common/polylib.c new file mode 100644 index 00000000..c190ebd6 --- /dev/null +++ b/tools/quake2/extra/common/polylib.c @@ -0,0 +1,642 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "polylib.h" + + +extern int numthreads; + +// counters are only bumped when running single threaded, +// because they are an awefull coherence problem +int c_active_windings; +int c_peak_windings; +int c_winding_allocs; +int c_winding_points; + +#define BOGUS_RANGE 8192 + +void pw(winding_t *w) +{ + int i; + for (i=0 ; inumpoints ; i++) + printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); +} + + +/* +============= +AllocWinding +============= +*/ +winding_t *AllocWinding (int points) +{ + winding_t *w; + int s; + + if (numthreads == 1) + { + c_winding_allocs++; + c_winding_points += points; + c_active_windings++; + if (c_active_windings > c_peak_windings) + c_peak_windings = c_active_windings; + } + s = sizeof(vec_t)*3*points + sizeof(int); + w = malloc (s); + memset (w, 0, s); + return w; +} + +void FreeWinding (winding_t *w) +{ + if (*(unsigned *)w == 0xdeaddead) + Error ("FreeWinding: freed a freed winding"); + *(unsigned *)w = 0xdeaddead; + + if (numthreads == 1) + c_active_windings--; + free (w); +} + +/* +============ +RemoveColinearPoints +============ +*/ +int c_removed; + +void RemoveColinearPoints (winding_t *w) +{ + int i, j, k; + vec3_t v1, v2; + int nump; + vec3_t p[MAX_POINTS_ON_WINDING]; + + nump = 0; + for (i=0 ; inumpoints ; i++) + { + j = (i+1)%w->numpoints; + k = (i+w->numpoints-1)%w->numpoints; + VectorSubtract (w->p[j], w->p[i], v1); + VectorSubtract (w->p[i], w->p[k], v2); + VectorNormalize(v1,v1); + VectorNormalize(v2,v2); + if (DotProduct(v1, v2) < 0.999) + { + VectorCopy (w->p[i], p[nump]); + nump++; + } + } + + if (nump == w->numpoints) + return; + + if (numthreads == 1) + c_removed += w->numpoints - nump; + w->numpoints = nump; + memcpy (w->p, p, nump*sizeof(p[0])); +} + +/* +============ +WindingPlane +============ +*/ +void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) +{ + vec3_t v1, v2; + + VectorSubtract (w->p[1], w->p[0], v1); + VectorSubtract (w->p[2], w->p[0], v2); + CrossProduct (v2, v1, normal); + VectorNormalize (normal, normal); + *dist = DotProduct (w->p[0], normal); + +} + +/* +============= +WindingArea +============= +*/ +vec_t WindingArea (winding_t *w) +{ + int i; + vec3_t d1, d2, cross; + vec_t total; + + total = 0; + for (i=2 ; inumpoints ; i++) + { + VectorSubtract (w->p[i-1], w->p[0], d1); + VectorSubtract (w->p[i], w->p[0], d2); + CrossProduct (d1, d2, cross); + total += 0.5 * VectorLength ( cross ); + } + return total; +} + +void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs) +{ + vec_t v; + int i,j; + + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; + + for (i=0 ; inumpoints ; i++) + { + for (j=0 ; j<3 ; j++) + { + v = w->p[i][j]; + if (v < mins[j]) + mins[j] = v; + if (v > maxs[j]) + maxs[j] = v; + } + } +} + +/* +============= +WindingCenter +============= +*/ +void WindingCenter (winding_t *w, vec3_t center) +{ + int i; + float scale; + + VectorCopy (vec3_origin, center); + for (i=0 ; inumpoints ; i++) + VectorAdd (w->p[i], center, center); + + scale = 1.0/w->numpoints; + VectorScale (center, scale, center); +} + +/* +================= +BaseWindingForPlane +================= +*/ +winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist) +{ + int i, x; + vec_t max, v; + vec3_t org, vright, vup; + winding_t *w; + +// find the major axis + + max = -BOGUS_RANGE; + x = -1; + for (i=0 ; i<3; i++) + { + v = fabs(normal[i]); + if (v > max) + { + x = i; + max = v; + } + } + if (x==-1) + Error ("BaseWindingForPlane: no axis found"); + + VectorCopy (vec3_origin, vup); + switch (x) + { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + v = DotProduct (vup, normal); + VectorMA (vup, -v, normal, vup); + VectorNormalize (vup, vup); + + VectorScale (normal, dist, org); + + CrossProduct (vup, normal, vright); + + VectorScale (vup, 8192, vup); + VectorScale (vright, 8192, vright); + +// project a really big axis aligned box onto the plane + w = AllocWinding (4); + + VectorSubtract (org, vright, w->p[0]); + VectorAdd (w->p[0], vup, w->p[0]); + + VectorAdd (org, vright, w->p[1]); + VectorAdd (w->p[1], vup, w->p[1]); + + VectorAdd (org, vright, w->p[2]); + VectorSubtract (w->p[2], vup, w->p[2]); + + VectorSubtract (org, vright, w->p[3]); + VectorSubtract (w->p[3], vup, w->p[3]); + + w->numpoints = 4; + + return w; +} + +/* +================== +CopyWinding +================== +*/ +winding_t *CopyWinding (winding_t *w) +{ + int size; + winding_t *c; + + c = AllocWinding (w->numpoints); + size = (int)((winding_t *)0)->p[w->numpoints]; + memcpy (c, w, size); + return c; +} + +/* +================== +ReverseWinding +================== +*/ +winding_t *ReverseWinding (winding_t *w) +{ + int i; + winding_t *c; + + c = AllocWinding (w->numpoints); + for (i=0 ; inumpoints ; i++) + { + VectorCopy (w->p[w->numpoints-1-i], c->p[i]); + } + c->numpoints = w->numpoints; + return c; +} + + +/* +============= +ClipWindingEpsilon +============= +*/ +void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + static vec_t dot; // VC 4.2 optimizer bug if not static + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f, *b; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) + sides[i] = SIDE_FRONT; + else if (dot < -epsilon) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) + { + *back = CopyWinding (in); + return; + } + if (!counts[1]) + { + *front = CopyWinding (in); + return; + } + + maxpts = in->numpoints+4; // cant use counts[0]+2 because + // of fp grouping errors + + *front = f = AllocWinding (maxpts); + *back = b = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); +} + + +/* +============= +ChopWindingInPlace +============= +*/ +void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon) +{ + winding_t *in; + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + static vec_t dot; // VC 4.2 optimizer bug if not static + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f; + int maxpts; + + in = *inout; + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > epsilon) + sides[i] = SIDE_FRONT; + else if (dot < -epsilon) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (!counts[0]) + { + FreeWinding (in); + *inout = NULL; + return; + } + if (!counts[1]) + return; // inout stays the same + + maxpts = in->numpoints+4; // cant use counts[0]+2 because + // of fp grouping errors + + f = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + } + + if (f->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); + + FreeWinding (in); + *inout = f; +} + + +/* +================= +ChopWinding + +Returns the fragment of in that is on the front side +of the cliping plane. The original is freed. +================= +*/ +winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) +{ + winding_t *f, *b; + + ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b); + FreeWinding (in); + if (b) + FreeWinding (b); + return f; +} + + +/* +================= +CheckWinding + +================= +*/ +void CheckWinding (winding_t *w) +{ + int i, j; + vec_t *p1, *p2; + vec_t d, edgedist; + vec3_t dir, edgenormal, facenormal; + vec_t area; + vec_t facedist; + + if (w->numpoints < 3) + Error ("CheckWinding: %i points",w->numpoints); + + area = WindingArea(w); + if (area < 1) + Error ("CheckWinding: %f area", area); + + WindingPlane (w, facenormal, &facedist); + + for (i=0 ; inumpoints ; i++) + { + p1 = w->p[i]; + + for (j=0 ; j<3 ; j++) + if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) + Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); + + j = i+1 == w->numpoints ? 0 : i+1; + + // check the point is on the face plane + d = DotProduct (p1, facenormal) - facedist; + if (d < -ON_EPSILON || d > ON_EPSILON) + Error ("CheckWinding: point off plane"); + + // check the edge isnt degenerate + p2 = w->p[j]; + VectorSubtract (p2, p1, dir); + + if (VectorLength (dir) < ON_EPSILON) + Error ("CheckWinding: degenerate edge"); + + CrossProduct (facenormal, dir, edgenormal); + VectorNormalize (edgenormal, edgenormal); + edgedist = DotProduct (p1, edgenormal); + edgedist += ON_EPSILON; + + // all other points must be on front side + for (j=0 ; jnumpoints ; j++) + { + if (j == i) + continue; + d = DotProduct (w->p[j], edgenormal); + if (d > edgedist) + Error ("CheckWinding: non-convex"); + } + } +} + + +/* +============ +WindingOnPlaneSide +============ +*/ +int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist) +{ + qboolean front, back; + int i; + vec_t d; + + front = false; + back = false; + for (i=0 ; inumpoints ; i++) + { + d = DotProduct (w->p[i], normal) - dist; + if (d < -ON_EPSILON) + { + if (front) + return SIDE_CROSS; + back = true; + continue; + } + if (d > ON_EPSILON) + { + if (back) + return SIDE_CROSS; + front = true; + continue; + } + } + + if (back) + return SIDE_BACK; + if (front) + return SIDE_FRONT; + return SIDE_ON; +} + diff --git a/tools/quake2/extra/common/polylib.h b/tools/quake2/extra/common/polylib.h new file mode 100644 index 00000000..2024a0dc --- /dev/null +++ b/tools/quake2/extra/common/polylib.h @@ -0,0 +1,55 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +typedef struct +{ + int numpoints; + vec3_t p[4]; // variable sized +} winding_t; + +#define MAX_POINTS_ON_WINDING 64 + +// you can define on_epsilon in the makefile as tighter +#ifndef ON_EPSILON +#define ON_EPSILON 0.1 +#endif + +winding_t *AllocWinding (int points); +vec_t WindingArea (winding_t *w); +void WindingCenter (winding_t *w, vec3_t center); +void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, + vec_t epsilon, winding_t **front, winding_t **back); +winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); +winding_t *CopyWinding (winding_t *w); +winding_t *ReverseWinding (winding_t *w); +winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); +void CheckWinding (winding_t *w); +void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); +void RemoveColinearPoints (winding_t *w); +int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist); +void FreeWinding (winding_t *w); +void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); + +void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon); +// frees the original if clipped + +void pw(winding_t *w); diff --git a/tools/quake2/extra/common/qfiles.h b/tools/quake2/extra/common/qfiles.h new file mode 100644 index 00000000..d7a85563 --- /dev/null +++ b/tools/quake2/extra/common/qfiles.h @@ -0,0 +1,486 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// +// qfiles.h: quake file formats +// This file must be identical in the quake and utils directories +// + +/* +======================================================================== + +The .pak files are just a linear collapse of a directory tree + +======================================================================== +*/ + +#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P') + +typedef struct +{ + char name[56]; + int filepos, filelen; +} dpackfile_t; + +typedef struct +{ + int ident; // == IDPAKHEADER + int dirofs; + int dirlen; +} dpackheader_t; + +#define MAX_FILES_IN_PACK 4096 + + +/* +======================================================================== + +PCX files are used for as many images as possible + +======================================================================== +*/ + +typedef struct +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + unsigned short xmin,ymin,xmax,ymax; + unsigned short hres,vres; + unsigned char palette[48]; + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + char filler[58]; + unsigned char data; // unbounded +} pcx_t; + + +/* +======================================================================== + +.MD2 triangle model file format + +======================================================================== +*/ + +#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I') +#define ALIAS_VERSION 8 + +#define MAX_TRIANGLES 4096 +#define MAX_VERTS 2048 +#define MAX_FRAMES 512 +#define MAX_MD2SKINS 32 +#define MAX_SKINNAME 64 + +typedef struct +{ + short s; + short t; +} dstvert_t; + +typedef struct +{ + short index_xyz[3]; + short index_st[3]; +} dtriangle_t; + +typedef struct +{ + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; +} dtrivertx_t; + +#define DTRIVERTX_V0 0 +#define DTRIVERTX_V1 1 +#define DTRIVERTX_V2 2 +#define DTRIVERTX_LNI 3 +#define DTRIVERTX_SIZE 4 + +typedef struct +{ + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + dtrivertx_t verts[1]; // variable sized +} daliasframe_t; + + +// the glcmd format: +// a positive integer starts a tristrip command, followed by that many +// vertex structures. +// a negative integer starts a trifan command, followed by -x vertexes +// a zero indicates the end of the command list. +// a vertex consists of a floating point s, a floating point t, +// and an integer vertex index. + + +typedef struct +{ + int ident; + int version; + + int skinwidth; + int skinheight; + int framesize; // byte size of each frame + + int num_skins; + int num_xyz; + int num_st; // greater than num_xyz for seams + int num_tris; + int num_glcmds; // dwords in strip/fan command list + int num_frames; + + int ofs_skins; // each skin is a MAX_SKINNAME string + int ofs_st; // byte offset from start for stverts + int ofs_tris; // offset for dtriangles + int ofs_frames; // offset for first frame + int ofs_glcmds; + int ofs_end; // end of file + +} dmdl_t; + +/* +======================================================================== + +.SP2 sprite file format + +======================================================================== +*/ + +#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I') + // little-endian "IDS2" +#define SPRITE_VERSION 2 + +typedef struct +{ + int width, height; + int origin_x, origin_y; // raster coordinates inside pic + char name[MAX_SKINNAME]; // name of pcx file +} dsprframe_t; + +typedef struct { + int ident; + int version; + int numframes; + dsprframe_t frames[1]; // variable sized +} dsprite_t; + +/* +============================================================================== + + .WAL texture file format + +============================================================================== +*/ + + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[32]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored + char animname[32]; // next frame in animation chain + int flags; + int contents; + int value; +} miptex_t; + + + +/* +============================================================================== + + .BSP file format + +============================================================================== +*/ + +#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') + // little-endian "IBSP" + +#define BSPVERSION 38 + + +// upper design bounds +// leaffaces, leafbrushes, planes, and verts are still bounded by +// 16 bit short limits +#define MAX_MAP_MODELS 1024 +#define MAX_MAP_BRUSHES 8192 +#define MAX_MAP_ENTITIES 2048 +#define MAX_MAP_ENTSTRING 0x40000 +#define MAX_MAP_TEXINFO 8192 + +#define MAX_MAP_AREAS 256 +#define MAX_MAP_AREAPORTALS 1024 +#define MAX_MAP_PLANES 65536 +#define MAX_MAP_NODES 65536 +#define MAX_MAP_BRUSHSIDES 65536 +#define MAX_MAP_LEAFS 65536 +#define MAX_MAP_VERTS 65536 +#define MAX_MAP_FACES 65536 +#define MAX_MAP_LEAFFACES 65536 +#define MAX_MAP_LEAFBRUSHES 65536 +#define MAX_MAP_PORTALS 65536 +#define MAX_MAP_EDGES 128000 +#define MAX_MAP_SURFEDGES 256000 +#define MAX_MAP_LIGHTING 0x200000 +#define MAX_MAP_VISIBILITY 0x100000 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 1024 + +//============================================================================= + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_VERTEXES 2 +#define LUMP_VISIBILITY 3 +#define LUMP_NODES 4 +#define LUMP_TEXINFO 5 +#define LUMP_FACES 6 +#define LUMP_LIGHTING 7 +#define LUMP_LEAFS 8 +#define LUMP_LEAFFACES 9 +#define LUMP_LEAFBRUSHES 10 +#define LUMP_EDGES 11 +#define LUMP_SURFEDGES 12 +#define LUMP_MODELS 13 +#define LUMP_BRUSHES 14 +#define LUMP_BRUSHSIDES 15 +#define LUMP_POP 16 +#define LUMP_AREAS 17 +#define LUMP_AREAPORTALS 18 +#define HEADER_LUMPS 19 + +typedef struct +{ + int ident; + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; // for sounds or lights + int headnode; + int firstface, numfaces; // submodels just draw faces + // without walking the bsp tree +} dmodel_t; + + +typedef struct +{ + float point[3]; +} dvertex_t; + + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +// planes (x&~1) and (x&~1)+1 are allways opposites + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + + +// contents flags are seperate bits +// a given brush can contribute multiple content bits +// multiple brushes can be in a single leaf + +// these definitions also need to be in q_shared.h! + +// lower bits are stronger, and will eat weaker brushes completely +#define CONTENTS_SOLID 1 // an eye is never valid in a solid +#define CONTENTS_WINDOW 2 // translucent, but not watery +#define CONTENTS_AUX 4 +#define CONTENTS_LAVA 8 +#define CONTENTS_SLIME 16 +#define CONTENTS_WATER 32 +#define CONTENTS_MIST 64 +#define LAST_VISIBLE_CONTENTS 64 + +// remaining contents are non-visible, and don't eat brushes + +#define CONTENTS_AREAPORTAL 0x8000 + +#define CONTENTS_PLAYERCLIP 0x10000 +#define CONTENTS_MONSTERCLIP 0x20000 + +// currents can be added to any other contents, and may be mixed +#define CONTENTS_CURRENT_0 0x40000 +#define CONTENTS_CURRENT_90 0x80000 +#define CONTENTS_CURRENT_180 0x100000 +#define CONTENTS_CURRENT_270 0x200000 +#define CONTENTS_CURRENT_UP 0x400000 +#define CONTENTS_CURRENT_DOWN 0x800000 + +#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity + +#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game +#define CONTENTS_DEADMONSTER 0x4000000 +#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs +#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans +#define CONTENTS_LADDER 0x20000000 + + + +#define SURF_LIGHT 0x1 // value will hold the light strength + +#define SURF_SLICK 0x2 // effects game physics + +#define SURF_SKY 0x4 // don't draw, but add to skybox +#define SURF_WARP 0x8 // turbulent water warp +#define SURF_TRANS33 0x10 +#define SURF_TRANS66 0x20 +#define SURF_FLOWING 0x40 // scroll towards angle +#define SURF_NODRAW 0x80 // don't bother referencing the texture + +#define SURF_HINT 0x100 // make a primary bsp splitter +#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes + + + +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for frustom culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int flags; // miptex flags + overrides + int value; // light emission, etc + char texture[32]; // texture name (textures/*.wal) + int nexttexinfo; // for animations, -1 = end of chain +} texinfo_t; + + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 +typedef struct +{ + unsigned short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + +typedef struct +{ + int contents; // OR of all brushes (not needed?) + + short cluster; + short area; + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstleafface; + unsigned short numleaffaces; + + unsigned short firstleafbrush; + unsigned short numleafbrushes; +} dleaf_t; + +typedef struct +{ + unsigned short planenum; // facing out of the leaf + short texinfo; +} dbrushside_t; + +typedef struct +{ + int firstside; + int numsides; + int contents; +} dbrush_t; + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + + +// the visibility lump consists of a header with a count, then +// byte offsets for the PVS and PHS of each cluster, then the raw +// compressed bit vectors +#define DVIS_PVS 0 +#define DVIS_PHS 1 +typedef struct +{ + int numclusters; + int bitofs[8][2]; // bitofs[numclusters][2] +} dvis_t; + +// each area has a list of portals that lead into other areas +// when portals are closed, other areas may not be visible or +// hearable even if the vis info says that it should be +typedef struct +{ + int portalnum; + int otherarea; +} dareaportal_t; + +typedef struct +{ + int numareaportals; + int firstareaportal; +} darea_t; diff --git a/tools/quake2/extra/common/scriplib.c b/tools/quake2/extra/common/scriplib.c new file mode 100644 index 00000000..a9e2f3b5 --- /dev/null +++ b/tools/quake2/extra/common/scriplib.c @@ -0,0 +1,297 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// scriplib.c + +#include "cmdlib.h" +#include "scriplib.h" + +/* +============================================================================= + + PARSING STUFF + +============================================================================= +*/ + +typedef struct +{ + char filename[1024]; + char *buffer,*script_p,*end_p; + int line; +} script_t; + +#define MAX_INCLUDES 8 +script_t scriptstack[MAX_INCLUDES]; +script_t *script; +int scriptline; + +char token[MAXTOKEN]; +qboolean endofscript; +qboolean tokenready; // only true if UnGetToken was just called + +/* +============== +AddScriptToStack +============== +*/ +void AddScriptToStack (char *filename) +{ + int size; + + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + strcpy (script->filename, ExpandPath (filename) ); + + size = LoadFile (script->filename, (void **)&script->buffer); + + printf ("entering %s\n", script->filename); + + script->line = 1; + + script->script_p = script->buffer; + script->end_p = script->buffer + size; +} + + +/* +============== +LoadScriptFile +============== +*/ +void LoadScriptFile (char *filename) +{ + script = scriptstack; + AddScriptToStack (filename); + + endofscript = false; + tokenready = false; +} + + +/* +============== +ParseFromMemory +============== +*/ +void ParseFromMemory (char *buffer, int size) +{ + script = scriptstack; + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + strcpy (script->filename, "memory buffer" ); + + script->buffer = buffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + + endofscript = false; + tokenready = false; +} + + +/* +============== +UnGetToken + +Signals that the current token was not used, and should be reported +for the next GetToken. Note that + +GetToken (true); +UnGetToken (); +GetToken (false); + +could cross a line boundary. +============== +*/ +void UnGetToken (void) +{ + tokenready = true; +} + + +qboolean EndOfScript (qboolean crossline) +{ + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + + if (!strcmp (script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + free (script->buffer); + if (script == scriptstack+1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + printf ("returning to %s\n", script->filename); + return GetToken (crossline); +} + +/* +============== +GetToken +============== +*/ +qboolean GetToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + +// +// skip space +// +skipspace: + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + if (*script->script_p++ == '\n') + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + scriptline = script->line++; + } + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + + // ; # // comments + if (*script->script_p == ';' || *script->script_p == '#' + || ( script->script_p[0] == '/' && script->script_p[1] == '/') ) + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + goto skipspace; + } + + // /* */ comments + if (script->script_p[0] == '/' && script->script_p[1] == '*') + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + script->script_p+=2; + while (script->script_p[0] != '*' && script->script_p[1] != '/') + { + script->script_p++; + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + } + script->script_p += 2; + goto skipspace; + } + +// +// copy token +// + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + script->script_p++; + } + else // regular token + while ( *script->script_p > 32 && *script->script_p != ';') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + + *token_p = 0; + + if (!strcmp (token, "$include")) + { + GetToken (false); + AddScriptToStack (token); + return GetToken (crossline); + } + + return true; +} + + +/* +============== +TokenAvailable + +Returns true if there is another token on the line +============== +*/ +qboolean TokenAvailable (void) +{ + char *search_p; + + search_p = script->script_p; + + if (search_p >= script->end_p) + return false; + + while ( *search_p <= 32) + { + if (*search_p == '\n') + return false; + search_p++; + if (search_p == script->end_p) + return false; + + } + + if (*search_p == ';') + return false; + + return true; +} + + diff --git a/tools/quake2/extra/common/scriplib.h b/tools/quake2/extra/common/scriplib.h new file mode 100644 index 00000000..25c1c059 --- /dev/null +++ b/tools/quake2/extra/common/scriplib.h @@ -0,0 +1,45 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// scriplib.h + +#ifndef __CMDLIB__ +#include "cmdlib.h" +#endif + +#define MAXTOKEN 1024 + +extern char token[MAXTOKEN]; +extern char *scriptbuffer,*script_p,*scriptend_p; +extern int grabbed; +extern int scriptline; +extern qboolean endofscript; + + +void LoadScriptFile (char *filename); +void ParseFromMemory (char *buffer, int size); + +qboolean GetToken (qboolean crossline); +void UnGetToken (void); +qboolean TokenAvailable (void); + + diff --git a/tools/quake2/extra/common/threads.c b/tools/quake2/extra/common/threads.c new file mode 100644 index 00000000..25a87c78 --- /dev/null +++ b/tools/quake2/extra/common/threads.c @@ -0,0 +1,448 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "threads.h" + +#define MAX_THREADS 64 + +int dispatch; +int workcount; +int oldf; +qboolean pacifier; + +qboolean threaded; + +/* +============= +GetThreadWork + +============= +*/ +int GetThreadWork (void) +{ + int r; + int f; + + ThreadLock (); + + if (dispatch == workcount) + { + ThreadUnlock (); + return -1; + } + + f = 10*dispatch / workcount; + if (f != oldf) + { + oldf = f; + if (pacifier) + printf ("%i...", f); + } + + r = dispatch; + dispatch++; + ThreadUnlock (); + + return r; +} + + +void (*workfunction) (int); + +void ThreadWorkerFunction (int threadnum) +{ + int work; + + while (1) + { + work = GetThreadWork (); + if (work == -1) + break; +//printf ("thread %i, work %i\n", threadnum, work); + workfunction(work); + } +} + +void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + if (numthreads == -1) + ThreadSetDefault (); + workfunction = func; + RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); +} + + +/* +=================================================================== + +WIN32 + +=================================================================== +*/ +#ifdef WIN32 + +#define USED + +#include + +int numthreads = -1; +CRITICAL_SECTION crit; +static int enter; + +void ThreadSetDefault (void) +{ + SYSTEM_INFO info; + + if (numthreads == -1) // not set manually + { + GetSystemInfo (&info); + numthreads = info.dwNumberOfProcessors; + if (numthreads < 1 || numthreads > 32) + numthreads = 1; + } + + qprintf ("%i threads\n", numthreads); +} + + +void ThreadLock (void) +{ + if (!threaded) + return; + EnterCriticalSection (&crit); + if (enter) + Error ("Recursive ThreadLock\n"); + enter = 1; +} + +void ThreadUnlock (void) +{ + if (!threaded) + return; + if (!enter) + Error ("ThreadUnlock without lock\n"); + enter = 0; + LeaveCriticalSection (&crit); +} + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int threadid[MAX_THREADS]; + HANDLE threadhandle[MAX_THREADS]; + int i; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + // + // run threads in parallel + // + InitializeCriticalSection (&crit); + + if (numthreads == 1) + { // use same thread + func (0); + } + else + { + for (i=0 ; i + +pthread_mutex_t *my_mutex; + +void ThreadLock (void) +{ + if (my_mutex) + pthread_mutex_lock (my_mutex); +} + +void ThreadUnlock (void) +{ + if (my_mutex) + pthread_mutex_unlock (my_mutex); +} + + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + pthread_t work_threads[MAX_THREADS]; + pthread_addr_t status; + pthread_attr_t attrib; + pthread_mutexattr_t mattrib; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (pacifier) + setbuf (stdout, NULL); + + if (!my_mutex) + { + my_mutex = malloc (sizeof(*my_mutex)); + if (pthread_mutexattr_create (&mattrib) == -1) + Error ("pthread_mutex_attr_create failed"); + if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) + Error ("pthread_mutexattr_setkind_np failed"); + if (pthread_mutex_init (my_mutex, mattrib) == -1) + Error ("pthread_mutex_init failed"); + } + + if (pthread_attr_create (&attrib) == -1) + Error ("pthread_attr_create failed"); + if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) + Error ("pthread_attr_setstacksize failed"); + + for (i=0 ; i +#include +#include +#include + + +int numthreads = -1; +abilock_t lck; + +void ThreadSetDefault (void) +{ + if (numthreads == -1) + numthreads = prctl(PR_MAXPPROCS); + printf ("%i threads\n", numthreads); +//@@ + usconfig (CONF_INITUSERS, numthreads); +} + + +void ThreadLock (void) +{ + spin_lock (&lck); +} + +void ThreadUnlock (void) +{ + release_lock (&lck); +} + + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + int pid[MAX_THREADS]; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (pacifier) + setbuf (stdout, NULL); + + init_lock (&lck); + + for (i=0 ; i +#include "cmdlib.h" +#include "mathlib.h" +#include "trilib.h" + +// on disk representation of a face + + +#define FLOAT_START 99999.0 +#define FLOAT_END -FLOAT_START +#define MAGIC 123322 + +//#define NOISY 1 + +typedef struct { + float v[3]; +} vector; + +typedef struct +{ + vector n; /* normal */ + vector p; /* point */ + vector c; /* color */ + float u; /* u */ + float v; /* v */ +} aliaspoint_t; + +typedef struct { + aliaspoint_t pt[3]; +} tf_triangle; + + +void ByteSwapTri (tf_triangle *tri) +{ + int i; + + for (i=0 ; iverts[j][k] = tri.pt[j].p.v[k]; + } + } + + ptri++; + + if ((ptri - *pptri) >= MAXTRIANGLES) + Error ("Error: too many triangles; increase MAXTRIANGLES\n"); + } + } + + *numtriangles = ptri - *pptri; + + fclose (input); +} + diff --git a/tools/quake2/extra/common/trilib.h b/tools/quake2/extra/common/trilib.h new file mode 100644 index 00000000..11ece3de --- /dev/null +++ b/tools/quake2/extra/common/trilib.h @@ -0,0 +1,33 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// +// trilib.h: header file for loading triangles from an Alias triangle file +// +#define MAXTRIANGLES 2048 + +typedef struct { + vec3_t verts[3]; +} triangle_t; + +void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles); + diff --git a/tools/quake2/extra/qdata/anorms.h b/tools/quake2/extra/qdata/anorms.h new file mode 100644 index 00000000..18da0abc --- /dev/null +++ b/tools/quake2/extra/qdata/anorms.h @@ -0,0 +1,184 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +{-0.525731, 0.000000, 0.850651}, +{-0.442863, 0.238856, 0.864188}, +{-0.295242, 0.000000, 0.955423}, +{-0.309017, 0.500000, 0.809017}, +{-0.162460, 0.262866, 0.951056}, +{0.000000, 0.000000, 1.000000}, +{0.000000, 0.850651, 0.525731}, +{-0.147621, 0.716567, 0.681718}, +{0.147621, 0.716567, 0.681718}, +{0.000000, 0.525731, 0.850651}, +{0.309017, 0.500000, 0.809017}, +{0.525731, 0.000000, 0.850651}, +{0.295242, 0.000000, 0.955423}, +{0.442863, 0.238856, 0.864188}, +{0.162460, 0.262866, 0.951056}, +{-0.681718, 0.147621, 0.716567}, +{-0.809017, 0.309017, 0.500000}, +{-0.587785, 0.425325, 0.688191}, +{-0.850651, 0.525731, 0.000000}, +{-0.864188, 0.442863, 0.238856}, +{-0.716567, 0.681718, 0.147621}, +{-0.688191, 0.587785, 0.425325}, +{-0.500000, 0.809017, 0.309017}, +{-0.238856, 0.864188, 0.442863}, +{-0.425325, 0.688191, 0.587785}, +{-0.716567, 0.681718, -0.147621}, +{-0.500000, 0.809017, -0.309017}, +{-0.525731, 0.850651, 0.000000}, +{0.000000, 0.850651, -0.525731}, +{-0.238856, 0.864188, -0.442863}, +{0.000000, 0.955423, -0.295242}, +{-0.262866, 0.951056, -0.162460}, +{0.000000, 1.000000, 0.000000}, +{0.000000, 0.955423, 0.295242}, +{-0.262866, 0.951056, 0.162460}, +{0.238856, 0.864188, 0.442863}, +{0.262866, 0.951056, 0.162460}, +{0.500000, 0.809017, 0.309017}, +{0.238856, 0.864188, -0.442863}, +{0.262866, 0.951056, -0.162460}, +{0.500000, 0.809017, -0.309017}, +{0.850651, 0.525731, 0.000000}, +{0.716567, 0.681718, 0.147621}, +{0.716567, 0.681718, -0.147621}, +{0.525731, 0.850651, 0.000000}, +{0.425325, 0.688191, 0.587785}, +{0.864188, 0.442863, 0.238856}, +{0.688191, 0.587785, 0.425325}, +{0.809017, 0.309017, 0.500000}, +{0.681718, 0.147621, 0.716567}, +{0.587785, 0.425325, 0.688191}, +{0.955423, 0.295242, 0.000000}, +{1.000000, 0.000000, 0.000000}, +{0.951056, 0.162460, 0.262866}, +{0.850651, -0.525731, 0.000000}, +{0.955423, -0.295242, 0.000000}, +{0.864188, -0.442863, 0.238856}, +{0.951056, -0.162460, 0.262866}, +{0.809017, -0.309017, 0.500000}, +{0.681718, -0.147621, 0.716567}, +{0.850651, 0.000000, 0.525731}, +{0.864188, 0.442863, -0.238856}, +{0.809017, 0.309017, -0.500000}, +{0.951056, 0.162460, -0.262866}, +{0.525731, 0.000000, -0.850651}, +{0.681718, 0.147621, -0.716567}, +{0.681718, -0.147621, -0.716567}, +{0.850651, 0.000000, -0.525731}, +{0.809017, -0.309017, -0.500000}, +{0.864188, -0.442863, -0.238856}, +{0.951056, -0.162460, -0.262866}, +{0.147621, 0.716567, -0.681718}, +{0.309017, 0.500000, -0.809017}, +{0.425325, 0.688191, -0.587785}, +{0.442863, 0.238856, -0.864188}, +{0.587785, 0.425325, -0.688191}, +{0.688191, 0.587785, -0.425325}, +{-0.147621, 0.716567, -0.681718}, +{-0.309017, 0.500000, -0.809017}, +{0.000000, 0.525731, -0.850651}, +{-0.525731, 0.000000, -0.850651}, +{-0.442863, 0.238856, -0.864188}, +{-0.295242, 0.000000, -0.955423}, +{-0.162460, 0.262866, -0.951056}, +{0.000000, 0.000000, -1.000000}, +{0.295242, 0.000000, -0.955423}, +{0.162460, 0.262866, -0.951056}, +{-0.442863, -0.238856, -0.864188}, +{-0.309017, -0.500000, -0.809017}, +{-0.162460, -0.262866, -0.951056}, +{0.000000, -0.850651, -0.525731}, +{-0.147621, -0.716567, -0.681718}, +{0.147621, -0.716567, -0.681718}, +{0.000000, -0.525731, -0.850651}, +{0.309017, -0.500000, -0.809017}, +{0.442863, -0.238856, -0.864188}, +{0.162460, -0.262866, -0.951056}, +{0.238856, -0.864188, -0.442863}, +{0.500000, -0.809017, -0.309017}, +{0.425325, -0.688191, -0.587785}, +{0.716567, -0.681718, -0.147621}, +{0.688191, -0.587785, -0.425325}, +{0.587785, -0.425325, -0.688191}, +{0.000000, -0.955423, -0.295242}, +{0.000000, -1.000000, 0.000000}, +{0.262866, -0.951056, -0.162460}, +{0.000000, -0.850651, 0.525731}, +{0.000000, -0.955423, 0.295242}, +{0.238856, -0.864188, 0.442863}, +{0.262866, -0.951056, 0.162460}, +{0.500000, -0.809017, 0.309017}, +{0.716567, -0.681718, 0.147621}, +{0.525731, -0.850651, 0.000000}, +{-0.238856, -0.864188, -0.442863}, +{-0.500000, -0.809017, -0.309017}, +{-0.262866, -0.951056, -0.162460}, +{-0.850651, -0.525731, 0.000000}, +{-0.716567, -0.681718, -0.147621}, +{-0.716567, -0.681718, 0.147621}, +{-0.525731, -0.850651, 0.000000}, +{-0.500000, -0.809017, 0.309017}, +{-0.238856, -0.864188, 0.442863}, +{-0.262866, -0.951056, 0.162460}, +{-0.864188, -0.442863, 0.238856}, +{-0.809017, -0.309017, 0.500000}, +{-0.688191, -0.587785, 0.425325}, +{-0.681718, -0.147621, 0.716567}, +{-0.442863, -0.238856, 0.864188}, +{-0.587785, -0.425325, 0.688191}, +{-0.309017, -0.500000, 0.809017}, +{-0.147621, -0.716567, 0.681718}, +{-0.425325, -0.688191, 0.587785}, +{-0.162460, -0.262866, 0.951056}, +{0.442863, -0.238856, 0.864188}, +{0.162460, -0.262866, 0.951056}, +{0.309017, -0.500000, 0.809017}, +{0.147621, -0.716567, 0.681718}, +{0.000000, -0.525731, 0.850651}, +{0.425325, -0.688191, 0.587785}, +{0.587785, -0.425325, 0.688191}, +{0.688191, -0.587785, 0.425325}, +{-0.955423, 0.295242, 0.000000}, +{-0.951056, 0.162460, 0.262866}, +{-1.000000, 0.000000, 0.000000}, +{-0.850651, 0.000000, 0.525731}, +{-0.955423, -0.295242, 0.000000}, +{-0.951056, -0.162460, 0.262866}, +{-0.864188, 0.442863, -0.238856}, +{-0.951056, 0.162460, -0.262866}, +{-0.809017, 0.309017, -0.500000}, +{-0.864188, -0.442863, -0.238856}, +{-0.951056, -0.162460, -0.262866}, +{-0.809017, -0.309017, -0.500000}, +{-0.681718, 0.147621, -0.716567}, +{-0.681718, -0.147621, -0.716567}, +{-0.850651, 0.000000, -0.525731}, +{-0.688191, 0.587785, -0.425325}, +{-0.587785, 0.425325, -0.688191}, +{-0.425325, 0.688191, -0.587785}, +{-0.425325, -0.688191, -0.587785}, +{-0.587785, -0.425325, -0.688191}, +{-0.688191, -0.587785, -0.425325}, diff --git a/tools/quake2/extra/qdata/images.c b/tools/quake2/extra/qdata/images.c new file mode 100644 index 00000000..90934f13 --- /dev/null +++ b/tools/quake2/extra/qdata/images.c @@ -0,0 +1,763 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qdata.h" + +char mip_prefix[1024]; // directory to dump the textures in + +qboolean colormap_issued; +byte colormap_palette[768]; + +/* +============== +RemapZero + +Replaces all 0 bytes in an image with the closest palette entry. +This is because NT won't let us change index 0, so any palette +animation leaves those pixels untouched. +============== +*/ +void RemapZero (byte *pixels, byte *palette, int width, int height) +{ + int i, c; + int alt_zero; + int value, best; + + alt_zero = 0; + best = 9999999; + for (i=1 ; i<255 ; i++) + { + value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2]; + if (value < best) + { + best = value; + alt_zero = i; + } + } + + c = width*height; + for (i=0 ; ibyteimagewidth || yl+h>byteimageheight) + Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h); + + // crop it to the proper size + cropped = malloc (w*h); + for (y=0 ; ybyteimagewidth || yl+h>byteimageheight) + Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h); + + // crop it to the proper size + cropped = malloc (w*h); + for (y=0 ; y 255) + r = 255; + if (r < 0) + r = 0; + if (g > 255) + g = 255; + if (g < 0) + g = 0; + if (b > 255) + b = 255; + if (b < 0) + b = 0; +#ifndef TABLECOLORS + bestcolor = BestColor (r, g, b, 0, 254); +#else + bestcolor = palmap[r>>3][g>>3][b>>3]; +#endif + + return bestcolor; +} + + +void BuildPalmap (void) +{ +#ifdef TABLECOLORS + int r, g, b; + int bestcolor; + + if (palmap_built) + return; + palmap_built = true; + + for (r=4 ; r<256 ; r+=8) + { + for (g=4 ; g<256 ; g+=8) + { + for (b=4 ; b<256 ; b+=8) + { + bestcolor = BestColor (r, g, b, 1, 254); + palmap[r>>3][g>>3][b>>3] = bestcolor; + } + } + } +#endif + + if (!colormap_issued) + Error ("You must issue a $colormap command first"); + +} + +/* +============= +AveragePixels +============= +*/ +byte AveragePixels (int count) +{ + int r,g,b; + int i; + int vis; + int pix; + int bestcolor; + byte *pal; + int fullbright; + + vis = 0; + r = g = b = 0; + fullbright = 0; + for (i=0 ; i +must be multiples of sixteen +SURF_WINDOW +============== +*/ +void Cmd_Mip (void) +{ + int x,y,xl,yl,xh,yh,w,h; + byte *screen_p, *source; + int linedelta; + miptex_t *qtex; + int miplevel, mipstep; + int xx, yy, pix; + int count; + int flags, value, contents; + mipparm_t *mp; + char lumpname[64]; + byte *lump_p; + char filename[1024]; + char animname[64]; + + GetToken (false); + strcpy (lumpname, token); + + GetToken (false); + xl = atoi (token); + GetToken (false); + yl = atoi (token); + GetToken (false); + w = atoi (token); + GetToken (false); + h = atoi (token); + + if ( (w & 15) || (h & 15) ) + Error ("line %i: miptex sizes must be multiples of 16", scriptline); + + flags = 0; + contents = 0; + value = 0; + + animname[0] = 0; + + // get optional flags and values + while (TokenAvailable ()) + { + GetToken (false); + + for (mp=mipparms ; mp->name ; mp++) + { + if (!strcmp(mp->name, token)) + { + switch (mp->type) + { + case pt_animvalue: + GetToken (false); // specify the next animation frame + strcpy (animname, token); + break; + case pt_flags: + flags |= mp->flags; + break; + case pt_contents: + contents |= mp->flags; + break; + case pt_flagvalue: + flags |= mp->flags; + GetToken (false); // specify the light value + value = atoi(token); + break; + } + break; + } + } + if (!mp->name) + Error ("line %i: unknown parm %s", scriptline, token); + } + + sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname); + if (g_release) + return; // textures are only released by $maps + + xh = xl+w; + yh = yl+h; + + qtex = malloc (sizeof(miptex_t) + w*h*2); + memset (qtex, 0, sizeof(miptex_t)); + + qtex->width = LittleLong(w); + qtex->height = LittleLong(h); + qtex->flags = LittleLong(flags); + qtex->contents = LittleLong(contents); + qtex->value = LittleLong(value); + sprintf (qtex->name, "%s/%s", mip_prefix, lumpname); + if (animname[0]) + sprintf (qtex->animname, "%s/%s", mip_prefix, animname); + + lump_p = (byte *)(&qtex->value+1); + + screen_p = byteimage + yl*byteimagewidth + xl; + linedelta = byteimagewidth - w; + + source = lump_p; + qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex); + + for (y=yl ; yoffsets[miplevel] = LittleLong(lump_p - (byte *)qtex); + + mipstep = 1< /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/models.o : models.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/sprites.o : sprites.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/images.o : images.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/tables.o : tables.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i + +$(ODIR)/cmdlib.o : ../common/cmdlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/scriplib.o : ../common/scriplib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/lbmlib.o : ../common/lbmlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/mathlib.o : ../common/mathlib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/trilib.o : ../common/trilib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/l3dslib.o : ../common/l3dslib.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i +$(ODIR)/threads.o : ../common/threads.c + cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i + cc $(CFLAGS) -o $@ /tmp/temp.i diff --git a/tools/quake2/extra/qdata/models.c b/tools/quake2/extra/qdata/models.c new file mode 100644 index 00000000..d6922cb7 --- /dev/null +++ b/tools/quake2/extra/qdata/models.c @@ -0,0 +1,1152 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qdata.h" + +//================================================================= + +typedef struct +{ + int numnormals; + vec3_t normalsum; +} vertexnormals_t; + +typedef struct +{ + vec3_t v; + int lightnormalindex; +} trivert_t; + +typedef struct +{ + vec3_t mins, maxs; + char name[16]; + trivert_t v[MAX_VERTS]; +} frame_t; + +//================================================================ + +frame_t g_frames[MAX_FRAMES]; + +dmdl_t model; + + +float scale_up; // set by $scale +vec3_t adjust; // set by $origin +int g_fixedwidth, g_fixedheight; // set by $skinsize + + +// +// base frame info +// +vec3_t base_xyz[MAX_VERTS]; +dstvert_t base_st[MAX_VERTS]; +dtriangle_t triangles[MAX_TRIANGLES]; + +int triangle_st[MAX_TRIANGLES][3][2]; + +// the command list holds counts, s/t values, and xyz indexes +// that are valid for every frame +int commands[16384]; +int numcommands; +int numglverts; +int used[MAX_TRIANGLES]; + +char g_skins[MAX_MD2SKINS][64]; + +char cdarchive[1024]; +char cdpartial[1024]; +char cddir[1024]; + +char modelname[64]; // empty unless $modelname issued (players) + +#define NUMVERTEXNORMALS 162 + +float avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + +FILE *headerouthandle = NULL; + +//============================================================== + +/* +=============== +ClearModel +=============== +*/ +void ClearModel (void) +{ + memset (&model, 0, sizeof(model)); + + modelname[0] = 0; + scale_up = 1.0; + VectorCopy (vec3_origin, adjust); + g_fixedwidth = g_fixedheight = 0; + g_skipmodel = false; +} + + +void H_printf(char *fmt, ...) +{ + va_list argptr; + char name[1024]; + + if (!headerouthandle) + { + sprintf (name, "%s/tris.h", cddir); + headerouthandle = SafeOpenWrite (name); + fprintf(headerouthandle, "// %s\n\n", cddir); + fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n"); + } + + va_start (argptr, fmt); + vfprintf (headerouthandle, fmt, argptr); + va_end (argptr); +} + + +/* +============ +WriteModelFile +============ +*/ +void WriteModelFile (FILE *modelouthandle) +{ + int i; + dmdl_t modeltemp; + int j, k; + frame_t *in; + daliasframe_t *out; + byte buffer[MAX_VERTS*4+128]; + float v; + int c_on, c_off; + + model.ident = IDALIASHEADER; + model.version = ALIAS_VERSION; + model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz]; + model.num_glcmds = numcommands; + model.ofs_skins = sizeof(dmdl_t); + model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME; + model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t); + model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t); + model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize; + model.ofs_end = model.ofs_glcmds + model.num_glcmds*4; + + // + // write out the model header + // + for (i=0 ; iname, in->name); + for (j=0 ; j<3 ; j++) + { + out->scale[j] = (in->maxs[j] - in->mins[j])/255; + out->translate[j] = in->mins[j]; + } + + for (j=0 ; jverts[j].lightnormalindex = in->v[j].lightnormalindex; + + for (k=0 ; k<3 ; k++) + { + // scale to byte values & min/max check + v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] ); + + // clamp, so rounding doesn't wrap from 255.6 to 0 + if (v > 255.0) + v = 255.0; + if (v < 0) + v = 0; + out->verts[j].v[k] = v; + } + } + + for (j=0 ; j<3 ; j++) + { + out->scale[j] = LittleFloat (out->scale[j]); + out->translate[j] = LittleFloat (out->translate[j]); + } + + SafeWrite (modelouthandle, out, model.framesize); + } + + // + // write out glcmds + // + SafeWrite (modelouthandle, commands, numcommands*4); +} + + +/* +=============== +FinishModel +=============== +*/ +void FinishModel (void) +{ + FILE *modelouthandle; + int i; + char name[1024]; + + if (!model.num_frames) + return; + +// +// copy to release directory tree if doing a release build +// + if (g_release) + { + if (modelname[0]) + sprintf (name, "%s", modelname); + else + sprintf (name, "%s/tris.md2", cdpartial); + ReleaseFile (name); + + for (i=0 ; iindex_xyz[(startv)%3]; + strip_xyz[1] = last->index_xyz[(startv+1)%3]; + strip_xyz[2] = last->index_xyz[(startv+2)%3]; + strip_st[0] = last->index_st[(startv)%3]; + strip_st[1] = last->index_st[(startv+1)%3]; + strip_st[2] = last->index_st[(startv+2)%3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[(startv+2)%3]; + st1 = last->index_st[(startv+2)%3]; + m2 = last->index_xyz[(startv+1)%3]; + st2 = last->index_st[(startv+1)%3]; + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] + ; jindex_xyz[k] != m1) + continue; + if (check->index_st[k] != st1) + continue; + if (check->index_xyz[ (k+1)%3 ] != m2) + continue; + if (check->index_st[ (k+1)%3 ] != st2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + if (stripcount & 1) + { + m2 = check->index_xyz[ (k+2)%3 ]; + st2 = check->index_st[ (k+2)%3 ]; + } + else + { + m1 = check->index_xyz[ (k+2)%3 ]; + st1 = check->index_st[ (k+2)%3 ]; + } + + strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ]; + strip_st[stripcount+2] = check->index_st[ (k+2)%3 ]; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jindex_xyz[(startv)%3]; + strip_xyz[1] = last->index_xyz[(startv+1)%3]; + strip_xyz[2] = last->index_xyz[(startv+2)%3]; + strip_st[0] = last->index_st[(startv)%3]; + strip_st[1] = last->index_st[(startv+1)%3]; + strip_st[2] = last->index_st[(startv+2)%3]; + + strip_tris[0] = starttri; + stripcount = 1; + + m1 = last->index_xyz[(startv+0)%3]; + st1 = last->index_st[(startv+0)%3]; + m2 = last->index_xyz[(startv+2)%3]; + st2 = last->index_st[(startv+2)%3]; + + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] + ; jindex_xyz[k] != m1) + continue; + if (check->index_st[k] != st1) + continue; + if (check->index_xyz[ (k+1)%3 ] != m2) + continue; + if (check->index_st[ (k+1)%3 ] != st2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + m2 = check->index_xyz[ (k+2)%3 ]; + st2 = check->index_st[ (k+2)%3 ]; + + strip_xyz[stripcount+2] = m2; + strip_st[stripcount+2] = st2; + strip_tris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; j bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; j= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + + s_scale = t_scale = scale; + + iwidth = ceil(width*s_scale); + iheight = ceil(height*t_scale); + + iwidth += 4; + iheight += 4; + } + else + { // new style + iwidth = g_fixedwidth / 2; + iheight = g_fixedheight; + + s_scale = (float)(iwidth-4) / width; + t_scale = (float)(iheight-4) / height; + } + +// +// determine which side of each triangle to map the texture to +// + for (i=0 ; i 0) + { + basex = iwidth + 2; + } + else + { + basex = 2; + } + basey = 2; + + for (j=0 ; j<3 ; j++) + { + pbasevert = ptri[i].verts[j]; + + triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex); + triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey); + } + } + +// make the width a multiple of 4; some hardware requires this, and it ensures +// dword alignment for each scan + swidth = iwidth*2; + model.skinwidth = (swidth + 3) & ~3; + model.skinheight = iheight; +} + + +/* +================= +Cmd_Base +================= +*/ +void Cmd_Base (void) +{ + triangle_t *ptri; + int i, j, k; + int time1; + char file1[1024]; + + GetToken (false); + + if (g_skipmodel || g_release || g_archive) + return; + + printf ("---------------------\n"); + sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext); + printf ("%s\n", file1); + + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s.%s", cddir, token, trifileext); + + time1 = FileTime (file1); + if (time1 == -1) + Error ("%s doesn't exist", file1); + +// +// load the base triangles +// + if (do3ds) + Load3DSTriangleList (file1, &ptri, &model.num_tris); + else + LoadTriangleList (file1, &ptri, &model.num_tris); + +// +// get the ST values +// + BuildST (ptri, model.num_tris); + +// +// run through all the base triangles, storing each unique vertex in the +// base vertex list and setting the indirect triangles to point to the base +// vertices +// + for (i=0 ; i= '0' && *s <= '9') + s--; + + strcpy (suffix, s+1); + strcpy (base, frame); + base[s-frame+1] = 0; + + // check for 'run1.tri' + sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, trifileext); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s%s.%s", base, suffix, trifileext); + return retname; + } + + // check for 'run.1' + sprintf (file1, "%s/%s.%s",cddir, base, suffix); + time1 = FileTime (file1); + if (time1 != -1) + { + sprintf (retname, "%s.%s", base, suffix); + return retname; + } + + Error ("frame %s could not be found",frame); + return NULL; +} + +/* +=============== +GrabFrame +=============== +*/ +void GrabFrame (char *frame) +{ + triangle_t *ptri; + int i, j; + trivert_t *ptrivert; + int num_tris; + char file1[1024]; + frame_t *fr; + vertexnormals_t vnorms[MAX_VERTS]; + int index_xyz; + char *framefile; + + // the frame 'run1' will be looked for as either + // run.1 or run1.tri, so the new alias sequence save + // feature an be used + framefile = FindFrameFile (frame); + + sprintf (file1, "%s/%s", cdarchive, framefile); + ExpandPathAndArchive (file1); + + sprintf (file1, "%s/%s",cddir, framefile); + + printf ("grabbing %s\n", file1); + + if (model.num_frames >= MAX_FRAMES) + Error ("model.num_frames >= MAX_FRAMES"); + fr = &g_frames[model.num_frames]; + model.num_frames++; + + strcpy (fr->name, frame); + +// +// load the frame +// + if (do3ds) + Load3DSTriangleList (file1, &ptri, &num_tris); + else + LoadTriangleList (file1, &ptri, &num_tris); + + if (num_tris != model.num_tris) + Error ("%s: number of triangles doesn't match base frame\n", file1); + +// +// allocate storage for the frame's vertices +// + ptrivert = fr->v; + + for (i=0 ; imins, fr->maxs); + +// +// store the frame's vertices in the same order as the base. This assumes the +// triangles and vertices in this frame are in exactly the same order as in the +// base +// + for (i=0 ; imins, fr->maxs); + + VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum); + vnorms[index_xyz].numnormals++; + } + } + +// +// calculate the vertex normals, match them to the template list, and store the +// index of the best match +// + for (i=0 ; i maxdot) + { + maxdot = dot; + maxdotindex = j; + } + } + + ptrivert[i].lightnormalindex = maxdotindex; + } + + free (ptri); +} + +/* +=============== +Cmd_Frame +=============== +*/ +void Cmd_Frame (void) +{ + while (TokenAvailable()) + { + GetToken (false); + if (g_skipmodel) + continue; + if (g_release || g_archive) + { + model.num_frames = 1; // don't skip the writeout + continue; + } + + H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames); + + GrabFrame (token); + } +} + + +/* +=============== +Cmd_Skin + +Skins aren't actually stored in the file, only a reference +is saved out to the header file. +=============== +*/ +void Cmd_Skin (void) +{ + byte *palette; + byte *pixels; + int width, height; + byte *cropped; + int y; + char name[1024], savename[1024]; + + GetToken (false); + + if (model.num_skins == MAX_MD2SKINS) + Error ("model.num_skins == MAX_MD2SKINS"); + + if (g_skipmodel) + return; + + sprintf (name, "%s/%s.lbm", cdarchive, token); + strcpy (name, ExpandPathAndArchive( name ) ); +// sprintf (name, "%s/%s.lbm", cddir, token); + + if (TokenAvailable()) + { + GetToken (false); + sprintf (g_skins[model.num_skins], "%s.pcx", token); + sprintf (savename, "%s%s.pcx", gamedir, g_skins[model.num_skins]); + } + else + { + sprintf (savename, "%s/%s.pcx", cddir, token); + sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token); + } + + model.num_skins++; + + if (g_skipmodel || g_release || g_archive) + return; + + // load the image + printf ("loading %s\n", name); + Load256Image (name, &pixels, &palette, &width, &height); + RemapZero (pixels, palette, width, height); + + // crop it to the proper size + cropped = malloc (model.skinwidth*model.skinheight); + for (y=0 ; y= sizeof(pf->name)) + Error ("Filename too long for pak: %s", filename); + + len = LoadFile (source, (void **)&buf); + + if (g_compress_pak && len < 4096*1024 ) + { + cblock_t in, out; + cblock_t Huffman (cblock_t in); + + in.count = len; + in.data = buf; + + out = Huffman (in); + + if (out.count < in.count) + { + printf (" compressed from %i to %i\n", in.count, out.count); + free (in.data); + buf = out.data; + len = out.count; + } + else + free (out.data); + } + + strcpy (pf->name, filename); + pf->filepos = LittleLong(ftell(pakfile)); + pf->filelen = LittleLong(len); + pf++; + + SafeWrite (pakfile, buf, len); + + free (buf); +} + + +/* +============== +FinishPak +============== +*/ +void FinishPak (void) +{ + int dirlen; + int d; + int i; + unsigned checksum; + + if (!g_pak) + return; + + pakheader.id[0] = 'P'; + pakheader.id[1] = 'A'; + pakheader.id[2] = 'C'; + pakheader.id[3] = 'K'; + dirlen = (byte *)pf - (byte *)pfiles; + pakheader.dirofs = LittleLong(ftell(pakfile)); + pakheader.dirlen = LittleLong(dirlen); + + checksum = Com_BlockChecksum ( (void *)pfiles, dirlen ); + + SafeWrite (pakfile, pfiles, dirlen); + + i = ftell (pakfile); + + fseek (pakfile, 0, SEEK_SET); + SafeWrite (pakfile, &pakheader, sizeof(pakheader)); + fclose (pakfile); + + d = pf - pfiles; + printf ("%i files packed in %i bytes\n",d, i); + printf ("checksum: 0x%x\n", checksum); +} + + +/* +=============== +Cmd_File + +This is only used to cause a file to be copied during a release +build (default.cfg, maps, etc) +=============== +*/ +void Cmd_File (void) +{ + GetToken (false); + ReleaseFile (token); +} + +/* +=============== +PackDirectory_r + +=============== +*/ +#ifdef _WIN32 +#include "io.h" +void PackDirectory_r (char *dir) +{ + struct _finddata_t fileinfo; + int handle; + char dirstring[1024]; + char filename[1024]; + + sprintf (dirstring, "%s%s/*.*", gamedir, dir); + + handle = _findfirst (dirstring, &fileinfo); + if (handle == -1) + return; + + do + { + sprintf (filename, "%s/%s", dir, fileinfo.name); + if (fileinfo.attrib & _A_SUBDIR) + { // directory + if (fileinfo.name[0] != '.') // don't pak . and .. + PackDirectory_r (filename); + continue; + } + // copy or pack the file + ReleaseFile (filename); + } while (_findnext( handle, &fileinfo ) != -1); + + _findclose (handle); +} +#else + +#include +#ifdef NeXT +#include +#else +#include +#endif + +void PackDirectory_r (char *dir) +{ +#ifdef NeXT + struct direct **namelist, *ent; +#else + struct dirent **namelist, *ent; +#endif + int count; + struct stat st; + int i; + int len; + char fullname[1024]; + char dirstring[1024]; + char *name; + + sprintf (dirstring, "%s%s", gamedir, dir); + count = scandir(dirstring, &namelist, NULL, NULL); + + for (i=0 ; id_name; + + if (name[0] == '.') + continue; + + sprintf (fullname, "%s/%s", dir, name); + sprintf (dirstring, "%s%s/%s", gamedir, dir, name); + + if (stat (dirstring, &st) == -1) + Error ("fstating %s", pf->name); + if (st.st_mode & S_IFDIR) + { // directory + PackDirectory_r (fullname); + continue; + } + + // copy or pack the file + ReleaseFile (fullname); + } +} +#endif + + +/* +=============== +Cmd_Dir + +This is only used to cause a directory to be copied during a +release build (sounds, etc) +=============== +*/ +void Cmd_Dir (void) +{ + GetToken (false); + PackDirectory_r (token); +} + +//======================================================================== + +#define MAX_RTEX 16384 +int numrtex; +char rtex[MAX_RTEX][64]; + +void ReleaseTexture (char *name) +{ + int i; + char path[1024]; + + for (i=0 ; i= argc) + Error ("usage: qgrab [-archive ] [-release ] [-only ] [-3ds] file.qgr"); + + if (do3ds) + trifileext = ext_3ds; + else + trifileext = ext_tri; + + for ( ; i +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=qdata - 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 "qdata.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 "qdata.mak" CFG="qdata - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "qdata - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "qdata - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "qdata - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "qdata - 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" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "qdata - Win32 Release" +# Name "qdata - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\common\bspfile.c +# End Source File +# Begin Source File + +SOURCE=..\common\cmdlib.c +# End Source File +# Begin Source File + +SOURCE=.\images.c +# End Source File +# Begin Source File + +SOURCE=..\common\l3dslib.c +# End Source File +# Begin Source File + +SOURCE=..\common\lbmlib.c +# End Source File +# Begin Source File + +SOURCE=..\common\mathlib.c +# End Source File +# Begin Source File + +SOURCE=..\common\mdfour.c +# End Source File +# Begin Source File + +SOURCE=.\models.c +# End Source File +# Begin Source File + +SOURCE=.\qdata.c +# End Source File +# Begin Source File + +SOURCE=..\common\scriplib.c +# End Source File +# Begin Source File + +SOURCE=.\sprites.c +# End Source File +# Begin Source File + +SOURCE=.\tables.c +# End Source File +# Begin Source File + +SOURCE=..\common\threads.c +# End Source File +# Begin Source File + +SOURCE=..\common\trilib.c +# End Source File +# Begin Source File + +SOURCE=.\video.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\anorms.h +# End Source File +# Begin Source File + +SOURCE=..\common\bspfile.h +# End Source File +# Begin Source File + +SOURCE=..\common\cmdlib.h +# End Source File +# Begin Source File + +SOURCE=..\common\l3dslib.h +# End Source File +# Begin Source File + +SOURCE=..\common\lbmlib.h +# End Source File +# Begin Source File + +SOURCE=..\common\mathlib.h +# End Source File +# Begin Source File + +SOURCE=.\modelgen.h +# End Source File +# Begin Source File + +SOURCE=.\qdata.h +# End Source File +# Begin Source File + +SOURCE=..\common\qfiles.h +# End Source File +# Begin Source File + +SOURCE=..\common\scriplib.h +# End Source File +# Begin Source File + +SOURCE=..\common\threads.h +# End Source File +# Begin Source File + +SOURCE=..\common\trilib.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/tools/quake2/extra/qdata/qdata.dsw b/tools/quake2/extra/qdata/qdata.dsw new file mode 100644 index 00000000..5a1c558b --- /dev/null +++ b/tools/quake2/extra/qdata/qdata.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "qdata"=.\qdata.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/tools/quake2/extra/qdata/qdata.h b/tools/quake2/extra/qdata/qdata.h new file mode 100644 index 00000000..bd8e63c3 --- /dev/null +++ b/tools/quake2/extra/qdata/qdata.h @@ -0,0 +1,89 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// qdata.h + + +#include +#include +#include +#include +#include + +#include "cmdlib.h" +#include "scriplib.h" +#include "mathlib.h" +#include "trilib.h" +#include "lbmlib.h" +#include "threads.h" +#include "l3dslib.h" +#include "bspfile.h" + +void Cmd_Modelname (void); +void Cmd_Base (void); +void Cmd_Cd (void); +void Cmd_Origin (void); +void Cmd_ScaleUp (void); +void Cmd_Frame (void); +void Cmd_Modelname (void); +void Cmd_Skin (void); +void Cmd_Skinsize (void); +void FinishModel (void); + +void Cmd_Inverse16Table( void ); + +void Cmd_SpriteName (void); +void Cmd_Load (void); +void Cmd_SpriteFrame (void); +void FinishSprite (void); + +void Cmd_Grab (void); +void Cmd_Raw (void); +void Cmd_Mip (void); +void Cmd_Environment (void); +void Cmd_Colormap (void); + +void Cmd_File (void); +void Cmd_Dir (void); +void Cmd_StartWad (void); +void Cmd_EndWad (void); +void Cmd_Mippal (void); +void Cmd_Mipdir (void); +void Cmd_Alphalight (void); + +void Cmd_Video (void); + +void RemapZero (byte *pixels, byte *palette, int width, int height); + +void ReleaseFile (char *filename); + +extern byte *byteimage, *lbmpalette; +extern int byteimagewidth, byteimageheight; + +extern qboolean g_release; // don't grab, copy output data to new tree +extern char g_releasedir[1024]; // c:\quake2\baseq2, etc +extern qboolean g_archive; // don't grab, copy source data to new tree +extern qboolean do3ds; +extern char g_only[256]; // if set, only grab this cd +extern qboolean g_skipmodel; // set true when a cd is not g_only + +extern char *trifileext; diff --git a/tools/quake2/extra/qdata/qdata.mak b/tools/quake2/extra/qdata/qdata.mak new file mode 100644 index 00000000..5639dab1 --- /dev/null +++ b/tools/quake2/extra/qdata/qdata.mak @@ -0,0 +1,549 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=qdata - Win32 Debug +!MESSAGE No configuration specified. Defaulting to qdata - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "qdata - Win32 Release" && "$(CFG)" != "qdata - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "qdata.mak" CFG="qdata - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "qdata - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "qdata - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "qdata - Win32 Debug" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "qdata - 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 "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\qdata.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\images.obj" + -@erase "$(INTDIR)\l3dslib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\models.obj" + -@erase "$(INTDIR)\qdata.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\sprites.obj" + -@erase "$(INTDIR)\tables.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\trilib.obj" + -@erase "$(OUTDIR)\qdata.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I "../common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "../common" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /Fp"$(INTDIR)/qdata.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qdata.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)/qdata.pdb" /machine:I386 /out:"$(OUTDIR)/qdata.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\images.obj" \ + "$(INTDIR)\l3dslib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\models.obj" \ + "$(INTDIR)\qdata.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\sprites.obj" \ + "$(INTDIR)\tables.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\trilib.obj" + +"$(OUTDIR)\qdata.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qdata - 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 "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\qdata.exe" + +CLEAN : + -@erase "$(INTDIR)\bspfile.obj" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\images.obj" + -@erase "$(INTDIR)\l3dslib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\models.obj" + -@erase "$(INTDIR)\qdata.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\sprites.obj" + -@erase "$(INTDIR)\tables.obj" + -@erase "$(INTDIR)\threads.obj" + -@erase "$(INTDIR)\trilib.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\qdata.exe" + -@erase "$(OUTDIR)\qdata.ilk" + -@erase "$(OUTDIR)\qdata.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "../common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "../common" /D "WIN32" /D "_DEBUG"\ + /D "_CONSOLE" /Fp"$(INTDIR)/qdata.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qdata.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)/qdata.pdb" /debug /machine:I386 /out:"$(OUTDIR)/qdata.exe" +LINK32_OBJS= \ + "$(INTDIR)\bspfile.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\images.obj" \ + "$(INTDIR)\l3dslib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\models.obj" \ + "$(INTDIR)\qdata.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\sprites.obj" \ + "$(INTDIR)\tables.obj" \ + "$(INTDIR)\threads.obj" \ + "$(INTDIR)\trilib.obj" + +"$(OUTDIR)\qdata.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "qdata - Win32 Release" +# Name "qdata - Win32 Debug" + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\images.c +DEP_CPP_IMAGE=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\lbmlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + ".\../common\threads.h"\ + ".\../common\trilib.h"\ + ".\qdata.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\images.obj" : $(SOURCE) $(DEP_CPP_IMAGE) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\modelgen.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qdata.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\sprites.c +DEP_CPP_SPRIT=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\lbmlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + ".\../common\threads.h"\ + ".\../common\trilib.h"\ + ".\qdata.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\sprites.obj" : $(SOURCE) $(DEP_CPP_SPRIT) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\l3dslib.c +DEP_CPP_L3DSL=\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\mathlib.h"\ + ".\../common\trilib.h"\ + + +"$(INTDIR)\l3dslib.obj" : $(SOURCE) $(DEP_CPP_L3DSL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\lbmlib.c +DEP_CPP_LBMLI=\ + ".\../common\cmdlib.h"\ + ".\../common\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.c +DEP_CPP_MATHL=\ + ".\../common\cmdlib.h"\ + ".\../common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\scriplib.c +DEP_CPP_SCRIP=\ + ".\../common\cmdlib.h"\ + ".\../common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\threads.c +DEP_CPP_THREA=\ + ".\../common\cmdlib.h"\ + ".\../common\threads.h"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\threads.obj" : $(SOURCE) $(DEP_CPP_THREA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\trilib.c +DEP_CPP_TRILI=\ + ".\../common\cmdlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\trilib.h"\ + + +"$(INTDIR)\trilib.obj" : $(SOURCE) $(DEP_CPP_TRILI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.c +DEP_CPP_CMDLI=\ + ".\../common\cmdlib.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\models.c +DEP_CPP_MODEL=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\lbmlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + ".\../common\threads.h"\ + ".\../common\trilib.h"\ + ".\anorms.h"\ + ".\qdata.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\models.obj" : $(SOURCE) $(DEP_CPP_MODEL) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qdata.c +DEP_CPP_QDATA=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\lbmlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + ".\../common\threads.h"\ + ".\../common\trilib.h"\ + ".\qdata.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\qdata.obj" : $(SOURCE) $(DEP_CPP_QDATA) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\mathlib.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\lbmlib.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\cmdlib.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\tables.c +DEP_CPP_TABLE=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\l3dslib.h"\ + ".\../common\lbmlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + ".\../common\threads.h"\ + ".\../common\trilib.h"\ + ".\qdata.h"\ + {$(INCLUDE)}"\sys\STAT.H"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + + +"$(INTDIR)\tables.obj" : $(SOURCE) $(DEP_CPP_TABLE) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\qfiles.h + +!IF "$(CFG)" == "qdata - Win32 Release" + +!ELSEIF "$(CFG)" == "qdata - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=..\common\bspfile.c +DEP_CPP_BSPFI=\ + "..\common\qfiles.h"\ + ".\../common\bspfile.h"\ + ".\../common\cmdlib.h"\ + ".\../common\mathlib.h"\ + ".\../common\scriplib.h"\ + + +"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/tools/quake2/extra/qdata/sprites.c b/tools/quake2/extra/qdata/sprites.c new file mode 100644 index 00000000..7bc308a8 --- /dev/null +++ b/tools/quake2/extra/qdata/sprites.c @@ -0,0 +1,228 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qdata.h" + +#define MAX_SPRFRAMES MAX_MD2SKINS + +dsprite_t sprite; +dsprframe_t frames[MAX_SPRFRAMES]; + +byte *byteimage, *lbmpalette; +int byteimagewidth, byteimageheight; + +char spritename[1024]; + + +void FinishSprite (void); +void Cmd_Spritename (void); + + + +/* +============== +FinishSprite +============== +*/ +void FinishSprite (void) +{ + FILE *spriteouthandle; + int i, curframe; + dsprite_t spritetemp; + char savename[1024]; + + if (sprite.numframes == 0) + return; + + if (!strlen(spritename)) + Error ("Didn't name sprite file"); + + sprintf (savename, "%s%s.sp2", gamedir, spritename); + + if (g_release) + { + char name[1024]; + + sprintf (name, "%s.sp2", spritename); + ReleaseFile (name); + spritename[0] = 0; // clear for a new sprite + sprite.numframes = 0; + return; + } + + + printf ("saving in %s\n", savename); + CreatePath (savename); + spriteouthandle = SafeOpenWrite (savename); + + +// +// write out the sprite header +// + spritetemp.ident = LittleLong (IDSPRITEHEADER); + spritetemp.version = LittleLong (SPRITE_VERSION); + spritetemp.numframes = LittleLong (sprite.numframes); + + SafeWrite (spriteouthandle, &spritetemp, 12); + +// +// write out the frames +// + curframe = 0; + + for (i=0 ; i 256) || (h > 256)) + Error ("Sprite has a dimension longer than 256"); + + xh = xl+w; + yh = yl+h; + + if (sprite.numframes >= MAX_SPRFRAMES) + Error ("Too many frames; increase MAX_SPRFRAMES\n"); + + pframe = &frames[sprite.numframes]; + pframe->width = w; + pframe->height = h; + pframe->origin_x = ox; + pframe->origin_y = oy; + sprintf (pframe->name, "%s_%i.pcx", spritename, sprite.numframes); + sprintf (savename, "%s%s_%i.pcx", gamedir, spritename, sprite.numframes); + sprite.numframes++; + + if (g_release) + { + ReleaseFile (pframe->name); + return; + } + + // crop it to the proper size + cropped = malloc (w*h); + for (y=0 ; y> 5 ) & 63 ) << 2; + b[0] = ( ( color >> 11 ) & 31 ) << 3; + + for ( i = 0; i < 256; i++ ) + { + r[1] = ( d_8to24table[i] >> 0 ) & 0xFF; + g[1] = ( d_8to24table[i] >> 8 ) & 0xFF; + b[1] = ( d_8to24table[i] >> 16 ) & 0xFF; + + d = ( r[1] - r[0] ) * ( r[1] - r[0] ) + + ( g[1] - g[0] ) * ( g[1] - g[0] ) + + ( b[1] - b[0] ) * ( b[1] - b[0] ); + + if ( d < closest_distance_so_far ) + { + closest_distance_so_far = d; + closest_so_far = i; + } + } + + return closest_so_far; +} +*/ + +extern byte BestColor( int, int, int, int, int ); + +void Inverse16_BuildTable( void ) +{ + int i; + + /* + ** create the 16-to-8 table + */ + for ( i = 0; i < 65536; i++ ) + { + int r = i & 31; + int g = ( i >> 5 ) & 63; + int b = ( i >> 11 ) & 31; + + r <<= 3; + g <<= 2; + b <<= 3; + + inverse16to8table[i] = BestColor( r, g, b, 0, 255 ); + } +} + +void Alphalight_Thread (int i) +{ + int j; + float r, g, b; + float mr, mg, mb, ma; + float distortion, bestdistortion; + float v; + + r = (i>>10) * (1.0/16); + g = ((i>>5)&31) * (1.0/16); + b = (i&31) * (1.0/16); + + bestdistortion = 999999; + for (j=0 ; j<16*16*16*16 ; j++) + { + mr = (j>>12) * (1.0/16); + mg = ((j>>8)&15) * (1.0/16); + mb = ((j>>4)&15) * (1.0/16); + ma = (j&15) * (1.0/16); + + v = r * 0.5 - (mr*ma + 0.5*(1.0-ma)); + distortion = v*v; + v = g * 0.5 - (mg*ma + 0.5*(1.0-ma)); + distortion += v*v; + v = b * 0.5 - (mb*ma + 0.5*(1.0-ma)); + distortion += v*v; + + distortion *= 1.0 + ma*4; + + if (distortion < bestdistortion) + { + bestdistortion = distortion; + alphamap[i] = j; + } + } +} + +void Cmd_Alphalight (void) +{ + char savename[1024]; + + GetToken (false); + + if (g_release) + { + ReleaseFile (token); + return; + } + + sprintf (savename, "%s%s", gamedir, token); + printf ("Building alphalight table...\n"); + + RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread); + + SaveFile (savename, (byte *)alphamap, sizeof(alphamap)); +} + + +void Cmd_Inverse16Table( void ) +{ + char savename[1024]; + + if ( g_release ) + { + sprintf (savename, "pics/16to8.dat"); + ReleaseFile( savename ); + return; + } + + sprintf (savename, "%spics/16to8.dat", gamedir); + printf ("Building inverse 16-to-8 table...\n"); + + Inverse16_BuildTable(); + + SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) ); +} diff --git a/tools/quake2/extra/qdata/video.c b/tools/quake2/extra/qdata/video.c new file mode 100644 index 00000000..b2df1493 --- /dev/null +++ b/tools/quake2/extra/qdata/video.c @@ -0,0 +1,1259 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qdata.h" + +byte *soundtrack; +char base[32]; + +/* +=============================================================================== + +WAV loading + +=============================================================================== +*/ + +typedef struct +{ + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start +} wavinfo_t; + + +byte *data_p; +byte *iff_end; +byte *last_chunk; +byte *iff_data; +int iff_chunk_len; + + +int samplecounts[0x10000]; + +wavinfo_t wavinfo; + +short GetLittleShort(void) +{ + short val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + data_p += 2; + return val; +} + +int GetLittleLong(void) +{ + int val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + val = val + (*(data_p+2)<<16); + val = val + (*(data_p+3)<<24); + data_p += 4; + return val; +} + +void FindNextChunk(char *name) +{ + while (1) + { + data_p=last_chunk; + + if (data_p >= iff_end) + { // didn't find the chunk + data_p = NULL; + return; + } + + data_p += 4; + iff_chunk_len = GetLittleLong(); + if (iff_chunk_len < 0) + { + data_p = NULL; + return; + } +// if (iff_chunk_len > 1024*1024) +// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); + data_p -= 8; + last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); + if (!strncmp(data_p, name, 4)) + return; + } +} + +void FindChunk(char *name) +{ + last_chunk = iff_data; + FindNextChunk (name); +} + + +void DumpChunks(void) +{ + char str[5]; + + str[4] = 0; + data_p=iff_data; + do + { + memcpy (str, data_p, 4); + data_p += 4; + iff_chunk_len = GetLittleLong(); + printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); + data_p += (iff_chunk_len + 1) & ~1; + } while (data_p < iff_end); +} + +/* +============ +GetWavinfo +============ +*/ +wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) +{ + wavinfo_t info; + int i; + int format; + int samples; + + memset (&info, 0, sizeof(info)); + + if (!wav) + return info; + + iff_data = wav; + iff_end = wav + wavlength; + +// find "RIFF" chunk + FindChunk("RIFF"); + if (!(data_p && !strncmp(data_p+8, "WAVE", 4))) + { + printf("Missing RIFF/WAVE chunks\n"); + return info; + } + +// get "fmt " chunk + iff_data = data_p + 12; +// DumpChunks (); + + FindChunk("fmt "); + if (!data_p) + { + printf("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) + { + printf("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4+2; + info.width = GetLittleShort() / 8; + +// get cue chunk + FindChunk("cue "); + if (data_p) + { + data_p += 32; + info.loopstart = GetLittleLong(); +// Com_Printf("loopstart=%d\n", sfx->loopstart); + + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk ("LIST"); + if (data_p) + { + if (!strncmp (data_p + 28, "mark", 4)) + { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong (); // samples in loop + info.samples = info.loopstart + i; + } + } + } + else + info.loopstart = -1; + +// find data chunk + FindChunk("data"); + if (!data_p) + { + printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong (); + + if (info.samples) + { + if (samples < info.samples) + Error ("Sound %s has a bad loop length", name); + } + else + info.samples = samples; + + info.dataofs = data_p - wav; + + return info; +} + +//===================================================================== + +/* +============== +LoadSoundtrack +============== +*/ +void LoadSoundtrack (void) +{ + char name[1024]; + FILE *f; + int len; + int i, val, j; + + soundtrack = NULL; + sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base); + printf ("%s\n", name); + f = fopen (name, "rb"); + if (!f) + { + printf ("no soundtrack for %s\n", base); + return; + } + len = Q_filelength(f); + soundtrack = malloc(len); + fread (soundtrack, 1, len, f); + fclose (f); + + wavinfo = GetWavinfo (name, soundtrack, len); + + // count samples for compression + memset (samplecounts, 0, sizeof(samplecounts)); + + j = wavinfo.samples/2; + for (i=0 ; i wavinfo.samples || !soundtrack) + fwrite (&empty, 1, width, output); + else + fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output); + } +} + +//========================================================================== + +/* +================== +MTF +================== +*/ +cblock_t MTF (cblock_t in) +{ + int i, j, b, code; + byte *out_p; + int index[256]; + cblock_t out; + + out_p = out.data = malloc(in.count + 4); + + // write count + *out_p++ = in.count&255; + *out_p++ = (in.count>>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + for (i=0 ; i<256 ; i++) + index[i] = i; + + for (i=0 ; i b2) + return 1; + if (++i1 == bwt_size) + i1 = 0; + if (++i2 == bwt_size) + i2 = 0; + } + + return 0; +} + +/* +================== +BWT +================== +*/ +cblock_t BWT (cblock_t in) +{ + int *sorted; + int i; + byte *out_p; + cblock_t out; + + bwt_size = in.count; + bwt_data = in.data; + + sorted = malloc(in.count*sizeof(*sorted)); + for (i=0 ; i>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + // write head index + for (i=0 ; i>8)&255; + *out_p++ = (i>>16)&255; + *out_p++ = (i>>24)&255; + + // write the L column + for (i=0 ; i 32) + Error ("bitcount > 32"); + charbits[nodenum] = bits; + charbitscount[nodenum] = bitcount; + return; + } + + node = &hnodes[nodenum]; + bits <<= 1; + BuildChars (node->children[0], bits, bitcount+1); + bits |= 1; + BuildChars (node->children[1], bits, bitcount+1); +} + + +/* +================== +Huffman +================== +*/ +cblock_t Huffman (cblock_t in) +{ + int i; + hnode_t *node; + int outbits, c; + unsigned bits; + byte *out_p; + cblock_t out; + int max, maxchar; + + // count + memset (hnodes, 0, sizeof(hnodes)); + for (i=0 ; i max) + { + max = hnodes[i].count; + maxchar = i; + } + } + if (max == 0) + Error ("Huffman: max == 0"); + + for (i=0 ; i<256 ; i++) + { + hnodes[i].count = (hnodes[i].count*255+max-1) / max; + } + + // build the nodes + numhnodes = 256; + while (numhnodes != 511) + { + node = &hnodes[numhnodes]; + + // pick two lowest counts + node->children[0] = SmallestNode (); + if (node->children[0] == -1) + break; // no more + + node->children[1] = SmallestNode (); + if (node->children[1] == -1) + { + if (node->children[0] != numhnodes-1) + Error ("Bad smallestnode"); + break; + } + node->count = hnodes[node->children[0]].count + + hnodes[node->children[1]].count; + numhnodes++; + } + + BuildChars (numhnodes-1, 0, 0); + + out_p = out.data = malloc(in.count*2 + 1024); + memset (out_p, 0, in.count*2+1024); + + // write count + *out_p++ = in.count&255; + *out_p++ = (in.count>>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + // save out the 256 normalized counts so the tree can be recreated + for (i=0 ; i<256 ; i++) + *out_p++ = hnodes[i].count; + + // write bits + outbits = 0; + for (i=0 ; i>3] |= 1<<(outbits&7); + outbits++; + } + } + + out_p += (outbits+7)>>3; + + out.count = out_p - out.data; + + return out; +} + +//========================================================================== + +/* +================== +RLE +================== +*/ +#define RLE_CODE 0xe8 +#define RLE_TRIPPLE 0xe9 + +int rle_counts[256]; +int rle_bytes[256]; + +cblock_t RLE (cblock_t in) +{ + int i; + byte *out_p; + int val; + int repeat; + cblock_t out; + + out_p = out.data = malloc (in.count*2); + + // write count + *out_p++ = in.count&255; + *out_p++ = (in.count>>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + for (i=0 ; i 3 || val == RLE_CODE) + { + *out_p++ = RLE_CODE; + *out_p++ = val; + *out_p++ = repeat; + } + else + { + while (repeat--) + *out_p++ = val; + } + } + + out.count = out_p - out.data; + return out; +} + +//========================================================================== + +unsigned lzss_head[256]; +unsigned lzss_next[0x20000]; + +/* +================== +LZSS +================== +*/ +#define BACK_WINDOW 0x10000 +#define BACK_BITS 16 +#define FRONT_WINDOW 16 +#define FRONT_BITS 4 +cblock_t LZSS (cblock_t in) +{ + int i; + byte *out_p; + cblock_t out; + int val; + int j, start, max; + int bestlength, beststart; + int outbits; + +if (in.count >= sizeof(lzss_next)/4) +Error ("LZSS: too big"); + + memset (lzss_head, -1, sizeof(lzss_head)); + + out_p = out.data = malloc (in.count*2); + memset (out.data, 0, in.count*2); + + // write count + *out_p++ = in.count&255; + *out_p++ = (in.count>>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + outbits = 0; + for (i=0 ; i in.count) + max = in.count - i; + + start = lzss_head[val]; + while (start != -1 && start >= i-BACK_WINDOW) + { + // count match length + for (j=0 ; j bestlength) + { + bestlength = j; + beststart = start; + } + start = lzss_next[start]; + } + +#else +// slow simple search + // search for a match + max = FRONT_WINDOW; + if (i + max > in.count) + max = in.count - i; + + start = i - BACK_WINDOW; + if (start < 0) + start = 0; + bestlength = 0; + beststart = 0; + for ( ; start < i ; start++) + { + if (in.data[start] != val) + continue; + // count match length + for (j=0 ; j bestlength) + { + bestlength = j; + beststart = start; + } + } +#endif + beststart = BACK_WINDOW - (i-beststart); + + if (bestlength < 3) + { // output a single char + bestlength = 1; + + out_p[outbits>>3] |= 1<<(outbits&7); // set bit to mark char + outbits++; + for (j=0 ; j<8 ; j++, outbits++) + if (val & (1<>3] |= 1<<(outbits&7); + } + else + { // output a phrase + outbits++; // leave a 0 bit to mark phrase + for (j=0 ; j>3] |= 1<<(outbits&7); + for (j=0 ; j>3] |= 1<<(outbits&7); + } + + while (bestlength--) + { + val = in.data[i]; + lzss_next[i] = lzss_head[val]; + lzss_head[val] = i; + i++; + } + } + + out_p += (outbits+7)>>3; + out.count = out_p - out.data; + return out; +} + +//========================================================================== + +#define MIN_REPT 15 +#define MAX_REPT 0 +#define HUF_TOKENS (256+MAX_REPT) + +unsigned charbits1[256][HUF_TOKENS]; +int charbitscount1[256][HUF_TOKENS]; + +hnode_t hnodes1[256][HUF_TOKENS*2]; +int numhnodes1[256]; + +int order0counts[256]; + +/* +================== +SmallestNode1 +================== +*/ +int SmallestNode1 (hnode_t *hnodes, int numhnodes) +{ + int i; + int best, bestnode; + + best = 99999999; + bestnode = -1; + for (i=0 ; i 32) + Error ("bitcount > 32"); + charbits1[prev][nodenum] = bits; + charbitscount1[prev][nodenum] = bitcount; + return; + } + + node = &hnodes1[prev][nodenum]; + bits <<= 1; + BuildChars1 (prev, node->children[0], bits, bitcount+1); + bits |= 1; + BuildChars1 (prev, node->children[1], bits, bitcount+1); +} + + +/* +================== +BuildTree1 +================== +*/ +void BuildTree1 (int prev) +{ + hnode_t *node, *nodebase; + int numhnodes; + + // build the nodes + numhnodes = HUF_TOKENS; + nodebase = hnodes1[prev]; + while (1) + { + node = &nodebase[numhnodes]; + + // pick two lowest counts + node->children[0] = SmallestNode1 (nodebase, numhnodes); + if (node->children[0] == -1) + break; // no more + + node->children[1] = SmallestNode1 (nodebase, numhnodes); + if (node->children[1] == -1) + break; + + node->count = nodebase[node->children[0]].count + + nodebase[node->children[1]].count; + numhnodes++; + } + numhnodes1[prev] = numhnodes-1; + BuildChars1 (prev, numhnodes-1, 0, 0); +} + + +/* +================== +Huffman1_Count +================== +*/ +void Huffman1_Count (cblock_t in) +{ + int i; + int prev; + int v; + int rept; + + prev = 0; + for (i=0 ; i MIN_REPT) + { + hnodes1[prev][255+rept].count++; + i += rept-1; + } +#endif + } +} + + +/* +================== +Huffman1_Build +================== +*/ +byte scaled[256][HUF_TOKENS]; +void Huffman1_Build (FILE *f) +{ + int i, j, v; + int max; + int total; + + for (i=0 ; i<256 ; i++) + { + // normalize and save the counts + max = 0; + for (j=0 ; j max) + max = hnodes1[i][j].count; + } + if (max == 0) + max = 1; + total = 0; + for (j=0 ; j 255) + Error ("v > 255"); + scaled[i][j] = hnodes1[i][j].count = v; + if (v) + total++; + } + if (total == 1) + { // must have two tokens + if (!scaled[i][0]) + scaled[i][0] = hnodes1[i][0].count = 1; + else + scaled[i][1] = hnodes1[i][1].count = 1; + } + + BuildTree1 (i); + } + +#if 0 + // count up the total bits + total = 0; + for (i=0 ; i<256 ; i++) + for (j=0 ; j<256 ; j++) + total += charbitscount1[i][j] * hnodes1[i][j].count; + + total = (total+7)/8; + printf ("%i bytes huffman1 compressed\n", total); +#endif + + fwrite (scaled, 1, sizeof(scaled), f); +} + +/* +================== +Huffman1 + +Order 1 compression with pre-built table +================== +*/ +cblock_t Huffman1 (cblock_t in) +{ + int i; + int outbits, c; + unsigned bits; + byte *out_p; + cblock_t out; + int prev; + int v; + int rept; + + out_p = out.data = malloc(in.count*2 + 1024); + memset (out_p, 0, in.count*2+1024); + + // write count + *out_p++ = in.count&255; + *out_p++ = (in.count>>8)&255; + *out_p++ = (in.count>>16)&255; + *out_p++ = (in.count>>24)&255; + + // write bits + outbits = 0; + prev = 0; + for (i=0 ; i>3] |= 1<<(outbits&7); + outbits++; + } + + prev = v; +#if 1 + // check for repeat encodes + for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++) + if (in.data[i+rept] != v) + break; + if (rept > MIN_REPT) + { + c = charbitscount1[prev][255+rept]; + bits = charbits1[prev][255+rept]; + if (!c) + Error ("!bits"); + while (c) + { + c--; + if (bits & (1<>3] |= 1<<(outbits&7); + outbits++; + } + i += rept-1; + } +#endif + } + + out_p += (outbits+7)>>3; + + out.count = out_p - out.data; + + return out; +} + +//========================================================================== + + +/* +=================== +LoadFrame +=================== +*/ +cblock_t LoadFrame (char *base, int frame, int digits, byte **palette) +{ + int ten3, ten2, ten1, ten0; + cblock_t in; + int width, height; + char name[1024]; + FILE *f; + + in.data = NULL; + in.count = -1; + + ten3 = frame/1000; + ten2 = (frame-ten3*1000)/100; + ten1 = (frame-ten3*1000-ten2*100)/10; + ten0 = frame%10; + + if (digits == 4) + sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0); + else + sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0); + + f = fopen(name, "rb"); + if (!f) + { + in.data = NULL; + return in; + } + fclose (f); + + printf ("%s\n", name); + Load256Image (name, &in.data, palette, &width, &height); + in.count = width*height; +// FIXME: map 0 and 255! + +#if 0 + // rle compress + rle = RLE(in); + free (in.data); + + return rle; +#endif + + return in; +} + +/* +=============== +Cmd_Video + +video +=============== +*/ +void Cmd_Video (void) +{ + char savename[1024]; + char name[1024]; + FILE *output; + int startframe, frame; + byte *palette; + int width, height; + byte current_palette[768]; + int command; + int i; + int digits; + cblock_t in, huffman; + int swap; + + + GetToken (false); + strcpy (base, token); + if (g_release) + { +// sprintf (savename, "video/%s.cin", token); +// ReleaseFile (savename); + return; + } + + GetToken (false); + digits = atoi(token); + + // optionally skip frames + if (TokenAvailable ()) + { + GetToken (false); + startframe = atoi(token); + } + else + startframe=0; + + sprintf (savename, "%svideo/%s.cin", gamedir, base); + + + // clear stuff + memset (charbits1, 0, sizeof(charbits1)); + memset (charbitscount1, 0, sizeof(charbitscount1)); + memset (hnodes1, 0, sizeof(hnodes1)); + memset (numhnodes1, 0, sizeof(numhnodes1)); + memset (order0counts, 0, sizeof(order0counts)); + + + // load the entire sound wav file if present + LoadSoundtrack (); + + if (digits == 4) + sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base); + else + sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base); + + printf ("%s\n", name); + Load256Image (name, NULL, &palette, &width, &height); + + output = fopen (savename, "wb"); + if (!output) + Error ("Can't open %s", savename); + + // write header info + i = LittleLong (width); + fwrite (&i, 4, 1, output); + i = LittleLong (height); + fwrite (&i, 4, 1, output); + i = LittleLong (wavinfo.rate); + fwrite (&i, 4, 1, output); + i = LittleLong (wavinfo.width); + fwrite (&i, 4, 1, output); + i = LittleLong (wavinfo.channels); + fwrite (&i, 4, 1, output); + + // build the dictionary + for ( frame=startframe ; ; frame++) + { + printf ("counting ", frame); + in = LoadFrame (base, frame, digits, &palette); + if (!in.data) + break; + Huffman1_Count (in); + free (in.data); + } + printf ("\n"); + + // build nodes and write counts + Huffman1_Build (output); + + + memset (current_palette, 0, sizeof(current_palette)); + + // compress it with the dictionary + for (frame=startframe ; ; frame++) + { + printf ("packing ", frame); + in = LoadFrame (base, frame, digits, &palette); + if (!in.data) + break; + + // see if the palette has changed + for (i=0 ; i<768 ; i++) + if (palette[i] != current_palette[i]) + { + // write a palette change + memcpy (current_palette, palette, sizeof(current_palette)); + command = LittleLong(1); + fwrite (&command, 1, 4, output); + fwrite (current_palette, 1, sizeof(current_palette), output); + break; + } + if (i == 768) + { + command = 0; // no palette change + fwrite (&command, 1, 4, output); + } + + // save the image + huffman = Huffman1 (in); + printf ("%5i bytes after huffman1\n", huffman.count); + + swap = LittleLong (huffman.count); + fwrite (&swap, 1, sizeof(swap), output); + + fwrite (huffman.data, 1, huffman.count, output); + + // save some sound samples + WriteSound (output, frame); + + free (palette); + free (in.data); + free (huffman.data); + } + printf ("\n"); + + // write end-of-file command + command = 2; + fwrite (&command, 1, 4, output); + + printf ("Total size: %i\n", ftell (output)); + + fclose (output); + + if (soundtrack) + free (soundtrack); +} diff --git a/tools/quake2/extra/qe4/brush.c b/tools/quake2/extra/qe4/brush.c new file mode 100644 index 00000000..e8a2b53a --- /dev/null +++ b/tools/quake2/extra/qe4/brush.c @@ -0,0 +1,1568 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include +#include "qe3.h" + +#define MAX_POINTS_ON_WINDING 64 + +face_t *Face_Alloc( void ); +void Face_Free( face_t *f ); + +winding_t *NewWinding (int points); +void FreeWinding (winding_t *w); +winding_t *Winding_Clone( winding_t *w ); +winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon); + +void PrintWinding (winding_t *w) +{ + int i; + + printf ("-------------\n"); + for (i=0 ; inumpoints ; i++) + printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0] + , w->points[i][1], w->points[i][2]); +} + +void PrintPlane (plane_t *p) +{ + printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n", p->normal[0], p->normal[1], + p->normal[2], p->dist); +} + +void PrintVector (vec3_t v) +{ + printf ("(%5.2f, %5.2f, %5.2f)\n", v[0], v[1], v[2]); +} + + +face_t *Face_Clone (face_t *f) +{ + face_t *n; + + n = Face_Alloc(); + n->texdef = f->texdef; + memcpy (n->planepts, f->planepts, sizeof(n->planepts)); + + // all other fields are derived, and will be set by Brush_Build + return n; +} + +//============================================================================ + +#define BOGUS_RANGE 18000 + + +/* +================== +NewWinding +================== +*/ +winding_t *NewWinding (int points) +{ + winding_t *w; + int size; + + if (points > MAX_POINTS_ON_WINDING) + Error ("NewWinding: %i points", points); + + size = (int)((winding_t *)0)->points[points]; + w = malloc (size); + memset (w, 0, size); + w->maxpoints = points; + + return w; +} + + +void FreeWinding (winding_t *w) +{ + free (w); +} + + +/* +================== +Winding_Clone +================== +*/ +winding_t *Winding_Clone(winding_t *w) +{ + int size; + winding_t *c; + + size = (int)((winding_t *)0)->points[w->numpoints]; + c = qmalloc (size); + memcpy (c, w, size); + return c; +} + + +/* +================== +ClipWinding + +Clips the winding to the plane, returning the new winding on the positive side +Frees the input winding. +If keepon is true, an exactly on-plane winding will be saved, otherwise +it will be clipped away. +================== +*/ +winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon) +{ + vec_t dists[MAX_POINTS_ON_WINDING]; + int sides[MAX_POINTS_ON_WINDING]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *neww; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->points[i], split->normal); + dot -= split->dist; + dists[i] = dot; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (keepon && !counts[0] && !counts[1]) + return in; + + if (!counts[0]) + { + FreeWinding (in); + return NULL; + } + if (!counts[1]) + return in; + + maxpts = in->numpoints+4; // can't use counts[0]+2 because + // of fp grouping errors + neww = NewWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->points[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->points[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (split->normal[j] == 1) + mid[j] = split->dist; + else if (split->normal[j] == -1) + mid[j] = -split->dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, neww->points[neww->numpoints]); + neww->numpoints++; + } + + if (neww->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + +// free the original winding + FreeWinding (in); + + return neww; +} + + + +/* +============================================================================= + + TEXTURE COORDINATES + +============================================================================= +*/ + + +/* +================== +textureAxisFromPlane +================== +*/ +vec3_t baseaxis[18] = +{ +{0,0,1}, {1,0,0}, {0,-1,0}, // floor +{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling +{1,0,0}, {0,1,0}, {0,0,-1}, // west wall +{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall +{0,1,0}, {1,0,0}, {0,0,-1}, // south wall +{0,-1,0}, {1,0,0}, {0,0,-1} // north wall +}; + +void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv) +{ + int bestaxis; + float dot,best; + int i; + + best = 0; + bestaxis = 0; + + for (i=0 ; i<6 ; i++) + { + dot = DotProduct (pln->normal, baseaxis[i*3]); + if (dot > best) + { + best = dot; + bestaxis = i; + } + } + + VectorCopy (baseaxis[bestaxis*3+1], xv); + VectorCopy (baseaxis[bestaxis*3+2], yv); +} + + +float lightaxis[3] = {0.6, 0.8, 1.0}; +/* +================ +SetShadeForPlane + +Light different planes differently to +improve recognition +================ +*/ +float SetShadeForPlane (plane_t *p) +{ + int i; + float f; + + // axial plane + for (i=0 ; i<3 ; i++) + if (fabs(p->normal[i]) > 0.9) + { + f = lightaxis[i]; + return f; + } + + // between two axial planes + for (i=0 ; i<3 ; i++) + if (fabs(p->normal[i]) < 0.1) + { + f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2; + return f; + } + + // other + f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3; + return f; +} + +vec3_t vecs[2]; +float shift[2]; + +/* +================ +BeginTexturingFace +================ +*/ +void BeginTexturingFace (brush_t *b, face_t *f, qtexture_t *q) +{ + vec3_t pvecs[2]; + int sv, tv; + float ang, sinv, cosv; + float ns, nt; + int i,j; + float shade; + + // get natural texture axis + TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]); + + // set shading for face + shade = SetShadeForPlane (&f->plane); + if (camera.draw_mode == cd_texture && !b->owner->eclass->fixedsize) + { + f->d_color[0] = + f->d_color[1] = + f->d_color[2] = shade; + } + else + { + f->d_color[0] = shade*q->color[0]; + f->d_color[1] = shade*q->color[1]; + f->d_color[2] = shade*q->color[2]; + } + + if (camera.draw_mode != cd_texture) + return; + + if (!f->texdef.scale[0]) + f->texdef.scale[0] = 1; + if (!f->texdef.scale[1]) + f->texdef.scale[1] = 1; + + +// rotate axis + if (f->texdef.rotate == 0) + { sinv = 0 ; cosv = 1; } + else if (f->texdef.rotate == 90) + { sinv = 1 ; cosv = 0; } + else if (f->texdef.rotate == 180) + { sinv = 0 ; cosv = -1; } + else if (f->texdef.rotate == 270) + { sinv = -1 ; cosv = 0; } + else + { + ang = f->texdef.rotate / 180 * Q_PI; + sinv = sin(ang); + cosv = cos(ang); + } + + if (pvecs[0][0]) + sv = 0; + else if (pvecs[0][1]) + sv = 1; + else + sv = 2; + + if (pvecs[1][0]) + tv = 0; + else if (pvecs[1][1]) + tv = 1; + else + tv = 2; + + for (i=0 ; i<2 ; i++) + { + ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv]; + nt = sinv * pvecs[i][sv] + cosv * pvecs[i][tv]; + vecs[i][sv] = ns; + vecs[i][tv] = nt; + } + + for (i=0 ; i<2 ; i++) + for (j=0 ; j<3 ; j++) + vecs[i][j] = vecs[i][j] / f->texdef.scale[i]; +} + + +void _EmitTextureCoordinates (vec3_t v, qtexture_t *q) +{ + float s, t; + + s = DotProduct (v, vecs[0]); + t = DotProduct (v, vecs[1]); + + s += shift[0]; + t += shift[1]; + + s /= q->width; + t /= q->height; + + glTexCoord2f (s, t); +} + +void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f) +{ + float s, t, ns, nt; + float ang, sinv, cosv; + vec3_t vecs[2]; + texdef_t *td; + + // get natural texture axis + TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]); + + td = &f->texdef; + + ang = td->rotate / 180 * Q_PI; + sinv = sin(ang); + cosv = cos(ang); + + if (!td->scale[0]) + td->scale[0] = 1; + if (!td->scale[1]) + td->scale[1] = 1; + + s = DotProduct(xyzst, vecs[0]); + t = DotProduct(xyzst, vecs[1]); + + ns = cosv * s - sinv * t; + nt = sinv * s + cosv * t; + + s = ns/td->scale[0] + td->shift[0]; + t = nt/td->scale[1] + td->shift[1]; + + // gl scales everything from 0 to 1 + s /= q->width; + t /= q->height; + + xyzst[3] = s; + xyzst[4] = t; +} + +//========================================================================== + + +/* +================= +BasePolyForPlane +================= +*/ +winding_t *BasePolyForPlane (plane_t *p) +{ + int i, x; + vec_t max, v; + vec3_t org, vright, vup; + winding_t *w; + +// find the major axis + + max = -BOGUS_RANGE; + x = -1; + for (i=0 ; i<3; i++) + { + v = fabs(p->normal[i]); + if (v > max) + { + x = i; + max = v; + } + } + if (x==-1) + Error ("BasePolyForPlane: no axis found"); + + VectorCopy (vec3_origin, vup); + switch (x) + { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + + v = DotProduct (vup, p->normal); + VectorMA (vup, -v, p->normal, vup); + VectorNormalize (vup); + + VectorScale (p->normal, p->dist, org); + + CrossProduct (vup, p->normal, vright); + + VectorScale (vup, 8192, vup); + VectorScale (vright, 8192, vright); + +// project a really big axis aligned box onto the plane + w = NewWinding (4); + + VectorSubtract (org, vright, w->points[0]); + VectorAdd (w->points[0], vup, w->points[0]); + + VectorAdd (org, vright, w->points[1]); + VectorAdd (w->points[1], vup, w->points[1]); + + VectorAdd (org, vright, w->points[2]); + VectorSubtract (w->points[2], vup, w->points[2]); + + VectorSubtract (org, vright, w->points[3]); + VectorSubtract (w->points[3], vup, w->points[3]); + + w->numpoints = 4; + + return w; +} + +void Brush_MakeFacePlanes (brush_t *b) +{ + face_t *f; + int j; + vec3_t t1, t2, t3; + + for (f=b->brush_faces ; f ; f=f->next) + { + // convert to a vector / dist plane + for (j=0 ; j<3 ; j++) + { + t1[j] = f->planepts[0][j] - f->planepts[1][j]; + t2[j] = f->planepts[2][j] - f->planepts[1][j]; + t3[j] = f->planepts[1][j]; + } + + CrossProduct(t1,t2, f->plane.normal); + if (VectorCompare (f->plane.normal, vec3_origin)) + printf ("WARNING: brush plane with no normal\n"); + VectorNormalize (f->plane.normal); + f->plane.dist = DotProduct (t3, f->plane.normal); + } +} + +void DrawBrushEntityName (brush_t *b) +{ + char *name; + float a, s, c; + vec3_t mid; + int i; + + if (!b->owner) + return; // during contruction + + if (b->owner == world_entity) + return; + + if (b != b->owner->brushes.onext) + return; // not key brush + + // draw the angle pointer + a = FloatForKey (b->owner, "angle"); + if (a) + { + s = sin (a/180*Q_PI); + c = cos (a/180*Q_PI); + for (i=0 ; i<3 ; i++) + mid[i] = (b->mins[i] + b->maxs[i])*0.5; + + glBegin (GL_LINE_STRIP); + glVertex3fv (mid); + mid[0] += c*8; + mid[1] += s*8; + glVertex3fv (mid); + mid[0] -= c*4; + mid[1] -= s*4; + mid[0] -= s*4; + mid[1] += c*4; + glVertex3fv (mid); + mid[0] += c*4; + mid[1] += s*4; + mid[0] += s*4; + mid[1] -= c*4; + glVertex3fv (mid); + mid[0] -= c*4; + mid[1] -= s*4; + mid[0] += s*4; + mid[1] -= c*4; + glVertex3fv (mid); + glEnd (); + } + + if (!g_qeglobals.d_savedinfo.show_names) + return; + + name = ValueForKey (b->owner, "classname"); + glRasterPos2f (b->mins[0]+4, b->mins[1]+4); + glCallLists (strlen(name), GL_UNSIGNED_BYTE, name); +} + +/* +================= +MakeFaceWinding + +returns the visible polygon on a face +================= +*/ +winding_t *MakeFaceWinding (brush_t *b, face_t *face) +{ + winding_t *w; + face_t *clip; + plane_t plane; + qboolean past; + + // get a poly that covers an effectively infinite area + w = BasePolyForPlane (&face->plane); + + // chop the poly by all of the other faces + past = false; + for (clip = b->brush_faces ; clip && w ; clip=clip->next) + { + if (clip == face) + { + past = true; + continue; + } + if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999 + && fabs(face->plane.dist - clip->plane.dist) < 0.01 ) + { // identical plane, use the later one + if (past) + { + free (w); + return NULL; + } + continue; + } + + // flip the plane, because we want to keep the back side + VectorSubtract (vec3_origin,clip->plane.normal, plane.normal); + plane.dist = -clip->plane.dist; + + w = ClipWinding (w, &plane, false); + if (!w) + return w; + } + + if (w->numpoints < 3) + { + free(w); + w = NULL; + } + + if (!w) + printf ("unused plane\n"); + + return w; +} + + +void Brush_SnapPlanepts (brush_t *b) +{ + int i, j; + face_t *f; + + for (f=b->brush_faces ; f; f=f->next) + for (i=0 ; i<3 ; i++) + for (j=0 ; j<3 ; j++) + f->planepts[i][j] = floor (f->planepts[i][j] + 0.5); +} + +/* +** Brush_Build +** +** Builds a brush rendering data and also sets the min/max bounds +*/ +#define ZERO_EPSILON 0.001 +void Brush_Build( brush_t *b ) +{ +// int order; +// face_t *face; +// winding_t *w; + char title[1024]; + + if (modified != 1) + { + modified = true; // mark the map as changed + sprintf (title, "%s *", currentmap); + + QE_ConvertDOSToUnixName( title, title ); + Sys_SetTitle (title); + } + + /* + ** build the windings and generate the bounding box + */ + Brush_BuildWindings( b ); + + /* + ** move the points and edges if in select mode + */ + if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge) + SetupVertexSelection (); +} + +/* +================= +Brush_Parse + +The brush is NOT linked to any list +================= +*/ +brush_t *Brush_Parse (void) +{ + brush_t *b; + face_t *f; + int i,j; + + g_qeglobals.d_parsed_brushes++; + b = qmalloc(sizeof(brush_t)); + + do + { + if (!GetToken (true)) + break; + if (!strcmp (token, "}") ) + break; + + f = Face_Alloc(); + + // add the brush to the end of the chain, so + // loading and saving a map doesn't reverse the order + + f->next = NULL; + if (!b->brush_faces) + { + b->brush_faces = f; + } + else + { + face_t *scan; + + for (scan=b->brush_faces ; scan->next ; scan=scan->next) + ; + scan->next = f; + } + + // read the three point plane definition + for (i=0 ; i<3 ; i++) + { + if (i != 0) + GetToken (true); + if (strcmp (token, "(") ) + Error ("parsing brush"); + + for (j=0 ; j<3 ; j++) + { + GetToken (false); + f->planepts[i][j] = atoi(token); + } + + GetToken (false); + if (strcmp (token, ")") ) + Error ("parsing brush"); + + } + + // read the texturedef + GetToken (false); + strcpy(f->texdef.name, token); + GetToken (false); + f->texdef.shift[0] = atoi(token); + GetToken (false); + f->texdef.shift[1] = atoi(token); + GetToken (false); + f->texdef.rotate = atoi(token); + GetToken (false); + f->texdef.scale[0] = atof(token); + GetToken (false); + f->texdef.scale[1] = atof(token); + + // the flags and value field aren't necessarily present + f->d_texture = Texture_ForName( f->texdef.name ); + f->texdef.flags = f->d_texture->flags; + f->texdef.value = f->d_texture->value; + f->texdef.contents = f->d_texture->contents; + + if (TokenAvailable ()) + { + GetToken (false); + f->texdef.contents = atoi(token); + GetToken (false); + f->texdef.flags = atoi(token); + GetToken (false); + f->texdef.value = atoi(token); + } + } while (1); + + return b; +} + +/* +================= +Brush_Write +================= +*/ +void Brush_Write (brush_t *b, FILE *f) +{ + face_t *fa; + char *pname; + int i; + + fprintf (f, "{\n"); + for (fa=b->brush_faces ; fa ; fa=fa->next) + { + for (i=0 ; i<3 ; i++) + fprintf (f, "( %i %i %i ) ", (int)fa->planepts[i][0] + , (int)fa->planepts[i][1], (int)fa->planepts[i][2]); + + pname = fa->texdef.name; + if (pname[0] == 0) + pname = "unnamed"; + + fprintf (f, "%s %i %i %i ", pname, + (int)fa->texdef.shift[0], (int)fa->texdef.shift[1], + (int)fa->texdef.rotate); + + if (fa->texdef.scale[0] == (int)fa->texdef.scale[0]) + fprintf (f, "%i ", (int)fa->texdef.scale[0]); + else + fprintf (f, "%f ", (float)fa->texdef.scale[0]); + if (fa->texdef.scale[1] == (int)fa->texdef.scale[1]) + fprintf (f, "%i", (int)fa->texdef.scale[1]); + else + fprintf (f, "%f", (float)fa->texdef.scale[1]); + + // only output flags and value if not default + if (fa->texdef.value != fa->d_texture->value + || fa->texdef.flags != fa->d_texture->flags + || fa->texdef.contents != fa->d_texture->contents) + { + fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value); + } + + fprintf (f, "\n"); + } + fprintf (f, "}\n"); +} + + +/* +============= +Brush_Create + +Create non-textured blocks for entities +The brush is NOT linked to any list +============= +*/ +brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef) +{ + int i, j; + vec3_t pts[4][2]; + face_t *f; + brush_t *b; + + for (i=0 ; i<3 ; i++) + if (maxs[i] < mins[i]) + Error ("Brush_InitSolid: backwards"); + + b = qmalloc (sizeof(brush_t)); + + pts[0][0][0] = mins[0]; + pts[0][0][1] = mins[1]; + + pts[1][0][0] = mins[0]; + pts[1][0][1] = maxs[1]; + + pts[2][0][0] = maxs[0]; + pts[2][0][1] = maxs[1]; + + pts[3][0][0] = maxs[0]; + pts[3][0][1] = mins[1]; + + for (i=0 ; i<4 ; i++) + { + pts[i][0][2] = mins[2]; + pts[i][1][0] = pts[i][0][0]; + pts[i][1][1] = pts[i][0][1]; + pts[i][1][2] = maxs[2]; + } + + for (i=0 ; i<4 ; i++) + { + f = Face_Alloc(); + f->texdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + j = (i+1)%4; + + VectorCopy (pts[j][1], f->planepts[0]); + VectorCopy (pts[i][1], f->planepts[1]); + VectorCopy (pts[i][0], f->planepts[2]); + } + + f = Face_Alloc(); + f->texdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + + VectorCopy (pts[0][1], f->planepts[0]); + VectorCopy (pts[1][1], f->planepts[1]); + VectorCopy (pts[2][1], f->planepts[2]); + + f = Face_Alloc(); + f->texdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + + VectorCopy (pts[2][0], f->planepts[0]); + VectorCopy (pts[1][0], f->planepts[1]); + VectorCopy (pts[0][0], f->planepts[2]); + + return b; +} + + +/* +============= +Brush_MakeSided + +Makes the current brushhave the given number of 2d sides +============= +*/ +void Brush_MakeSided (int sides) +{ + int i; + vec3_t mins, maxs; + brush_t *b; + texdef_t *texdef; + face_t *f; + vec3_t mid; + float width; + float sv, cv; + + if (sides < 3) + { + Sys_Status ("Bad sides number", 0); + return; + } + + if (!QE_SingleBrush ()) + { + Sys_Status ("Must have a single brush selected", 0 ); + return; + } + + b = selected_brushes.next; + VectorCopy (b->mins, mins); + VectorCopy (b->maxs, maxs); + texdef = &g_qeglobals.d_texturewin.texdef; + + Brush_Free (b); + + // find center of brush + width = 8; + for (i=0 ; i<2 ; i++) + { + mid[i] = (maxs[i] + mins[i])*0.5; + if (maxs[i] - mins[i] > width) + width = maxs[i] - mins[i]; + } + width /= 2; + + b = qmalloc (sizeof(brush_t)); + + // create top face + f = Face_Alloc(); + f->texdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + +f->planepts[2][0] = mins[0];f->planepts[2][1] = mins[1];f->planepts[2][2] = maxs[2]; +f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = maxs[2]; +f->planepts[0][0] = maxs[0];f->planepts[0][1] = maxs[1];f->planepts[0][2] = maxs[2]; + + // create bottom face + f = Face_Alloc(); + f->texdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + +f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2]; +f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2]; +f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2]; + + for (i=0 ; itexdef = *texdef; + f->next = b->brush_faces; + b->brush_faces = f; + + sv = sin (i*3.14159265*2/sides); + cv = cos (i*3.14159265*2/sides); + + f->planepts[0][0] = floor(mid[0]+width*cv+0.5); + f->planepts[0][1] = floor(mid[1]+width*sv+0.5); + f->planepts[0][2] = mins[2]; + + f->planepts[1][0] = f->planepts[0][0]; + f->planepts[1][1] = f->planepts[0][1]; + f->planepts[1][2] = maxs[2]; + + f->planepts[2][0] = floor(f->planepts[0][0] - width*sv + 0.5); + f->planepts[2][1] = floor(f->planepts[0][1] + width*cv + 0.5); + f->planepts[2][2] = maxs[2]; + + } + + Brush_AddToList (b, &selected_brushes); + + Entity_LinkBrush (world_entity, b); + + Brush_Build( b ); + + Sys_UpdateWindows (W_ALL); +} + + +/* +============= +Brush_Free + +Frees the brush with all of its faces and display list. +Unlinks the brush from whichever chain it is in. +Decrements the owner entity's brushcount. +Removes owner entity if this was the last brush +unless owner is the world. +============= +*/ +void Brush_Free (brush_t *b) +{ + face_t *f, *next; + + // free faces + for (f=b->brush_faces ; f ; f=next) + { + next = f->next; + Face_Free( f ); + } + + /* + for ( i = 0; i < b->d_numwindings; i++ ) + { + if ( b->d_windings[i] ) + { + FreeWinding( b->d_windings[i] ); + b->d_windings[i] = 0; + } + } + */ + + // unlink from active/selected list + if (b->next) + Brush_RemoveFromList (b); + + // unlink from entity list + if (b->onext) + Entity_UnlinkBrush (b); + + free (b); +} + +/* +============ +Brush_Move +============ +*/ +void Brush_Move (brush_t *b, vec3_t move) +{ + int i; + face_t *f; + + for (f=b->brush_faces ; f ; f=f->next) + for (i=0 ; i<3 ; i++) + VectorAdd (f->planepts[i], move, f->planepts[i]); + Brush_Build( b ); +} + +/* +============ +Brush_Clone + +Does NOT add the new brush to any lists +============ +*/ +brush_t *Brush_Clone (brush_t *b) +{ + brush_t *n; + face_t *f, *nf; + + n = qmalloc(sizeof(brush_t)); + n->owner = b->owner; + for (f=b->brush_faces ; f ; f=f->next) + { + nf = Face_Clone( f ); + nf->next = n->brush_faces; + n->brush_faces = nf; + } + return n; +} + +/* +============== +Brush_Ray + +Itersects a ray with a brush +Returns the face hit and the distance along the ray the intersection occured at +Returns NULL and 0 if not hit at all +============== +*/ +face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist) +{ + face_t *f, *firstface; + vec3_t p1, p2; + float frac, d1, d2; + int i; + + VectorCopy (origin, p1); + for (i=0 ; i<3 ; i++) + p2[i] = p1[i] + dir[i]*16384; + + for (f=b->brush_faces ; f ; f=f->next) + { + d1 = DotProduct (p1, f->plane.normal) - f->plane.dist; + d2 = DotProduct (p2, f->plane.normal) - f->plane.dist; + if (d1 >= 0 && d2 >= 0) + { + *dist = 0; + return NULL; // ray is on front side of face + } + if (d1 <=0 && d2 <= 0) + continue; + // clip the ray to the plane + frac = d1 / (d1 - d2); + if (d1 > 0) + { + firstface = f; + for (i=0 ; i<3 ; i++) + p1[i] = p1[i] + frac *(p2[i] - p1[i]); + } + else + { + for (i=0 ; i<3 ; i++) + p2[i] = p1[i] + frac *(p2[i] - p1[i]); + } + } + + // find distance p1 is along dir + VectorSubtract (p1, origin, p1); + d1 = DotProduct (p1, dir); + + *dist = d1; + + return firstface; +} + +void Brush_AddToList (brush_t *b, brush_t *list) +{ + if (b->next || b->prev) + Error ("Brush_RemoveFromList: allready linked"); + b->next = list->next; + list->next->prev = b; + list->next = b; + b->prev = list; +} + +void Brush_RemoveFromList (brush_t *b) +{ + if (!b->next || !b->prev) + Error ("Brush_RemoveFromList: not linked"); + b->next->prev = b->prev; + b->prev->next = b->next; + b->next = b->prev = NULL; +} + +void Brush_SetTexture (brush_t *b, texdef_t *texdef) +{ + face_t *f; + + for (f=b->brush_faces ; f ; f=f->next) + f->texdef = *texdef; + Brush_Build( b ); +} + + +qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f) +{ + float d1, d2, fr; + int i; + float *v; + + d1 = DotProduct (p1, f->plane.normal) - f->plane.dist; + d2 = DotProduct (p2, f->plane.normal) - f->plane.dist; + + if (d1 >= 0 && d2 >= 0) + return false; // totally outside + if (d1 <= 0 && d2 <= 0) + return true; // totally inside + + fr = d1 / (d1 - d2); + + if (d1 > 0) + v = p1; + else + v = p2; + + for (i=0 ; i<3 ; i++) + v[i] = p1[i] + fr*(p2[i] - p1[i]); + + return true; +} + + +int AddPlanept (float *f) +{ + int i; + + for (i=0 ; iowner->eclass->fixedsize) + return; + + c = 0; + for (i=0 ; i<3 ; i++) + c += AddPlanept (f->planepts[i]); + if (c == 0) + return; // allready completely added + + // select all points on this plane in all brushes the selection + for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next) + { + if (b2 == b) + continue; + for (f2=b2->brush_faces ; f2 ; f2=f2->next) + { + for (i=0 ; i<3 ; i++) + if (fabs(DotProduct(f2->planepts[i], f->plane.normal) + -f->plane.dist) > ON_EPSILON) + break; + if (i==3) + { // move this face as well + Brush_SelectFaceForDragging (b2, f2, shear); + break; + } + } + } + + + // if shearing, take all the planes adjacent to + // selected faces and rotate their points so the + // edge clipped by a selcted face has two of the points + if (!shear) + return; + + for (f2=b->brush_faces ; f2 ; f2=f2->next) + { + if (f2 == f) + continue; + w = MakeFaceWinding (b, f2); + if (!w) + continue; + + // any points on f will become new control points + for (i=0 ; inumpoints ; i++) + { + d = DotProduct (w->points[i], f->plane.normal) + - f->plane.dist; + if (d > -ON_EPSILON && d < ON_EPSILON) + break; + } + + // + // if none of the points were on the plane, + // leave it alone + // + if (i != w->numpoints) + { + if (i == 0) + { // see if the first clockwise point was the + // last point on the winding + d = DotProduct (w->points[w->numpoints-1] + , f->plane.normal) - f->plane.dist; + if (d > -ON_EPSILON && d < ON_EPSILON) + i = w->numpoints - 1; + } + + AddPlanept (f2->planepts[0]); + + VectorCopy (w->points[i], f2->planepts[0]); + if (++i == w->numpoints) + i = 0; + + // see if the next point is also on the plane + d = DotProduct (w->points[i] + , f->plane.normal) - f->plane.dist; + if (d > -ON_EPSILON && d < ON_EPSILON) + AddPlanept (f2->planepts[1]); + + VectorCopy (w->points[i], f2->planepts[1]); + if (++i == w->numpoints) + i = 0; + + // the third point is never on the plane + + VectorCopy (w->points[i], f2->planepts[2]); + } + + free(w); + } +} + +/* +============== +Brush_SideSelect + +The mouse click did not hit the brush, so grab one or more side +planes for dragging +============== +*/ +void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir + , qboolean shear) +{ + face_t *f, *f2; + vec3_t p1, p2; + + for (f=b->brush_faces ; f ; f=f->next) + { + VectorCopy (origin, p1); + VectorMA (origin, 16384, dir, p2); + + for (f2=b->brush_faces ; f2 ; f2=f2->next) + { + if (f2 == f) + continue; + ClipLineToFace (p1, p2, f2); + } + + if (f2) + continue; + + if (VectorCompare (p1, origin)) + continue; + if (ClipLineToFace (p1, p2, f)) + continue; + + Brush_SelectFaceForDragging (b, f, shear); + } + + +} + +void Brush_BuildWindings( brush_t *b ) +{ + winding_t *w; + face_t *face; + vec_t v; + + Brush_SnapPlanepts( b ); + + // clear the mins/maxs bounds + b->mins[0] = b->mins[1] = b->mins[2] = 99999; + b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999; + + Brush_MakeFacePlanes (b); + + face = b->brush_faces; + + for ( ; face ; face=face->next) + { + int i, j; + + w = face->face_winding = MakeFaceWinding (b, face); + face->d_texture = Texture_ForName( face->texdef.name ); + + if (!w) + { + continue; + } + + for (i=0 ; inumpoints ; i++) + { + // add to bounding box + for (j=0 ; j<3 ; j++) + { + v = w->points[i][j]; + if (v > b->maxs[j]) + b->maxs[j] = v; + if (v < b->mins[j]) + b->mins[j] = v; + } + } + // setup s and t vectors, and set color + BeginTexturingFace( b, face, face->d_texture); + + + for (i=0 ; inumpoints ; i++) + { + EmitTextureCoordinates( w->points[i], face->d_texture, face); + } + } +} + +/* +================== +Brush_RemoveEmptyFaces + +Frees any overconstraining faces +================== +*/ +void Brush_RemoveEmptyFaces ( brush_t *b ) +{ + face_t *f, *next; + + f = b->brush_faces; + b->brush_faces = NULL; + + for ( ; f ; f=next) + { + next = f->next; + if (!f->face_winding) + Face_Free (f); + else + { + f->next = b->brush_faces; + b->brush_faces = f; + } + + } +} + +void Brush_Draw( brush_t *b ) +{ + face_t *face; + int i, order; + qtexture_t *prev = 0; + winding_t *w; + + if (b->owner->eclass->fixedsize && camera.draw_mode == cd_texture) + glDisable (GL_TEXTURE_2D); + + // guarantee the texture will be set first + prev = NULL; + for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++) + { + w = face->face_winding; + if (!w) + continue; // freed face + + if ( face->d_texture != prev && camera.draw_mode == cd_texture) + { + // set the texture for this face + prev = face->d_texture; + glBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number ); + } + + glColor3fv( face->d_color ); + + // draw the polygon + glBegin(GL_POLYGON); + for (i=0 ; inumpoints ; i++) + { + if (camera.draw_mode == cd_texture) + glTexCoord2fv( &w->points[i][3] ); + glVertex3fv(w->points[i]); + } + glEnd(); + } + + if (b->owner->eclass->fixedsize && camera.draw_mode == cd_texture) + glEnable (GL_TEXTURE_2D); + + glBindTexture( GL_TEXTURE_2D, 0 ); +} + +void Face_Draw( face_t *f ) +{ + int i; + + if ( f->face_winding == 0 ) + return; + glBegin( GL_POLYGON ); + for ( i = 0 ; i < f->face_winding->numpoints; i++) + glVertex3fv( f->face_winding->points[i] ); + glEnd(); +} + +void Brush_DrawXY( brush_t *b ) +{ + face_t *face; + int order; + winding_t *w; + int i; + + for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++) + { + // only draw up facing polygons + if (face->plane.normal[2] <= 0) + continue; + + w = face->face_winding; + if (!w) + continue; + + // draw the polygon + glBegin(GL_LINE_LOOP); + for (i=0 ; inumpoints ; i++) + glVertex3fv(w->points[i]); + glEnd(); + } + + // optionally add a text label + if ( g_qeglobals.d_savedinfo.show_names ) + DrawBrushEntityName (b); +} + +face_t *Face_Alloc( void ) +{ + face_t *f = qmalloc( sizeof( *f ) ); + + return f; +} + +void Face_Free( face_t *f ) +{ + assert( f != 0 ); + + if ( f->face_winding ) + free( f->face_winding ), f->face_winding = 0; + free( f ); +} diff --git a/tools/quake2/extra/qe4/brush.h b/tools/quake2/extra/qe4/brush.h new file mode 100644 index 00000000..7a948e03 --- /dev/null +++ b/tools/quake2/extra/qe4/brush.h @@ -0,0 +1,87 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// brush.h + + +typedef struct +{ + int numpoints; + int maxpoints; + float points[8][5]; // variable sized +} winding_t; + + +// the normals on planes point OUT of the brush +#define MAXPOINTS 16 +typedef struct face_s +{ + struct face_s *next; + vec3_t planepts[3]; + texdef_t texdef; + + plane_t plane; + + winding_t *face_winding; + + vec3_t d_color; + qtexture_t *d_texture; + +// int d_numpoints; +// vec3_t *d_points; +} face_t; + +#define MAX_FACES 16 +typedef struct brush_s +{ + struct brush_s *prev, *next; // links in active/selected + struct brush_s *oprev, *onext; // links in entity + struct entity_s *owner; + vec3_t mins, maxs; + + face_t *brush_faces; +} brush_t; + + +void Brush_AddToList (brush_t *b, brush_t *list); +void Brush_Build(brush_t *b); +void Brush_BuildWindings( brush_t *b ); +brush_t *Brush_Clone (brush_t *b); +brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef); +void Brush_Draw( brush_t *b ); +void Brush_DrawXY( brush_t *b ); +void Brush_Free (brush_t *b); +void Brush_MakeSided (int sides); +void Brush_Move (brush_t *b, vec3_t move); +brush_t *Brush_Parse (void); +face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist); +void Brush_RemoveFromList (brush_t *b); +void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear); +void Brush_SetTexture (brush_t *b, texdef_t *texdef); +void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir, qboolean shear); +void Brush_Write (brush_t *b, FILE *f); +void Brush_RemoveEmptyFaces ( brush_t *b ); + +int AddPlanept (float *f); +face_t *Face_Clone (face_t *f); +void Face_Draw( face_t *face ); +winding_t *MakeFaceWinding (brush_t *b, face_t *face); diff --git a/tools/quake2/extra/qe4/bspfile.h b/tools/quake2/extra/qe4/bspfile.h new file mode 100644 index 00000000..89c56a34 --- /dev/null +++ b/tools/quake2/extra/qe4/bspfile.h @@ -0,0 +1,378 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// upper design bounds +// leaffaces, leafbrushes, planes, and verts are still bounded by +// 16 bit short limits +#define MAX_MAP_MODELS 1024 +#define MAX_MAP_BRUSHES 8192 +#define MAX_MAP_ENTITIES 2048 +#define MAX_MAP_PATHS 2048 +#define MAX_MAP_ENTSTRING 0x20000 +#define MAX_MAP_TEXTURES 1024 +#define MAX_MAP_TEXINFO 8192 + +#define MAX_MAP_PLANES 65536 +#define MAX_MAP_NODES 65536 +#define MAX_MAP_BRUSHSIDES 65536 +#define MAX_MAP_LEAFS 65536 +#define MAX_MAP_VERTS 65536 +#define MAX_MAP_FACES 65536 +#define MAX_MAP_LEAFFACES 65536 +#define MAX_MAP_LEAFBRUSHES 65536 +#define MAX_MAP_PORTALS 65536 +#define MAX_MAP_EDGES 128000 +#define MAX_MAP_SURFEDGES 256000 +#define MAX_MAP_MIPTEX 0x200000 +#define MAX_MAP_LIGHTING 0x200000 +#define MAX_MAP_VISIBILITY 0x100000 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 1024 + +//============================================================================= + +#define BSPVERSION 34 + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_TEXTURES 2 +#define LUMP_VERTEXES 3 +#define LUMP_VISIBILITY 4 +#define LUMP_NODES 5 +#define LUMP_TEXINFO 6 +#define LUMP_FACES 7 +#define LUMP_LIGHTING 8 +#define LUMP_LEAFS 9 +#define LUMP_LEAFFACES 10 +#define LUMP_LEAFBRUSHES 11 +#define LUMP_EDGES 12 +#define LUMP_SURFEDGES 13 +#define LUMP_MODELS 14 +#define LUMP_PATHS 15 +#define LUMP_BRUSHES 16 +#define LUMP_BRUSHSIDES 17 +#define LUMP_POP 18 + +#define HEADER_LUMPS 18 + +typedef struct +{ + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; // for sounds or lights + int headnode; + int visleafs; // not including the solid leaf 0 + int firstface, numfaces; +} dmodel_t; + +typedef struct +{ + int nummiptex; + int dataofs[4]; // [nummiptex] +} dmiptexlump_t; + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[16]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored + int flags; + int value; +} miptex_t; + + +typedef struct +{ + float point[3]; +} dvertex_t; + + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +// planes (x&~1) and (x&~1)+1 are allways opposites + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + + +// contents flags are seperate bits +// a given brush can contribute multiple content bits +// multiple brushes can be in a single leaf + +// lower bits are stronger, and will eat weaker brushes completely +#define CONTENTS_SOLID 1 // an eye is never valid in a solid +#define CONTENTS_WINDOW 2 // translucent, but not watery +#define CONTENTS_LAVA 8 +#define CONTENTS_SLIME 16 +#define CONTENTS_WATER 32 +#define CONTENTS_THINWATER 64 // translucent faces + +#define LAST_VISIBLE_CONTENTS 64 + +// remaining contents are non-visible, and don't eat brushes +#define CONTENTS_MONSTER 128 +#define CONTENTS_PLAYERCLIP 256 +#define CONTENTS_MONSTERCLIP 512 + + +// currents can be added to any other contents, and may be mixed +#define CONTENTS_CURRENT_0 1024 +#define CONTENTS_CURRENT_90 2048 +#define CONTENTS_CURRENT_180 4096 +#define CONTENTS_CURRENT_270 8192 +#define CONTENTS_CURRENT_UP 16384 +#define CONTENTS_CURRENT_DOWN 32768 + +#define CONTENTS_ORIGIN 65536 // removed before processing + + + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for frustom culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int miptex; + int flags; // miptex flags + overrides + int value; // light emition, etc +} texinfo_t; + +#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision +#define SURF_LIGHT 2 + +#define SURF_WATER 4 +#define SURF_SLIME 8 +#define SURF_LAVA 16 +#define SURF_WINDOW 32 + +#define SURF_SKY 64 +#define SURF_MIRROR 128 + +#define SURF_SLIPPERY 256 + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 +typedef struct +{ + unsigned short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + +typedef struct +{ + int contents; // OR of all brushes + int visofs; // -1 = no visibility info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstleafface; + unsigned short numleaffaces; + + unsigned short firstleafbrush; + unsigned short numleafbrushes; +} dleaf_t; + + +typedef struct +{ + unsigned short planenum; // facing out of the leaf + short texinfo; +} dbrushside_t; + +typedef struct +{ + int firstside; + int numsides; + int contents; +} dbrush_t; + +typedef struct +{ + float origin[3]; + float angles[3]; + int next, prev; + int flags; + float speed; +} dpath_t; + +//============================================================================ + +#ifndef QUAKE_GAME + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + + +// the utilities get to be lazy and just use large static arrays + +extern int nummodels; +extern dmodel_t dmodels[MAX_MAP_MODELS]; + +extern int visdatasize; +extern byte dvisdata[MAX_MAP_VISIBILITY]; + +extern int lightdatasize; +extern byte dlightdata[MAX_MAP_LIGHTING]; + +extern int texdatasize; +extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) + +extern int entdatasize; +extern char dentdata[MAX_MAP_ENTSTRING]; + +extern int numleafs; +extern dleaf_t dleafs[MAX_MAP_LEAFS]; + +extern int numplanes; +extern dplane_t dplanes[MAX_MAP_PLANES]; + +extern int numvertexes; +extern dvertex_t dvertexes[MAX_MAP_VERTS]; + +extern int numnodes; +extern dnode_t dnodes[MAX_MAP_NODES]; + +extern int numtexinfo; +extern texinfo_t texinfo[MAX_MAP_TEXINFO]; + +extern int numfaces; +extern dface_t dfaces[MAX_MAP_FACES]; + +extern int numedges; +extern dedge_t dedges[MAX_MAP_EDGES]; + +extern int numleaffaces; +extern unsigned short dleaffaces[MAX_MAP_LEAFFACES]; + +extern int numleafbrushes; +extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES]; + +extern int numsurfedges; +extern int dsurfedges[MAX_MAP_SURFEDGES]; + +extern int numpaths; +extern dpath_t dpaths[MAX_MAP_PATHS]; + +extern int numbrushes; +extern dbrush_t dbrushes[MAX_MAP_BRUSHES]; + +extern int numbrushsides; +extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES]; + + +void DecompressVis (byte *in, byte *decompressed); +int CompressVis (byte *vis, byte *dest); + +void LoadBSPFile (char *filename); +void WriteBSPFile (char *filename); +void PrintBSPFileSizes (void); + +//=============== + + +typedef struct epair_s +{ + struct epair_s *next; + char *key; + char *value; +} epair_t; + +typedef struct +{ + vec3_t origin; + int firstbrush; + int numbrushes; + epair_t *epairs; +} entity_t; + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities (void); +void UnparseEntities (void); + +void SetKeyValue (entity_t *ent, char *key, char *value); +char *ValueForKey (entity_t *ent, char *key); +// will return "" if not present + +vec_t FloatForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); + +epair_t *ParseEpair (void); + +void PrintEntity (entity_t *ent); + +extern int r_leaftovis[MAX_MAP_LEAFS]; +extern int r_vistoleaf[MAX_MAP_LEAFS]; +extern int r_numvisleafs; + +#endif diff --git a/tools/quake2/extra/qe4/camera.c b/tools/quake2/extra/qe4/camera.c new file mode 100644 index 00000000..8dd7d5f5 --- /dev/null +++ b/tools/quake2/extra/qe4/camera.c @@ -0,0 +1,594 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +#define PAGEFLIPS 2 + +void DrawPathLines (void); + +camera_t camera; + +/* +============ +Cam_Init +============ +*/ +void Cam_Init (void) +{ +// camera.draw_mode = cd_texture; +// camera.draw_mode = cd_solid; +// camera.draw_mode = cd_wire; + + camera.timing = false; + + camera.origin[0] = 0; + camera.origin[1] = 20; + camera.origin[2] = 46; + + camera.color[0] = 0.3; + camera.color[1] = 0.3; + camera.color[2] = 0.3; +} + + +//============================================================================ + +void Cam_BuildMatrix (void) +{ + float xa, ya; + float matrix[4][4]; + int i; + + xa = camera.angles[0]/180*Q_PI; + ya = camera.angles[1]/180*Q_PI; + + // the movement matrix is kept 2d + + camera.forward[0] = cos(ya); + camera.forward[1] = sin(ya); + camera.right[0] = camera.forward[1]; + camera.right[1] = -camera.forward[0]; + + glGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]); + + for (i=0 ; i<3 ; i++) + { + camera.vright[i] = matrix[i][0]; + camera.vup[i] = matrix[i][1]; + camera.vpn[i] = matrix[i][2]; + } + + VectorNormalize (camera.vright); + VectorNormalize (camera.vup); + VectorNormalize (camera.vpn); +} + +//=============================================== + +/* +=============== +Cam_ChangeFloor +=============== +*/ +void Cam_ChangeFloor (qboolean up) +{ + brush_t *b; + float d, bestd, current; + vec3_t start, dir; + + start[0] = camera.origin[0]; + start[1] = camera.origin[1]; + start[2] = 8192; + dir[0] = dir[1] = 0; + dir[2] = -1; + + current = 8192 - (camera.origin[2] - 48); + if (up) + bestd = 0; + else + bestd = 16384; + + for (b=active_brushes.next ; b != &active_brushes ; b=b->next) + { + if (!Brush_Ray (start, dir, b, &d)) + continue; + if (up && d < current && d > bestd) + bestd = d; + if (!up && d > current && d < bestd) + bestd = d; + } + + if (bestd == 0 || bestd == 16384) + return; + + camera.origin[2] += current - bestd; + Sys_UpdateWindows (W_CAMERA|W_Z_OVERLAY); +} + + +//=============================================== + +int cambuttonstate; +static int buttonx, buttony; +static int cursorx, cursory; + +face_t *side_select; + +#define ANGLE_SPEED 300 +#define MOVE_SPEED 400 + +/* +================ +Cam_PositionDrag +================ +*/ +void Cam_PositionDrag (void) +{ + int x, y; + + Sys_GetCursorPos (&x, &y); + if (x != cursorx || y != cursory) + { + x -= cursorx; + VectorMA (camera.origin, x, camera.vright, camera.origin); + y -= cursory; + camera.origin[2] -= y; + + Sys_SetCursorPos (cursorx, cursory); + Sys_UpdateWindows (W_CAMERA | W_XY_OVERLAY); + } +} + +/* +=============== +Cam_MouseControl +=============== +*/ +void Cam_MouseControl (float dtime) +{ + int xl, xh; + int yl, yh; + float xf, yf; + + if (cambuttonstate != MK_RBUTTON) + return; + + xf = (float)(buttonx - camera.width/2) / (camera.width/2); + yf = (float)(buttony - camera.height/2) / (camera.height/2); + + xl = camera.width/3; + xh = xl*2; + yl = camera.height/3; + yh = yl*2; + +#if 0 + // strafe + if (buttony < yl && (buttonx < xl || buttonx > xh)) + VectorMA (camera.origin, xf*dtime*MOVE_SPEED, camera.right, camera.origin); + else +#endif + { + xf *= 1.0 - fabs(yf); + if (xf < 0) + { + xf += 0.1; + if (xf > 0) + xf = 0; + } + else + { + xf -= 0.1; + if (xf < 0) + xf = 0; + } + + VectorMA (camera.origin, yf*dtime*MOVE_SPEED, camera.forward, camera.origin); + camera.angles[YAW] += xf*-dtime*ANGLE_SPEED; + } + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); +} + + + + +/* +============== +Cam_MouseDown +============== +*/ +void Cam_MouseDown (int x, int y, int buttons) +{ + vec3_t dir; + float f, r, u; + int i; + + // + // calc ray direction + // + u = (float)(y - camera.height/2) / (camera.width/2); + r = (float)(x - camera.width/2) / (camera.width/2); + f = 1; + + for (i=0 ; i<3 ; i++) + dir[i] = camera.vpn[i] * f + camera.vright[i] * r + camera.vup[i] * u; + VectorNormalize (dir); + + Sys_GetCursorPos (&cursorx, &cursory); + + cambuttonstate = buttons; + buttonx = x; + buttony = y; + + // LBUTTON = manipulate selection + // shift-LBUTTON = select + // middle button = grab texture + // ctrl-middle button = set entire brush to texture + // ctrl-shift-middle button = set single face to texture + if ( (buttons == MK_LBUTTON) + || (buttons == (MK_LBUTTON | MK_SHIFT)) + || (buttons == (MK_LBUTTON | MK_CONTROL)) + || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) + || (buttons == MK_MBUTTON) + || (buttons == (MK_MBUTTON|MK_CONTROL)) + || (buttons == (MK_MBUTTON|MK_SHIFT|MK_CONTROL)) ) + { + Drag_Begin (x, y, buttons, + camera.vright, camera.vup, + camera.origin, dir); + return; + } + + if (buttons == MK_RBUTTON) + { + Cam_MouseControl (0.1); + return; + } +} + +/* +============== +Cam_MouseUp +============== +*/ +void Cam_MouseUp (int x, int y, int buttons) +{ + cambuttonstate = 0; + Drag_MouseUp (); +} + + +/* +============== +Cam_MouseMoved +============== +*/ +void Cam_MouseMoved (int x, int y, int buttons) +{ + cambuttonstate = buttons; + if (!buttons) + return; + buttonx = x; + buttony = y; + + if (buttons == (MK_RBUTTON|MK_CONTROL) ) + { + Cam_PositionDrag (); + Sys_UpdateWindows (W_XY|W_CAMERA|W_Z); + return; + } + + Sys_GetCursorPos (&cursorx, &cursory); + + if (buttons & (MK_LBUTTON | MK_MBUTTON) ) + { + Drag_MouseMoved (x, y, buttons); + Sys_UpdateWindows (W_XY|W_CAMERA|W_Z); + } +} + + +vec3_t cull1, cull2; +int cullv1[3], cullv2[3]; + +void InitCull (void) +{ + int i; + + VectorSubtract (camera.vpn, camera.vright, cull1); + VectorAdd (camera.vpn, camera.vright, cull2); + + for (i=0 ; i<3 ; i++) + { + if (cull1[i] > 0) + cullv1[i] = 3+i; + else + cullv1[i] = i; + if (cull2[i] > 0) + cullv2[i] = 3+i; + else + cullv2[i] = i; + } +} + +qboolean CullBrush (brush_t *b) +{ + int i; + vec3_t point; + float d; + + for (i=0 ; i<3 ; i++) + point[i] = b->mins[cullv1[i]] - camera.origin[i]; + + d = DotProduct (point, cull1); + if (d < -1) + return true; + + for (i=0 ; i<3 ; i++) + point[i] = b->mins[cullv2[i]] - camera.origin[i]; + + d = DotProduct (point, cull2); + if (d < -1) + return true; + + return false; +} + + +/* +============== +Cam_Draw +============== +*/ +void Cam_Draw (void) +{ + brush_t *brush; + face_t *face; + float screenaspect; + float yfov; + double start, end; + int i; + + if (!active_brushes.next) + return; // not valid yet + + if (camera.timing) + start = Sys_DoubleTime (); + + // + // clear + // + QE_CheckOpenGLForErrors(); + + glViewport(0, 0, camera.width, camera.height); + glScissor(0, 0, camera.width, camera.height); + glClearColor ( + g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0], + g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1], + g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], + 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // + // set up viewpoint + // + glMatrixMode(GL_PROJECTION); + glLoadIdentity (); + + screenaspect = (float)camera.width/camera.height; + yfov = 2*atan((float)camera.height/camera.width)*180/Q_PI; + gluPerspective (yfov, screenaspect, 2, 8192); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + glRotatef (camera.angles[0], 0, 1, 0); + glRotatef (-camera.angles[1], 0, 0, 1); + glTranslatef (-camera.origin[0], -camera.origin[1], -camera.origin[2]); + + Cam_BuildMatrix (); + + InitCull (); + + // + // draw stuff + // + + switch (camera.draw_mode) + { + case cd_wire: + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glColor3f(1.0, 1.0, 1.0); +// glEnable (GL_LINE_SMOOTH); + break; + + case cd_solid: + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + glShadeModel (GL_FLAT); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glDisable(GL_TEXTURE_2D); + + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); + break; + + case cd_texture: + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + + glShadeModel (GL_FLAT); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_TEXTURE_2D); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); + +#if 0 + + { + GLfloat fogColor[4] = {0.0, 1.0, 0.0, 0.25}; + + glFogi (GL_FOG_MODE, GL_LINEAR); + glHint (GL_FOG_HINT, GL_NICEST); /* per pixel */ + glFogf (GL_FOG_START, -8192); + glFogf (GL_FOG_END, 65536); + glFogfv (GL_FOG_COLOR, fogColor); + + } + +#endif + break; + + case cd_blend: + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + + glShadeModel (GL_FLAT); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_TEXTURE_2D); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glDisable(GL_DEPTH_TEST); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + } + + glMatrixMode(GL_TEXTURE); + for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) + { + if (CullBrush (brush)) + continue; + if (FilterBrush (brush)) + continue; + + Brush_Draw( brush ); + } + glMatrixMode(GL_PROJECTION); + + // + // now draw selected brushes + // + + glTranslatef (g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]); + glMatrixMode(GL_TEXTURE); + + // draw normally + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + { + Brush_Draw( brush ); + } + + // blend on top + glMatrixMode(GL_PROJECTION); + + glColor4f(1.0, 0.0, 0.0, 0.3); + glEnable (GL_BLEND); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable (GL_TEXTURE_2D); + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + for (face=brush->brush_faces ; face ; face=face->next) + Face_Draw( face ); + if (selected_face) + Face_Draw(selected_face); + + // non-zbuffered outline + + glDisable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glColor3f (1, 1, 1); + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + for (face=brush->brush_faces ; face ; face=face->next) + Face_Draw( face ); + + // edge / vertex flags + + if (g_qeglobals.d_select_mode == sel_vertex) + { + glPointSize (4); + glColor3f (0,1,0); + glBegin (GL_POINTS); + for (i=0 ; i32); + + com_token[len] = 0; + return data; +} + + +int Q_strncasecmp (char *s1, char *s2, int n) +{ + int c1, c2; + + while (1) + { + c1 = *s1++; + c2 = *s2++; + + if (!n--) + return 0; // strings are equal until end point + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + if (!c1) + return 0; // strings are equal + } + + return -1; +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return Q_strncasecmp (s1, s2, 99999); +} + + + +/* +============================================================================= + + MISC FUNCTIONS + +============================================================================= +*/ + + +int argc; +char *argv[MAX_NUM_ARGVS]; + +/* +============ +ParseCommandLine +============ +*/ +void ParseCommandLine (char *lpCmdLine) +{ + argc = 1; + argv[0] = "programname"; + + while (*lpCmdLine && (argc < MAX_NUM_ARGVS)) + { + while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + argv[argc] = lpCmdLine; + argc++; + + while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + *lpCmdLine = 0; + lpCmdLine++; + } + + } + } +} + + + +/* +================= +CheckParm + +Checks for the given parameter in the program's command line arguments +Returns the argument number (1 to argc-1) or 0 if not present +================= +*/ +int CheckParm (char *check) +{ + int i; + + for (i = 1;i 0 && path[length] != PATHSEPERATOR) + length--; + path[length] = 0; +} + +void StripExtension (char *path) +{ + int length; + + length = strlen(path)-1; + while (length > 0 && path[length] != '.') + { + length--; + if (path[length] == '/') + return; // no extension + } + if (length) + path[length] = 0; +} + + +/* +==================== +Extract file parts +==================== +*/ +void ExtractFilePath (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != PATHSEPERATOR) + src--; + + memcpy (dest, path, src-path); + dest[src-path] = 0; +} + +void ExtractFileName (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != '/' + && *(src-1) != '\\' ) + src--; + + while (*src) + { + *dest++ = *src++; + } + *dest = 0; +} + +void ExtractFileBase (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != '/' + && *(src-1) != '\\' ) + src--; + + while (*src && *src != '.') + { + *dest++ = *src++; + } + *dest = 0; +} + +void ExtractFileExtension (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a . or the start +// + while (src != path && *(src-1) != '.') + src--; + if (src == path) + { + *dest = 0; // no extension + return; + } + + strcpy (dest,src); +} + + +/* +============== +ParseNum / ParseHex +============== +*/ +int ParseHex (char *hex) +{ + char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + Error ("Bad hex number: %s",hex); + str++; + } + + return num; +} + + +int ParseNum (char *str) +{ + if (str[0] == '$') + return ParseHex (str+1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex (str+2); + return atol (str); +} + + + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +#ifdef _SGI_SOURCE +#define __BIG_ENDIAN__ +#endif + +#ifdef __BIG_ENDIAN__ + +short LittleShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short BigShort (short l) +{ + return l; +} + + +int LittleLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int BigLong (int l) +{ + return l; +} + + +float LittleFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float BigFloat (float l) +{ + return l; +} + + +#else + + +short BigShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short LittleShort (short l) +{ + return l; +} + + +int BigLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LittleLong (int l) +{ + return l; +} + +float BigFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float LittleFloat (float l) +{ + return l; +} + + + +#endif + diff --git a/tools/quake2/extra/qe4/cmdlib.h b/tools/quake2/extra/qe4/cmdlib.h new file mode 100644 index 00000000..b748950c --- /dev/null +++ b/tools/quake2/extra/qe4/cmdlib.h @@ -0,0 +1,99 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// cmdlib.h + +#ifndef __CMDLIB__ +#define __CMDLIB__ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __BYTEBOOL__ +#define __BYTEBOOL__ +typedef enum {false, true} qboolean; +typedef unsigned char byte; +#endif + +// the dec offsetof macro doesn't work very well... +#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) + + +// set these before calling CheckParm +extern int myargc; +extern char **myargv; + +int Q_strncasecmp (char *s1, char *s2, int n); +int Q_strcasecmp (char *s1, char *s2); + +int Q_filelength (FILE *f); + +double I_FloatTime (void); + +void Error (char *error, ...); +int CheckParm (char *check); +void ParseCommandLine (char *lpCmdLine); + +FILE *SafeOpenWrite (char *filename); +FILE *SafeOpenRead (char *filename); +void SafeRead (FILE *f, void *buffer, int count); +void SafeWrite (FILE *f, void *buffer, int count); + +int LoadFile (char *filename, void **bufferptr); +int LoadFileNoCrash (char *filename, void **bufferptr); +void SaveFile (char *filename, void *buffer, int count); + +void DefaultExtension (char *path, char *extension); +void DefaultPath (char *path, char *basepath); +void StripFilename (char *path); +void StripExtension (char *path); + +void ExtractFilePath (char *path, char *dest); +void ExtractFileName (char *path, char *dest); +void ExtractFileBase (char *path, char *dest); +void ExtractFileExtension (char *path, char *dest); + +int ParseNum (char *str); + +short BigShort (short l); +short LittleShort (short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + + +char *COM_Parse (char *data); + +extern char com_token[1024]; +extern qboolean com_eof; + +#define MAX_NUM_ARGVS 32 +extern int argc; +extern char *argv[MAX_NUM_ARGVS]; + +#endif diff --git a/tools/quake2/extra/qe4/csg.c b/tools/quake2/extra/qe4/csg.c new file mode 100644 index 00000000..e36a2ade --- /dev/null +++ b/tools/quake2/extra/qe4/csg.c @@ -0,0 +1,168 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +/* +============== +CSG_SplitBrushByFace + +The incoming brush is NOT freed. +The incoming face is NOT left referenced. +============== +*/ +void CSG_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back) +{ + brush_t *b; + face_t *nf; + vec3_t temp; + + b = Brush_Clone (in); + nf = Face_Clone (f); + + nf->texdef = b->brush_faces->texdef; + nf->next = b->brush_faces; + b->brush_faces = nf; + + Brush_Build( b ); + Brush_RemoveEmptyFaces ( b ); + if ( !b->brush_faces ) + { // completely clipped away + Brush_Free (b); + *back = NULL; + } + else + { + Entity_LinkBrush (in->owner, b); + *back = b; + } + + b = Brush_Clone (in); + nf = Face_Clone (f); + // swap the plane winding + VectorCopy (nf->planepts[0], temp); + VectorCopy (nf->planepts[1], nf->planepts[0]); + VectorCopy (temp, nf->planepts[1]); + + nf->texdef = b->brush_faces->texdef; + nf->next = b->brush_faces; + b->brush_faces = nf; + + Brush_Build( b ); + Brush_RemoveEmptyFaces ( b ); + if ( !b->brush_faces ) + { // completely clipped away + Brush_Free (b); + *front = NULL; + } + else + { + Entity_LinkBrush (in->owner, b); + *front = b; + } +} + +/* +============= +CSG_MakeHollow +============= +*/ +void CSG_MakeHollow (void) +{ + brush_t *b, *front, *back, *next; + face_t *f; + face_t split; + vec3_t move; + int i; + + for (b = selected_brushes.next ; b != &selected_brushes ; b=next) + { + next = b->next; + for (f = b->brush_faces ; f ; f=f->next) + { + split = *f; + VectorScale (f->plane.normal, g_qeglobals.d_gridsize, move); + for (i=0 ; i<3 ; i++) + VectorSubtract (split.planepts[i], move, split.planepts[i]); + + CSG_SplitBrushByFace (b, &split, &front, &back); + if (back) + Brush_Free (back); + if (front) + Brush_AddToList (front, &selected_brushes); + } + Brush_Free (b); + } + Sys_UpdateWindows (W_ALL); +} + + +/* +============= +CSG_Subtract +============= +*/ +void CSG_Subtract (void) +{ + brush_t *b, *s, *frag, *front, *back, *next, *snext; + face_t *f; + int i; + + Sys_Printf ("Subtracting...\n"); + + for (b = selected_brushes.next ; b != &selected_brushes ; b=next) + { + next = b->next; + + if (b->owner->eclass->fixedsize) + continue; // can't use texture from a fixed entity, so don't subtract + + for (s=active_brushes.next ; s != &active_brushes ; s=snext) + { + snext = s->next; + if (s->owner->eclass->fixedsize) + continue; + + for (i=0 ; i<3 ; i++) + if (b->mins[i] >= s->maxs[i] - ON_EPSILON + || b->maxs[i] <= s->mins[i] + ON_EPSILON) + break; + if (i != 3) + continue; // definately don't touch + + frag = s; + for (f = b->brush_faces ; f && frag ; f=f->next) + { + CSG_SplitBrushByFace (frag, f, &front, &back); + Brush_Free (frag); + frag = back; + if (front) + Brush_AddToList (front, &active_brushes); + } + if (frag) + Brush_Free (frag); + } + } + + Sys_Printf ("done.\n"); + Sys_UpdateWindows (W_ALL); +} diff --git a/tools/quake2/extra/qe4/drag.c b/tools/quake2/extra/qe4/drag.c new file mode 100644 index 00000000..2418325e --- /dev/null +++ b/tools/quake2/extra/qe4/drag.c @@ -0,0 +1,457 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +/* + + drag either multiple brushes, or select plane points from + a single brush. + +*/ + +qboolean drag_ok; +vec3_t drag_xvec; +vec3_t drag_yvec; + +static int buttonstate; +static int pressx, pressy; +static vec3_t pressdelta; +static int buttonx, buttony; + + +//int num_move_points; +//float *move_points[1024]; + +int lastx, lasty; + +qboolean drag_first; + + +void AxializeVector (vec3_t v) +{ + vec3_t a; + float o; + int i; + + if (!v[0] && !v[1]) + return; + if (!v[1] && !v[2]) + return; + if (!v[0] && !v[2]) + return; + + for (i=0 ; i<3 ; i++) + a[i] = fabs(v[i]); + if (a[0] > a[1] && a[0] > a[2]) + i = 0; + else if (a[1] > a[0] && a[1] > a[2]) + i = 1; + else + i = 2; + + o = v[i]; + VectorCopy (vec3_origin, v); + if (o<0) + v[i] = -1; + else + v[i] = 1; + +} + + +/* +=========== +Drag_Setup +=========== +*/ +void Drag_Setup (int x, int y, int buttons, + vec3_t xaxis, vec3_t yaxis, + vec3_t origin, vec3_t dir) +{ + trace_t t; + face_t *f; + + if (selected_brushes.next == &selected_brushes) + { + Sys_Status("No selection to drag\n", 0); + return; + } + + drag_first = true; + g_qeglobals.d_num_move_points = 0; + VectorCopy (vec3_origin, pressdelta); + pressx = x; + pressy = y; + + VectorCopy (xaxis, drag_xvec); + AxializeVector (drag_xvec); + VectorCopy (yaxis, drag_yvec); + AxializeVector (drag_yvec); + + if (g_qeglobals.d_select_mode == sel_vertex) + { + SelectVertexByRay (origin, dir); + if (g_qeglobals.d_num_move_points) + { + drag_ok = true; + return; + } + } + if (g_qeglobals.d_select_mode == sel_edge) + { + SelectEdgeByRay (origin, dir); + if (g_qeglobals.d_num_move_points) + { + drag_ok = true; + return; + } + } + + + // + // check for direct hit first + // + t = Test_Ray (origin, dir, true); + if (t.selected) + { + drag_ok = true; + + if (buttons == (MK_LBUTTON|MK_CONTROL) ) + { + Sys_Printf ("Shear dragging face\n"); + Brush_SelectFaceForDragging (t.brush, t.face, true); + } + else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) ) + { + Sys_Printf ("Sticky dragging brush\n"); + for (f=t.brush->brush_faces ; f ; f=f->next) + Brush_SelectFaceForDragging (t.brush, f, false); + } + else + Sys_Printf ("Dragging entire selection\n"); + + return; + } + + if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge) + return; + + // + // check for side hit + // + if (selected_brushes.next->next != &selected_brushes) + { + Sys_Printf ("Click isn't inside multiple selection\n"); + return; + } + + if (selected_brushes.next->owner->eclass->fixedsize) + { + Sys_Printf ("Can't stretch fixed size entities\n"); + return; + } + + + if (buttons & MK_CONTROL) + Brush_SideSelect (selected_brushes.next, origin, dir, true); + else + Brush_SideSelect (selected_brushes.next, origin, dir, false); + + + Sys_Printf ("Side stretch\n"); + drag_ok = true; +} + +entity_t *peLink; + +void UpdateTarget(vec3_t origin, vec3_t dir) +{ + trace_t t; + entity_t *pe; + int i; + char sz[128]; + + t = Test_Ray (origin, dir, 0); + + if (!t.brush) + return; + + pe = t.brush->owner; + + if (pe == NULL) + return; + + // is this the first? + if (peLink != NULL) + { + + // Get the target id from out current target + // if there is no id, make one + + i = IntForKey(pe, "target"); + if (i <= 0) + { + i = GetUniqueTargetId(1); + sprintf(sz, "%d", i); + + SetKeyValue(pe, "target", sz); + } + + // set the target # into our src + + sprintf(sz, "%d", i); + SetKeyValue(peLink, "targetname", sz); + + Sys_UpdateWindows(W_ENTITY); + + } + + // promote the target to the src + + peLink = pe; + +} + +/* +=========== +Drag_Begin +=========== +*/ +void Drag_Begin (int x, int y, int buttons, + vec3_t xaxis, vec3_t yaxis, + vec3_t origin, vec3_t dir) +{ + trace_t t; + + drag_ok = false; + VectorCopy (vec3_origin, pressdelta); + + drag_first = true; + peLink = NULL; + + // shift LBUTTON = select entire brush + if (buttons == (MK_LBUTTON | MK_SHIFT)) + { + if (!dir[0] && !dir[1]) + Select_Ray (origin, dir, SF_ENTITIES_FIRST); // hack for XY + else + Select_Ray (origin, dir, 0); + return; + } + + // ctrl-shift LBUTTON = select single face + if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) + { + Select_Deselect (); + Select_Ray (origin, dir, SF_SINGLEFACE); + return; + } + + // LBUTTON + all other modifiers = manipulate selection + if (buttons & MK_LBUTTON) + { + Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir); + return; + } + + // middle button = grab texture + if (buttons == MK_MBUTTON) + { + t = Test_Ray (origin, dir, false); + if (t.face) + { + g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2]; + g_qeglobals.d_new_brush_top_z = t.brush->maxs[2]; + Texture_SetTexture (&t.face->texdef); + } + else + Sys_Printf ("Did not select a texture\n"); + return; + } + + // ctrl-middle button = set entire brush to texture + if (buttons == (MK_MBUTTON|MK_CONTROL) ) + { + t = Test_Ray (origin, dir, false); + if (t.brush) + { + if (t.brush->brush_faces->texdef.name[0] == '(') + Sys_Printf ("Can't change an entity texture\n"); + else + { + Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef); + Sys_UpdateWindows (W_ALL); + } + } + else + Sys_Printf ("Didn't hit a btrush\n"); + return; + } + + // ctrl-shift-middle button = set single face to texture + if (buttons == (MK_MBUTTON|MK_SHIFT|MK_CONTROL) ) + { + t = Test_Ray (origin, dir, false); + if (t.brush) + { + if (t.brush->brush_faces->texdef.name[0] == '(') + Sys_Printf ("Can't change an entity texture\n"); + else + { + t.face->texdef = g_qeglobals.d_texturewin.texdef; + Brush_Build( t.brush ); + Sys_UpdateWindows (W_ALL); + } + } + else + Sys_Printf ("Didn't hit a btrush\n"); + return; + } + +} + + +/* +=========== +MoveSelection +=========== +*/ +void MoveSelection (vec3_t move) +{ + int i; + brush_t *b; + + if (!move[0] && !move[1] && !move[2]) + return; + + Sys_UpdateWindows (W_XY|W_CAMERA); + + // + // dragging only a part of the selection + // + if (g_qeglobals.d_num_move_points) + { + for (i=0 ; inext) + { + Brush_Build( b ); + for (i=0 ; i<3 ; i++) + if (b->mins[i] > b->maxs[i] + || b->maxs[i] - b->mins[i] > 4096) + break; // dragged backwards or fucked up + if (i != 3) + break; + } + + // if any of the brushes were crushed out of existance + // calcel the entire move + if (b != &selected_brushes) + { + Sys_Printf ("Brush dragged backwards, move canceled\n"); + for (i=0 ; inext) + Brush_Build( b ); + } + + } + else + { + // + // if there are lots of brushes selected, just translate instead + // of rebuilding the brushes + // + if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes) + { + VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate); + } + else + { + Select_Move (move); + } + } +} + +/* +=========== +Drag_MouseMoved +=========== +*/ +void Drag_MouseMoved (int x, int y, int buttons) +{ + vec3_t move, delta; + int i; + char movestring[128]; + + if (!buttons) + { + drag_ok = false; + return; + } + if (!drag_ok) + return; + + // clear along one axis + if (buttons & MK_SHIFT) + { + drag_first = false; + if (abs(x-pressx) > abs(y-pressy)) + y = pressy; + else + x = pressx; + } + + + for (i=0 ; i<3 ; i++) + { + move[i] = drag_xvec[i]*(x - pressx) + + drag_yvec[i]*(y - pressy); + move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; + } + + sprintf (movestring, "drag (%i %i %i)", (int)move[0], (int)move[1], (int)move[2]); + Sys_Status (movestring, 0); + + VectorSubtract (move, pressdelta, delta); + MoveSelection (delta); + VectorCopy (move, pressdelta); +} + +/* +=========== +Drag_MouseUp +=========== +*/ +void Drag_MouseUp (void) +{ + Sys_Status ("drag completed.", 0); + if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2]) + { + Select_Move (g_qeglobals.d_select_translate); + VectorCopy (vec3_origin, g_qeglobals.d_select_translate); + Sys_UpdateWindows (W_CAMERA); + } +} diff --git a/tools/quake2/extra/qe4/eclass.c b/tools/quake2/extra/qe4/eclass.c new file mode 100644 index 00000000..466d8a48 --- /dev/null +++ b/tools/quake2/extra/qe4/eclass.c @@ -0,0 +1,281 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" +#include "io.h" + +eclass_t *eclass; +eclass_t *eclass_bad; +char eclass_directory[1024]; + +/* + +the classname, color triple, and bounding box are parsed out of comments +A ? size means take the exact brush size. + +/*QUAKED (0 0 0) ? +/*QUAKED (0 0 0) (-8 -8 -8) (8 8 8) + +Flag names can follow the size description: + +/*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY + +*/ +char *debugname; + +eclass_t *Eclass_InitFromText (char *text) +{ + char *t; + int len; + int r, i; + char parms[256], *p; + eclass_t *e; + char color[128]; + + e = qmalloc(sizeof(*e)); + memset (e, 0, sizeof(*e)); + + text += strlen("/*QUAKED "); + +// grab the name + text = COM_Parse (text); + e->name = qmalloc (strlen(com_token)+1); + strcpy (e->name, com_token); + debugname = e->name; + +// grab the color, reformat as texture name + r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]); + if (r != 3) + return e; + sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]); + strcpy (e->texdef.name, color); + + while (*text != ')') + { + if (!*text) + return e; + text++; + } + text++; + +// get the size + text = COM_Parse (text); + if (com_token[0] == '(') + { // parse the size as two vectors + e->fixedsize = true; + r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2], + &e->maxs[0], &e->maxs[1], &e->maxs[2]); + if (r != 6) + return e; + + for (i=0 ; i<2 ; i++) + { + while (*text != ')') + { + if (!*text) + return e; + text++; + } + text++; + } + } + else + { // use the brushes + } + +// get the flags + + +// copy to the first /n + p = parms; + while (*text && *text != '\n') + *p++ = *text++; + *p = 0; + text++; + +// any remaining words are parm flags + p = parms; + for (i=0 ; i<8 ; i++) + { + p = COM_Parse (p); + if (!p) + break; + strcpy (e->flagnames[i], com_token); + } + +// find the length until close comment + for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++) + ; + +// copy the comment block out + len = t-text; + e->comments = qmalloc (len+1); + memcpy (e->comments, text, len); +#if 0 + for (i=0 ; icomments[i] = '\r'; + else + e->comments[i] = text[i]; +#endif + e->comments[len] = 0; + + return e; +} + + +/* +================= +Eclass_InsertAlphabetized +================= +*/ +void Eclass_InsertAlphabetized (eclass_t *e) +{ + eclass_t *s; + + if (!eclass) + { + eclass = e; + return; + } + + + s = eclass; + if (stricmp (e->name, s->name) < 0) + { + e->next = s; + eclass = e; + return; + } + + do + { + if (!s->next || stricmp (e->name, s->next->name) < 0) + { + e->next = s->next; + s->next = e; + return; + } + s=s->next; + } while (1); +} + + +/* +================= +Eclass_ScanFile +================= +*/ +void Eclass_ScanFile (char *filename) +{ + int size; + char *data; + eclass_t *e; + int i; + char temp[1024]; + + QE_ConvertDOSToUnixName( temp, filename ); + + Sys_Printf ("ScanFile: %s\n", temp); + + size = LoadFile (filename, (void *)&data); + + for (i=0 ; inext) + if (!strcmp (name, e->name)) + return e; + + // create a new class for it + if (has_brushes) + { + sprintf (init, "/*QUAKED %s (0 0.5 0) ?\nNot found in source.\n", name); + e = Eclass_InitFromText (init); + } + else + { + sprintf (init, "/*QUAKED %s (0 0.5 0) (-8 -8 -8) (8 8 8)\nNot found in source.\n", name); + e = Eclass_InitFromText (init); + } + + Eclass_InsertAlphabetized (e); + + return e; +} + diff --git a/tools/quake2/extra/qe4/entity.c b/tools/quake2/extra/qe4/entity.c new file mode 100644 index 00000000..7cbe14ae --- /dev/null +++ b/tools/quake2/extra/qe4/entity.c @@ -0,0 +1,538 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +char *ValueForKey (entity_t *ent, char *key) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + return ep->value; + return ""; +} + +void SetKeyValue (entity_t *ent, char *key, char *value) +{ + epair_t *ep; + + if (ent == NULL) + return; + + if (!key || !key[0]) + return; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + { + free (ep->value); + ep->value = qmalloc(strlen(value)+1); + strcpy (ep->value, value); + return; + } + ep = qmalloc (sizeof(*ep)); + ep->next = ent->epairs; + ent->epairs = ep; + ep->key = qmalloc(strlen(key)+1); + strcpy (ep->key, key); + ep->value = qmalloc(strlen(value)+1); + strcpy (ep->value, value); +} + +void DeleteKey (entity_t *ent, char *key) +{ + epair_t **ep, *next; + + ep = &ent->epairs; + while (*ep) + { + next = *ep; + if ( !strcmp (next->key, key) ) + { + *ep = next->next; + free(next->key); + free(next->value); + free(next); + return; + } + ep = &next->next; + } +} + +float FloatForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atof(k); +} + +int IntForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atoi(k); +} + +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) +{ + char *k; + + k = ValueForKey (ent, key); + sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]); +} + + +/* +=============== +Entity_Free + +Frees the entity and any brushes is has. +The entity is removed from the global entities list. +=============== +*/ +void Entity_Free (entity_t *e) +{ + epair_t *ep, *next; + + while (e->brushes.onext != &e->brushes) + Brush_Free (e->brushes.onext); + + if (e->next) + { + e->next->prev = e->prev; + e->prev->next = e->next; + } + + for (ep = e->epairs ; ep ; ep=next) + { + next = ep->next; + free (ep); + } + free (e); +} + +/* +================= +ParseEpair +================= +*/ +epair_t *ParseEpair (void) +{ + epair_t *e; + + e = qmalloc (sizeof(*e)); + + e->key = qmalloc(strlen(token)+1); + strcpy (e->key, token); + + GetToken (false); + e->value = qmalloc(strlen(token)+1); + strcpy (e->value, token); + + return e; +} + +/* +================ +Entity_Parse + +If onlypairs is set, the classname info will not +be looked up, and the entity will not be added +to the global list. Used for parsing the project. +================ +*/ +entity_t *Entity_Parse (qboolean onlypairs) +{ + entity_t *ent; + eclass_t *e; + brush_t *b; + vec3_t mins, maxs; + epair_t *ep; + qboolean has_brushes; + + if (!GetToken (true)) + return NULL; + + if (strcmp (token, "{") ) + Error ("ParseEntity: { not found"); + + ent = qmalloc (sizeof(*ent)); + ent->brushes.onext = ent->brushes.oprev = &ent->brushes; + + do + { + if (!GetToken (true)) + Error ("ParseEntity: EOF without closing brace"); + if (!strcmp (token, "}") ) + break; + if (!strcmp (token, "{") ) + { + b = Brush_Parse (); + b->owner = ent; + + // add to the end of the entity chain + b->onext = &ent->brushes; + b->oprev = ent->brushes.oprev; + ent->brushes.oprev->onext = b; + ent->brushes.oprev = b; + } + else + { + ep = ParseEpair (); + ep->next = ent->epairs; + ent->epairs = ep; + } + } while (1); + + if (onlypairs) + return ent; + + if (ent->brushes.onext == &ent->brushes) + has_brushes = false; + else + has_brushes = true; + + GetVectorForKey (ent, "origin", ent->origin); + + e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes); + ent->eclass = e; + if (e->fixedsize) + { // fixed size entity + if (ent->brushes.onext != &ent->brushes) + { + printf ("Warning: Fixed size entity with brushes\n"); +#if 0 + while (ent->brushes.onext != &ent->brushes) + { // FIXME: this will free the entity and crash! + Brush_Free (b); + } +#endif +ent->brushes.next = ent->brushes.prev = &ent->brushes; + } + // create a custom brush + VectorAdd (e->mins, ent->origin, mins); + VectorAdd (e->maxs, ent->origin, maxs); + b = Brush_Create (mins, maxs, &e->texdef); + b->owner = ent; + + b->onext = ent->brushes.onext; + b->oprev = &ent->brushes; + ent->brushes.onext->oprev = b; + ent->brushes.onext = b; + } + else + { // brush entity + if (ent->brushes.next == &ent->brushes) + printf ("Warning: Brush entity with no brushes\n"); + } + + // add all the brushes to the main list + for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext) + { + b->next = active_brushes.next; + active_brushes.next->prev = b; + b->prev = &active_brushes; + active_brushes.next = b; + } + + return ent; +} + +/* +============ +Entity_Write +============ +*/ +void Entity_Write (entity_t *e, FILE *f, qboolean use_region) +{ + epair_t *ep; + brush_t *b; + vec3_t origin; + char text[128]; + int count; + + // if none of the entities brushes are in the region, + // don't write the entity at all + if (use_region) + { + // in region mode, save the camera position as playerstart + if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") ) + { + fprintf (f, "{\n"); + fprintf (f, "\"classname\" \"info_player_start\"\n"); + fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)camera.origin[0], + (int)camera.origin[1], (int)camera.origin[2]); + fprintf (f, "\"angle\" \"%i\"\n", (int)camera.angles[YAW]); + fprintf (f, "}\n"); + return; + } + + for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) + if (!Map_IsBrushFiltered(b)) + break; // got one + + if (b == &e->brushes) + return; // nothing visible + } + + // if fixedsize, calculate a new origin based on the current + // brush position + if (e->eclass->fixedsize) + { + VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin); + sprintf (text, "%i %i %i", (int)origin[0], + (int)origin[1], (int)origin[2]); + SetKeyValue (e, "origin", text); + } + + fprintf (f, "{\n"); + for (ep = e->epairs ; ep ; ep=ep->next) + fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value); + + if (!e->eclass->fixedsize) + { + count = 0; + for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) + { + if (!use_region || !Map_IsBrushFiltered (b)) + { + fprintf (f, "// brush %i\n", count); + count++; + Brush_Write (b, f); + } + } + } + fprintf (f, "}\n"); +} + + + +/* +============ +Entity_Create + +Creates a new entity out of the selected_brushes list. +If the entity class is fixed size, the brushes are only +used to find a midpoint. Otherwise, the brushes have +their ownershi[ transfered to the new entity. +============ +*/ +entity_t *Entity_Create (eclass_t *c) +{ + entity_t *e; + brush_t *b; + vec3_t mins, maxs; + int i; + + // check to make sure the brushes are ok + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + if (b->owner != world_entity) + { + Sys_Printf ("Entity NOT created, brushes not all from world\n"); + Sys_Beep (); + return NULL; + } + + // create it + + e = qmalloc(sizeof(*e)); + e->brushes.onext = e->brushes.oprev = &e->brushes; + e->eclass = c; + SetKeyValue (e, "classname", c->name); + + // add the entity to the entity list + e->next = entities.next; + entities.next = e; + e->next->prev = e; + e->prev = &entities; + + if (c->fixedsize) + { + // + // just use the selection for positioning + // + b = selected_brushes.next; + for (i=0 ; i<3 ; i++) + e->origin[i] = b->mins[i] - c->mins[i]; + + // create a custom brush + VectorAdd (c->mins, e->origin, mins); + VectorAdd (c->maxs, e->origin, maxs); + b = Brush_Create (mins, maxs, &c->texdef); + + Entity_LinkBrush (e, b); + + // delete the current selection + Select_Delete (); + + // select the new brush + b->next = b->prev = &selected_brushes; + selected_brushes.next = selected_brushes.prev = b; + + Brush_Build( b ); + } + else + { + // + // change the selected brushes over to the new entity + // + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + Entity_UnlinkBrush (b); + Entity_LinkBrush (e, b); + Brush_Build( b ); // so the key brush gets a name + } + } + + Sys_UpdateWindows (W_ALL); + return e; +} + + +/* +=========== +Entity_LinkBrush +=========== +*/ +void Entity_LinkBrush (entity_t *e, brush_t *b) +{ + if (b->oprev || b->onext) + Error ("Entity_LinkBrush: Allready linked"); + b->owner = e; + + b->onext = e->brushes.onext; + b->oprev = &e->brushes; + e->brushes.onext->oprev = b; + e->brushes.onext = b; +} + +/* +=========== +Entity_UnlinkBrush +=========== +*/ +void Entity_UnlinkBrush (brush_t *b) +{ + if (!b->owner || !b->onext || !b->oprev) + Error ("Entity_UnlinkBrush: Not currently linked"); + b->onext->oprev = b->oprev; + b->oprev->onext = b->onext; + b->onext = b->oprev = NULL; + b->owner = NULL; +} + + + +/* +=========== +Entity_Clone +=========== +*/ +entity_t *Entity_Clone (entity_t *e) +{ + entity_t *n; + epair_t *ep, *np; + + n = qmalloc(sizeof(*n)); + n->brushes.onext = n->brushes.oprev = &n->brushes; + n->eclass = e->eclass; + + // add the entity to the entity list + n->next = entities.next; + entities.next = n; + n->next->prev = n; + n->prev = &entities; + + for (ep = e->epairs ; ep ; ep=ep->next) + { + np = qmalloc(sizeof(*np)); + np->key = copystring(ep->key); + np->value = copystring(ep->value); + np->next = n->epairs; + n->epairs = np; + } + return n; +} + +int GetUniqueTargetId(int iHint) +{ + int iMin, iMax, i; + BOOL fFound; + entity_t *pe; + + fFound = FALSE; + pe = entities.next; + iMin = 0; + iMax = 0; + + for (; pe != NULL && pe != &entities ; pe = pe->next) + { + i = IntForKey(pe, "target"); + if (i) + { + iMin = min(i, iMin); + iMax = max(i, iMax); + if (i == iHint) + fFound = TRUE; + } + } + + if (fFound) + return iMax + 1; + else + return iHint; +} + +entity_t *FindEntity(char *pszKey, char *pszValue) +{ + entity_t *pe; + + pe = entities.next; + + for (; pe != NULL && pe != &entities ; pe = pe->next) + { + if (!strcmp(ValueForKey(pe, pszKey), pszValue)) + return pe; + } + + return NULL; +} + +entity_t *FindEntityInt(char *pszKey, int iValue) +{ + entity_t *pe; + + pe = entities.next; + + for (; pe != NULL && pe != &entities ; pe = pe->next) + { + if (IntForKey(pe, pszKey) == iValue) + return pe; + } + + return NULL; +} + diff --git a/tools/quake2/extra/qe4/entity.h b/tools/quake2/extra/qe4/entity.h new file mode 100644 index 00000000..012f08dc --- /dev/null +++ b/tools/quake2/extra/qe4/entity.h @@ -0,0 +1,84 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// entity.h + + +#define MAX_FLAGS 8 + +typedef struct eclass_s +{ + struct eclass_s *next; + char *name; + qboolean fixedsize; + qboolean unknown; // wasn't found in source + vec3_t mins, maxs; + vec3_t color; + texdef_t texdef; + char *comments; + char flagnames[MAX_FLAGS][32]; +} eclass_t; + +extern eclass_t *eclass; + +void Eclass_InitForSourceDirectory (char *path); +eclass_t *Eclass_ForName (char *name, qboolean has_brushes); + +//=================================================== + + +typedef struct epair_s +{ + struct epair_s *next; + char *key; + char *value; +} epair_t; + +typedef struct entity_s +{ + struct entity_s *prev, *next; + brush_t brushes; // head/tail of list + vec3_t origin; + eclass_t *eclass; + epair_t *epairs; +} entity_t; + +char *ValueForKey (entity_t *ent, char *key); +void SetKeyValue (entity_t *ent, char *key, char *value); +void DeleteKey (entity_t *ent, char *key); +float FloatForKey (entity_t *ent, char *key); +int IntForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); + +void Entity_Free (entity_t *e); +entity_t *Entity_Parse (qboolean onlypairs); +void Entity_Write (entity_t *e, FILE *f, qboolean use_region); +entity_t *Entity_Create (eclass_t *c); +entity_t *Entity_Clone (entity_t *e); + +void Entity_LinkBrush (entity_t *e, brush_t *b); +void Entity_UnlinkBrush (brush_t *b); +entity_t *FindEntity(char *pszKey, char *pszValue); +entity_t *FindEntityInt(char *pszKey, int iValue); + +int GetUniqueTargetId(int iHint); + diff --git a/tools/quake2/extra/qe4/entityw.h b/tools/quake2/extra/qe4/entityw.h new file mode 100644 index 00000000..d3f7bd05 --- /dev/null +++ b/tools/quake2/extra/qe4/entityw.h @@ -0,0 +1,66 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// entity.h + +#define DlgXBorder 5 +#define DlgYBorder 5 + + +#define EntList 0 +#define EntComment 1 +#define EntCheck1 2 +#define EntCheck2 3 +#define EntCheck3 4 +#define EntCheck4 5 +#define EntCheck5 6 +#define EntCheck6 7 +#define EntCheck7 8 +#define EntCheck8 9 +#define EntCheck9 10 +#define EntCheck10 11 +#define EntCheck11 12 +#define EntCheck12 13 +#define EntProps 14 +#define EntDir0 15 +#define EntDir45 16 +#define EntDir90 17 +#define EntDir135 18 +#define EntDir180 19 +#define EntDir225 20 +#define EntDir270 21 +#define EntDir315 22 +#define EntDirUp 23 +#define EntDirDown 24 +#define EntDelProp 25 +#define EntKeyLabel 26 +#define EntKeyField 27 +#define EntValueLabel 28 +#define EntValueField 29 +#define EntColor 30 + +#define EntLast 31 + +extern HWND hwndEnt[EntLast]; + +extern int rgIds[EntLast]; + diff --git a/tools/quake2/extra/qe4/glingr.h b/tools/quake2/extra/qe4/glingr.h new file mode 100644 index 00000000..19cb1c5e --- /dev/null +++ b/tools/quake2/extra/qe4/glingr.h @@ -0,0 +1,98 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// This .h file contains constants, typedefs, etc. for Intergraph +// extensions to OpenGL. These extensions are: +// +// Multiple Palette Extension +// Texture Object Extension + +#define GL_INGR_multiple_palette 1 +#define GL_EXT_texture_object 1 + + +// New constants and typedefs for the Multiple Palette Extension +#define GL_PALETTE_INGR 0x80c0 +#define GL_MAX_PALETTES_INGR 0x80c1 +#define GL_MAX_PALETTE_ENTRIES_INGR 0x80c2 +#define GL_CURRENT_PALETTE_INGR 0x80c3 +#define GL_PALETTE_WRITEMASK_INGR 0x80c4 +#define GL_CURRENT_RASTER_PALETTE_INGR 0x80c5 +#define GL_PALETTE_CLEAR_VALUE_INGR 0x80c6 + +// Function prototypes for the Multiple Palette Extension routines +typedef void (APIENTRY *PALETTEFUNCPTR)(GLuint); +typedef void (APIENTRY *PALETTEMASKFUNCPTR)(GLboolean); +typedef void (APIENTRY *WGLLOADPALETTEFUNCPTR)(GLuint, GLsizei, GLuint *); +typedef void (APIENTRY *CLEARPALETTEFUNCPTR)(GLuint); + + +// New Constants and typedefs for the Texture Object Extension +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 + +// Function prototypes for the Texture Object Extension routines +typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *, + const GLboolean *); +typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint); +typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *); +typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *); +typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint); +typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *, + const GLclampf *); + + +/* OpenGL ExtEscape escape function constants */ +#ifndef OPENGL_GETINFO +#define OPENGL_GETINFO 4353 /* for OpenGL ExtEscape */ +#endif + +// OPENGL_GETINFO ExtEscape sub-escape numbers. They are defined by +// Microsoft. + +#ifndef OPENGL_GETINFO_DRVNAME + +#define OPENGL_GETINFO_DRVNAME 0 + + +// Input structure for OPENGL_GETINFO ExtEscape. + +typedef struct _OPENGLGETINFO +{ + ULONG ulSubEsc; +} OPENGLGETINFO, *POPENGLGETINFO; + + +// Output structure for OPENGL_GETINFO_DRVNAME ExtEscape. + +typedef struct _GLDRVNAMERET +{ + ULONG ulVersion; // must be 1 for this version + ULONG ulDriverVersion; // driver specific version number + WCHAR awch[MAX_PATH+1]; +} GLDRVNAMERET, *PGLDRVNAMERET; + +#endif + + diff --git a/tools/quake2/extra/qe4/icon1.ico b/tools/quake2/extra/qe4/icon1.ico new file mode 100644 index 0000000000000000000000000000000000000000..d24956b6fe8f7efa2e945a98d72380e6c10ed564 GIT binary patch literal 766 zcmeH_K@P$o6huGOq+3^RW$7*SNZz2_z#~E80XPC(nz%4cV;TbOILO8rZ=myef8bBp z5JVJ9>x~p$8<8!2Pc%6aC2MvO!|b~ZLng*lW9L?!bMzA6wFD?T!YZTE{`%<`;2)^U zD 0x80) + { + rept = (rept^0xff)+2; + b = *source++; + memset(unpacked,b,rept); + unpacked += rept; + } + else if (rept < 0x80) + { + rept++; + memcpy(unpacked,source,rept); + unpacked += rept; + source += rept; + } + else + rept = 0; // rept of 0x80 is NOP + + count += rept; + + } while (countbpwidth) + Error ("Decompression exceeded width!\n"); + + + return source; +} + + +/* +================= +LoadLBM +================= +*/ +void LoadLBM (char *filename, byte **picture, byte **palette) +{ + byte *LBMbuffer, *picbuffer, *cmapbuffer; + int y; + byte *LBM_P, *LBMEND_P; + byte *pic_p; + byte *body_p; + + int formtype,formlength; + int chunktype,chunklength; + +// qiet compiler warnings + picbuffer = NULL; + cmapbuffer = NULL; + +// +// load the LBM +// + LoadFile (filename, (void **)&LBMbuffer); + +// +// parse the LBM header +// + LBM_P = LBMbuffer; + if ( *(int *)LBMbuffer != LittleLong(FORMID) ) + Error ("No FORM ID at start of file!\n"); + + LBM_P += 4; + formlength = BigLong( *(int *)LBM_P ); + LBM_P += 4; + LBMEND_P = LBM_P + Align(formlength); + + formtype = LittleLong(*(int *)LBM_P); + + if (formtype != ILBMID && formtype != PBMID) + Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff + ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); + + LBM_P += 4; + +// +// parse chunks +// + + while (LBM_P < LBMEND_P) + { + chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); + LBM_P += 4; + chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); + LBM_P += 4; + + switch ( chunktype ) + { + case BMHDID: + memcpy (&bmhd,LBM_P,sizeof(bmhd)); + bmhd.w = BigShort(bmhd.w); + bmhd.h = BigShort(bmhd.h); + bmhd.x = BigShort(bmhd.x); + bmhd.y = BigShort(bmhd.y); + bmhd.pageWidth = BigShort(bmhd.pageWidth); + bmhd.pageHeight = BigShort(bmhd.pageHeight); + break; + + case CMAPID: + cmapbuffer = malloc (768); + memset (cmapbuffer, 0, 768); + memcpy (cmapbuffer, LBM_P, chunklength); + break; + + case BODYID: + body_p = LBM_P; + + pic_p = picbuffer = malloc (bmhd.w*bmhd.h); + if (formtype == PBMID) + { + // + // unpack PBM + // + for (y=0 ; ydata; + + pcx->xmin = LittleShort(pcx->xmin); + pcx->ymin = LittleShort(pcx->ymin); + pcx->xmax = LittleShort(pcx->xmax); + pcx->ymax = LittleShort(pcx->ymax); + pcx->hres = LittleShort(pcx->hres); + pcx->vres = LittleShort(pcx->vres); + pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); + pcx->palette_type = LittleShort(pcx->palette_type); + + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8 + || pcx->xmax >= 640 + || pcx->ymax >= 480) + Error ("Bad pcx file %s", filename); + + if (palette) + { + *palette = malloc(768); + memcpy (*palette, (byte *)pcx + len - 768, 768); + } + + if (width) + *width = pcx->xmax+1; + if (height) + *height = pcx->ymax+1; + + if (!pic) + return; + + out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); + if (!out) + Error ("Skin_Cache: couldn't allocate"); + + *pic = out; + + pix = out; + + for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) + { + for (x=0 ; x<=pcx->xmax ; ) + { + dataByte = *raw++; + + if((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = *raw++; + } + else + runLength = 1; + + while(runLength-- > 0) + pix[x++] = dataByte; + } + + } + + if ( raw - (byte *)pcx > len) + Error ("PCX file %s was malformed", filename); + + free (pcx); +} + +/* +============== +WritePCXfile +============== +*/ +void WritePCXfile (char *filename, byte *data, + int width, int height, byte *palette) +{ + int i, j, length; + pcx_t *pcx; + byte *pack; + + pcx = malloc (width*height*2+1000); + memset (pcx, 0, sizeof(*pcx)); + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort((short)(width-1)); + pcx->ymax = LittleShort((short)(height-1)); + pcx->hres = LittleShort((short)width); + pcx->vres = LittleShort((short)height); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort((short)width); + pcx->palette_type = LittleShort(2); // not a grey scale + + // pack the image + pack = &pcx->data; + + for (i=0 ; i=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + else { // non run-length packet + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + } + breakOut:; + } + } + + fclose(fin); +} diff --git a/tools/quake2/extra/qe4/lbmlib.h b/tools/quake2/extra/qe4/lbmlib.h new file mode 100644 index 00000000..c90a6dd8 --- /dev/null +++ b/tools/quake2/extra/qe4/lbmlib.h @@ -0,0 +1,40 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// piclib.h + + +void LoadLBM (char *filename, byte **picture, byte **palette); +void WriteLBMfile (char *filename, byte *data, int width, int height + , byte *palette); +void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height); +void WritePCXfile (char *filename, byte *data, int width, int height + , byte *palette); + +// loads / saves either lbm or pcx, depending on extension +void Load256Image (char *name, byte **pixels, byte **palette, + int *width, int *height); +void Save256Image (char *name, byte *pixels, byte *palette, + int width, int height); + + +void LoadTGA (char *filename, byte **pixels, int *width, int *height); diff --git a/tools/quake2/extra/qe4/makefile b/tools/quake2/extra/qe4/makefile new file mode 100644 index 00000000..7797ac31 --- /dev/null +++ b/tools/quake2/extra/qe4/makefile @@ -0,0 +1,23 @@ + +TARGETOS=WINNT + +!include + +# This line allows NMAKE to work as well + +all: gengl.exe + +# Update the object file if necessary + +gengl.obj: gengl.c gengl.h + $(cc) $(cflags) $(cvars) $(cdebug) $(cf) gengl.c + +render.obj: render.c gengl.h + $(cc) $(cflags) $(cvars) $(cdebug) $(cf) render.c + +gengl.res: gengl.rc genglrc.h + rc -r gengl.rc + +gengl.exe: gengl.obj gengl.res render.obj + $(link) $(linkdebug) /NODEFAULTLIB $(guilflags) -out:gengl.exe \ + gengl.obj render.obj gengl.res $(guilibsdll) opengl32.lib glu32.lib diff --git a/tools/quake2/extra/qe4/map.c b/tools/quake2/extra/qe4/map.c new file mode 100644 index 00000000..9528e152 --- /dev/null +++ b/tools/quake2/extra/qe4/map.c @@ -0,0 +1,661 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// map.c + +#include "qe3.h" + +qboolean modified; // for quit confirmation (0 = clean, 1 = unsaved, + // 2 = autosaved, but not regular saved) + +char currentmap[1024]; + +brush_t active_brushes; // brushes currently being displayed +brush_t selected_brushes; // highlighted +face_t *selected_face; +brush_t *selected_face_brush; +brush_t filtered_brushes; // brushes that have been filtered or regioned + +entity_t entities; // head/tail of doubly linked list + +entity_t *world_entity; + +void AddRegionBrushes (void); +void RemoveRegionBrushes (void); + +/* +============================================================= + + Cross map selection saving + + this could fuck up if you have only part of a complex entity selected... +============================================================= +*/ + +brush_t between_brushes; +entity_t between_entities; + + +void Map_SaveBetween (void) +{ + brush_t *b; + entity_t *e, *e2; + + between_brushes.next = selected_brushes.next; + between_brushes.prev = selected_brushes.prev; + between_brushes.next->prev = &between_brushes; + between_brushes.prev->next = &between_brushes; + + between_entities.next = between_entities.prev = &between_entities; + selected_brushes.next = selected_brushes.prev = &selected_brushes; + + for (b=between_brushes.next ; b != &between_brushes ; b=b->next) + { + e = b->owner; + if (e == world_entity) + b->owner = NULL; + else + { + for (e2=between_entities.next ; e2 != &between_entities ; e2=e2->next) + if (e2 == e) + goto next; // allready got the entity + // move the entity over + e->prev->next = e->next; + e->next->prev = e->prev; + e->next = between_entities.next; + e->prev = &between_entities; + e->next->prev = e; + e->prev->next = e; + } +next: ; + } +} + +void Map_RestoreBetween (void) +{ + entity_t *head, *tail; + brush_t *b; + + if (!between_brushes.next) + return; + + for (b=between_brushes.next ; b != &between_brushes ; b=b->next) + { + if (!b->owner) + { + b->owner = world_entity; + b->onext = world_entity->brushes.onext; + b->oprev = &world_entity->brushes; + b->onext->oprev = b; + b->oprev->onext = b; + } + } + + selected_brushes.next = between_brushes.next; + selected_brushes.prev = between_brushes.prev; + selected_brushes.next->prev = &selected_brushes; + selected_brushes.prev->next = &selected_brushes; + + head = between_entities.next; + tail = between_entities.prev; + + if (head != tail) + { + entities.prev->next = head; + head->prev = entities.prev; + tail->next = &entities; + entities.prev = tail; + } + + between_brushes.next = NULL; + between_entities.next = NULL; +} + +//============================================================================ + +void Map_BuildBrushData(void) +{ + brush_t *b, *next; + + if (active_brushes.next == NULL) + return; + + Sys_BeginWait (); // this could take a while + + for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=next) + { + next = b->next; + Brush_Build( b ); + if (!b->brush_faces) + { + Brush_Free (b); + Sys_Printf ("Removed degenerate brush\n"); + } + } + + Sys_EndWait(); +} + +entity_t *Map_FindClass (char *cname) +{ + entity_t *ent; + + for (ent = entities.next ; ent != &entities ; ent=ent->next) + { + if (!strcmp(cname, ValueForKey (ent, "classname"))) + return ent; + } + return NULL; +} + +/* +================ +Map_Free +================ +*/ +void Map_Free (void) +{ + if (selected_brushes.next && + (selected_brushes.next != &selected_brushes) ) + { + if (MessageBox(g_qeglobals.d_hwndMain, "Copy selection?", "", MB_YESNO) == IDYES) + Map_SaveBetween (); + } + + Texture_ClearInuse (); + Pointfile_Clear (); + strcpy (currentmap, "unnamed.map"); + Sys_SetTitle (currentmap); + g_qeglobals.d_num_entities = 0; + + if (!active_brushes.next) + { // first map + active_brushes.prev = active_brushes.next = &active_brushes; + selected_brushes.prev = selected_brushes.next = &selected_brushes; + filtered_brushes.prev = filtered_brushes.next = &filtered_brushes; + + entities.prev = entities.next = &entities; + } + else + { + while (active_brushes.next != &active_brushes) + Brush_Free (active_brushes.next); + while (selected_brushes.next != &selected_brushes) + Brush_Free (selected_brushes.next); + while (filtered_brushes.next != &filtered_brushes) + Brush_Free (filtered_brushes.next); + + while (entities.next != &entities) + Entity_Free (entities.next); + } + + world_entity = NULL; +} + +/* +================ +Map_LoadFile +================ +*/ +void Map_LoadFile (char *filename) +{ + char *buf; + entity_t *ent; + char temp[1024]; + + Sys_BeginWait (); + + SetInspectorMode(W_CONSOLE); + + QE_ConvertDOSToUnixName( temp, filename ); + Sys_Printf ("Map_LoadFile: %s\n", temp ); + + Map_Free (); + + g_qeglobals.d_parsed_brushes = 0; + strcpy (currentmap, filename); + LoadFile (filename, (void **)&buf); + + StartTokenParsing (buf); + + g_qeglobals.d_num_entities = 0; + + while (1) + { + ent = Entity_Parse (false); + if (!ent) + break; + if (!strcmp(ValueForKey (ent, "classname"), "worldspawn")) + { + if (world_entity) + Sys_Printf ("WARNING: multiple worldspawn\n"); + world_entity = ent; + } + else + { + // add the entity to the end of the entity list + ent->next = &entities; + ent->prev = entities.prev; + entities.prev->next = ent; + entities.prev = ent; + g_qeglobals.d_num_entities++; + } + } + + free (buf); + + if (!world_entity) + { + Sys_Printf ("No worldspawn in map.\n"); + Map_New (); + return; + } + + Sys_Printf ("--- LoadMapFile ---\n"); + Sys_Printf ("%s\n", temp ); + + Sys_Printf ("%5i brushes\n", g_qeglobals.d_parsed_brushes ); + Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities); + + Map_RestoreBetween (); + + Sys_Printf ("Map_BuildAllDisplayLists\n"); + Map_BuildBrushData(); + + // + // move the view to a start position + // + ent = Map_FindClass ("info_player_start"); + if (!ent) + ent = Map_FindClass ("info_player_deathmatch"); + camera.angles[PITCH] = 0; + if (ent) + { + GetVectorForKey (ent, "origin", camera.origin); + GetVectorForKey (ent, "origin", g_qeglobals.d_xy.origin); + camera.angles[YAW] = FloatForKey (ent, "angle"); + } + else + { + camera.angles[YAW] = 0; + VectorCopy (vec3_origin, camera.origin); + VectorCopy (vec3_origin, g_qeglobals.d_xy.origin); + } + + Sys_UpdateWindows (W_ALL); + + Map_RegionOff (); + + modified = false; + Sys_SetTitle (temp); + + Texture_ShowInuse (); + + Sys_EndWait(); + +} + +/* +=========== +Map_SaveFile +=========== +*/ +void Map_SaveFile (char *filename, qboolean use_region ) +{ + entity_t *e, *next; + FILE *f; + char temp[1024]; + int count; + + QE_ConvertDOSToUnixName( temp, filename ); + + if (!use_region) + { + char backup[1024]; + + // rename current to .bak + strcpy (backup, filename); + StripExtension (backup); + strcat (backup, ".bak"); + _unlink (backup); + rename (filename, backup); + } + + Sys_Printf ("Map_SaveFile: %s\n", filename); + + f = fopen(filename, "w"); + if (!f) + { + Sys_Printf ("ERROR!!!! Couldn't open %s\n", filename); + return; + } + + if (use_region) + AddRegionBrushes (); + + // write world entity first + Entity_Write (world_entity, f, use_region); + + // then write all other ents + count = 1; + for (e=entities.next ; e != &entities ; e=next) + { + fprintf (f, "// entity %i\n", count); + count++; + next = e->next; + if (e->brushes.onext == &e->brushes) + Entity_Free (e); // no brushes left, so remove it + else + Entity_Write (e, f, use_region); + } + + fclose (f); + + if (use_region) + RemoveRegionBrushes (); + + Sys_Printf ("Saved.\n"); + modified = false; + + if ( !strstr( temp, "autosave" ) ) + Sys_SetTitle (temp); + + if (!use_region) + { + time_t timer; + FILE *f; + + time (&timer); + MessageBeep (MB_ICONEXCLAMATION); + f = fopen ("c:/tstamps.log", "a"); + if (f) + { + fprintf (f, "%4i : %35s : %s", g_qeglobals.d_workcount, filename, ctime(&timer)); + fclose (f); + g_qeglobals.d_workcount = 0; + } + fclose (f); + Sys_Status ("Saved.\n", 0); + } +} + +/* +=========== +Map_New +=========== +*/ +void Map_New (void) +{ + Sys_Printf ("Map_New\n"); + Map_Free (); + world_entity = qmalloc(sizeof(*world_entity)); + world_entity->brushes.onext = + world_entity->brushes.oprev = &world_entity->brushes; + SetKeyValue (world_entity, "classname", "worldspawn"); + world_entity->eclass = Eclass_ForName ("worldspawn", true); + + camera.angles[YAW] = 0; + VectorCopy (vec3_origin, camera.origin); + camera.origin[2] = 48; + VectorCopy (vec3_origin, g_qeglobals.d_xy.origin); + + Map_RestoreBetween (); + + Sys_UpdateWindows (W_ALL); + modified = false; +} + + +/* +=========================================================== + + REGION + +=========================================================== +*/ + +qboolean region_active; +vec3_t region_mins = {-4096, -4096, -4096}; +vec3_t region_maxs = {4096, 4096, 4096}; + +brush_t *region_sides[4]; + +/* +=========== +AddRegionBrushes + +a regioned map will have temp walls put up at the region boundary +=========== +*/ +void AddRegionBrushes (void) +{ + vec3_t mins, maxs; + int i; + texdef_t td; + + if (!region_active) + return; + + memset (&td, 0, sizeof(td)); + strcpy (td.name, "REGION"); + + mins[0] = region_mins[0] - 16; + maxs[0] = region_mins[0] + 1; + mins[1] = region_mins[1] - 16; + maxs[1] = region_maxs[1] + 16; + mins[2] = -2048; + maxs[2] = 2048; + region_sides[0] = Brush_Create (mins, maxs, &td); + + mins[0] = region_maxs[0] - 1; + maxs[0] = region_maxs[0] + 16; + region_sides[1] = Brush_Create (mins, maxs, &td); + + mins[0] = region_mins[0] - 16; + maxs[0] = region_maxs[0] + 16; + mins[1] = region_mins[1] - 16; + maxs[1] = region_mins[1] + 1; + region_sides[2] = Brush_Create (mins, maxs, &td); + + mins[1] = region_maxs[1] - 1; + maxs[1] = region_maxs[1] + 16; + region_sides[3] = Brush_Create (mins, maxs, &td); + + for (i=0 ; i<4 ; i++) + { + Brush_AddToList (region_sides[i], &selected_brushes); + Entity_LinkBrush (world_entity, region_sides[i]); + Brush_Build( region_sides[i] ); + } +} + +void RemoveRegionBrushes (void) +{ + int i; + + if (!region_active) + return; + for (i=0 ; i<4 ; i++) + Brush_Free (region_sides[i]); +} + + +qboolean Map_IsBrushFiltered (brush_t *b) +{ + int i; + + for (i=0 ; i<3 ; i++) + { + if (b->mins[i] > region_maxs[i]) + return true; + if (b->maxs[i] < region_mins[i]) + return true; + } + return false; +} + +/* +=========== +Map_RegionOff + +Other filtering options may still be on +=========== +*/ +void Map_RegionOff (void) +{ + brush_t *b, *next; + int i; + + region_active = false; + for (i=0 ; i<3 ; i++) + { + region_maxs[i] = 4096; + region_mins[i] = -4096; + } + + for (b=filtered_brushes.next ; b != &filtered_brushes ; b=next) + { + next = b->next; + if (Map_IsBrushFiltered (b)) + continue; // still filtered + Brush_RemoveFromList (b); + Brush_AddToList (b, &active_brushes); + } + + Sys_UpdateWindows (W_ALL); +} + +void Map_ApplyRegion (void) +{ + brush_t *b, *next; + + region_active = true; + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + if (!Map_IsBrushFiltered (b)) + continue; // still filtered + Brush_RemoveFromList (b); + Brush_AddToList (b, &filtered_brushes); + } + + Sys_UpdateWindows (W_ALL); +} + + +/* +======================== +Map_RegionSelectedBrushes +======================== +*/ +void Map_RegionSelectedBrushes (void) +{ + Map_RegionOff (); + + region_active = true; + Select_GetBounds (region_mins, region_maxs); + + // move the entire active_brushes list to filtered_brushes + filtered_brushes.next = active_brushes.next; + filtered_brushes.prev = active_brushes.prev; + filtered_brushes.next->prev = &filtered_brushes; + filtered_brushes.prev->next = &filtered_brushes; + + // move the entire selected_brushes list to active_brushes + active_brushes.next = selected_brushes.next; + active_brushes.prev = selected_brushes.prev; + active_brushes.next->prev = &active_brushes; + active_brushes.prev->next = &active_brushes; + + // clear selected_brushes + selected_brushes.next = selected_brushes.prev = &selected_brushes; + + Sys_UpdateWindows (W_ALL); +} + + +/* +=========== +Map_RegionXY +=========== +*/ +void Map_RegionXY (void) +{ + Map_RegionOff (); + + region_mins[0] = g_qeglobals.d_xy.origin[0] - 0.5*g_qeglobals.d_xy.width/g_qeglobals.d_xy.scale; + region_maxs[0] = g_qeglobals.d_xy.origin[0] + 0.5*g_qeglobals.d_xy.width/g_qeglobals.d_xy.scale; + region_mins[1] = g_qeglobals.d_xy.origin[1] - 0.5*g_qeglobals.d_xy.height/g_qeglobals.d_xy.scale; + region_maxs[1] = g_qeglobals.d_xy.origin[1] + 0.5*g_qeglobals.d_xy.height/g_qeglobals.d_xy.scale; + region_mins[2] = -4096; + region_maxs[2] = 4096; + + Map_ApplyRegion (); +} + +/* +=========== +Map_RegionTallBrush +=========== +*/ +void Map_RegionTallBrush (void) +{ + brush_t *b; + + if (!QE_SingleBrush ()) + return; + + b = selected_brushes.next; + + Map_RegionOff (); + + VectorCopy (b->mins, region_mins); + VectorCopy (b->maxs, region_maxs); + region_mins[2] = -4096; + region_maxs[2] = 4096; + + Select_Delete (); + Map_ApplyRegion (); +} +/* +=========== +Map_RegionBrush +=========== +*/ +void Map_RegionBrush (void) +{ + brush_t *b; + + if (!QE_SingleBrush ()) + return; + + b = selected_brushes.next; + + Map_RegionOff (); + + VectorCopy (b->mins, region_mins); + VectorCopy (b->maxs, region_maxs); + + Select_Delete (); + Map_ApplyRegion (); +} + diff --git a/tools/quake2/extra/qe4/map.h b/tools/quake2/extra/qe4/map.h new file mode 100644 index 00000000..58d9ed75 --- /dev/null +++ b/tools/quake2/extra/qe4/map.h @@ -0,0 +1,53 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// map.h -- the state of the current world that all views are displaying + +extern char currentmap[1024]; + +// head/tail of doubly linked lists +extern brush_t active_brushes; // brushes currently being displayed +extern brush_t selected_brushes; // highlighted +extern face_t *selected_face; +extern brush_t *selected_face_brush; +extern brush_t filtered_brushes; // brushes that have been filtered or regioned + +extern entity_t entities; +extern entity_t *world_entity; // the world entity is NOT included in + // the entities chain + +extern qboolean modified; // for quit confirmations + +extern vec3_t region_mins, region_maxs; +extern qboolean region_active; + +void Map_LoadFile (char *filename); +void Map_SaveFile (char *filename, qboolean use_region); +void Map_New (void); +void Map_BuildBrushData(void); + +void Map_RegionOff (void); +void Map_RegionXY (void); +void Map_RegionTallBrush (void); +void Map_RegionBrush (void); +void Map_RegionSelectedBrushes (void); +qboolean Map_IsBrushFiltered (brush_t *b); diff --git a/tools/quake2/extra/qe4/mathlib.c b/tools/quake2/extra/qe4/mathlib.c new file mode 100644 index 00000000..d430ff70 --- /dev/null +++ b/tools/quake2/extra/qe4/mathlib.c @@ -0,0 +1,131 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// mathlib.c -- math primitives + +#include "cmdlib.h" +#include "mathlib.h" + +vec3_t vec3_origin = {0.0f,0.0f,0.0f}; + + +float VectorLength(vec3_t v) +{ + int i; + float length; + + length = 0.0f; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = (float)sqrt (length); + + return length; +} + +qboolean VectorCompare (vec3_t v1, vec3_t v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON) + return false; + + return true; +} + +vec_t Q_rint (vec_t in) +{ + return (float)floor (in + 0.5); +} + +void VectorMA (vec3_t va, float scale, vec3_t vb, vec3_t vc) +{ + vc[0] = va[0] + scale*vb[0]; + vc[1] = va[1] + scale*vb[1]; + vc[2] = va[2] + scale*vb[2]; +} + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]-vb[0]; + out[1] = va[1]-vb[1]; + out[2] = va[2]-vb[2]; +} + +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]+vb[0]; + out[1] = va[1]+vb[1]; + out[2] = va[2]+vb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +vec_t VectorNormalize (vec3_t v) +{ + int i; + float length; + + length = 0.0f; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = (float)sqrt (length); + if (length == 0) + return (vec_t)0; + + for (i=0 ; i< 3 ; i++) + v[i] /= length; + + return length; +} + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void VectorScale (vec3_t v, vec_t scale, vec3_t out) +{ + out[0] = v[0] * scale; + out[1] = v[1] * scale; + out[2] = v[2] * scale; +} + diff --git a/tools/quake2/extra/qe4/mathlib.h b/tools/quake2/extra/qe4/mathlib.h new file mode 100644 index 00000000..2569bed5 --- /dev/null +++ b/tools/quake2/extra/qe4/mathlib.h @@ -0,0 +1,66 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#ifndef __MATHLIB__ +#define __MATHLIB__ + +// mathlib.h + +#include + +typedef float vec_t; +typedef vec_t vec3_t[3]; + +#define SIDE_FRONT 0 +#define SIDE_ON 2 +#define SIDE_BACK 1 +#define SIDE_CROSS -2 + +#define Q_PI 3.14159265358979323846 + +extern vec3_t vec3_origin; + +#define EQUAL_EPSILON 0.001 + +qboolean VectorCompare (vec3_t v1, vec3_t v2); + +#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) +#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];} +#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];} +#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];} + +vec_t Q_rint (vec_t in); +vec_t _DotProduct (vec3_t v1, vec3_t v2); +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); +void _VectorCopy (vec3_t in, vec3_t out); + +float VectorLength(vec3_t v); + +void VectorMA (vec3_t va, float scale, vec3_t vb, vec3_t vc); + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); +vec_t VectorNormalize (vec3_t v); +void VectorInverse (vec3_t v); +void VectorScale (vec3_t v, vec_t scale, vec3_t out); + +#endif diff --git a/tools/quake2/extra/qe4/mru.c b/tools/quake2/extra/qe4/mru.c new file mode 100644 index 00000000..84a5a3eb --- /dev/null +++ b/tools/quake2/extra/qe4/mru.c @@ -0,0 +1,671 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +//************************************************************* +// File name: mru.c +// +// Description: +// +// Routines for MRU support +// +// Development Team: +// +// Gilles Vollant (100144.2636@compuserve.com) +// +//************************************************************* + +#include +#include +#include + +#include "mru.h" +// CreateMruMenu : MRUMENU constructor +// wNbLruShowInit : nb of item showed in menu +// wNbLruMenuInit : nb of item stored in memory +// wMaxSizeLruItemInit : size max. of filename + + +//************************************************************* +// +// CreateMruMenu() +// +// Purpose: +// +// Allocate and Initialize an MRU and return a pointer on it +// +// +// Parameters: +// +// WORD wNbLruShowInit - Maximum number of item displayed on menu +// WORD wNbLruMenuInit - Maximum number of item stored in memory +// WORD wMaxSizeLruItemInit - Maximum size of an item (ie size of pathname) +// WORD wIdMruInit - ID of the first item in the menu (default:IDMRU) +// +// +// Return: (LPMRUMENU) +// +// Pointer on a MRUMENU structure, used by other function +// +// +// Comments: +// wNbLruShowInit <= wNbLruMenuInit +// +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* + +LPMRUMENU CreateMruMenu (WORD wNbLruShowInit, + WORD wNbLruMenuInit,WORD wMaxSizeLruItemInit,WORD wIdMruInit) +{ +LPMRUMENU lpMruMenu; + lpMruMenu = (LPMRUMENU)GlobalAllocPtr(GHND,sizeof(MRUMENU)); + + lpMruMenu->wNbItemFill = 0; + lpMruMenu->wNbLruMenu = wNbLruMenuInit; + lpMruMenu->wNbLruShow = wNbLruShowInit; + lpMruMenu->wIdMru = wIdMruInit; + lpMruMenu->wMaxSizeLruItem = wMaxSizeLruItemInit; + lpMruMenu->lpMRU = (LPSTR)GlobalAllocPtr(GHND, + lpMruMenu->wNbLruMenu*(UINT)lpMruMenu->wMaxSizeLruItem); + if (lpMruMenu->lpMRU == NULL) + { + GlobalFreePtr(lpMruMenu); + lpMruMenu = NULL; + } + return lpMruMenu; +} + +//************************************************************* +// +// CreateMruMenuDefault() +// +// Purpose: +// +// Allocate and Initialize an MRU and return a pointer on it +// Use default parameter +// +// +// Parameters: +// +// +// Return: (LPMRUMENU) +// +// Pointer on a MRUMENU structure, used by other function +// +// +// Comments: +// +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* + +LPMRUMENU CreateMruMenuDefault() +{ + return CreateMruMenu (NBMRUMENUSHOW,NBMRUMENU,MAXSIZEMRUITEM,IDMRU); +} + + +//************************************************************* +// +// DeleteMruMenu() +// +// Purpose: +// Destructor : +// Clean and free a MRUMENU structure +// +// Parameters: +// +// LPMRUMENU lpMruMenu - pointer on MRUMENU, allocated +// by CreateMruMenu() or CreateMruMenuDefault() +// +// +// Return: void +// +// +// Comments: +// +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +void DeleteMruMenu(LPMRUMENU lpMruMenu) +{ + GlobalFreePtr(lpMruMenu->lpMRU); + GlobalFreePtr(lpMruMenu); +} + +//************************************************************* +// +// SetNbLruShow() +// +// Purpose: +// Change the maximum number of item displayed on menu +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// WORD wNbLruShowInit - Maximum number of item displayed on menu +// +// +// Return: void +// +// +// Comments: +// +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +void SetNbLruShow (LPMRUMENU lpMruMenu,WORD wNbLruShowInit) +{ + lpMruMenu->wNbLruShow = min(wNbLruShowInit,lpMruMenu->wNbLruMenu); +} + +//************************************************************* +// +// SetMenuItem() +// +// Purpose: +// Set the filename of an item +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// WORD wItem - Number of Item to set, zero based +// LPSTR lpItem - String, contain the filename of the item +// +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// used when load .INI or reg database +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL SetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,LPSTR lpItem) +{ + if (wItem >= NBMRUMENU) + return FALSE; + _fstrncpy((lpMruMenu->lpMRU) + + ((lpMruMenu->wMaxSizeLruItem) * (UINT)wItem), + lpItem,lpMruMenu->wMaxSizeLruItem-1); + lpMruMenu->wNbItemFill = max(lpMruMenu->wNbItemFill,wItem+1); + return TRUE; +} + +//************************************************************* +// +// GetMenuItem() +// +// Purpose: +// Get the filename of an item +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// WORD wItem - Number of Item to set, zero based +// BOOL fIDMBased - TRUE : wItem is based on ID menu item +// FALSE : wItem is zero-based +// LPSTR lpItem - String where the filename of the item will be +// stored by GetMenuItem() +// UINT uiSize - Size of the lpItem buffer +// +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// Used for saving in .INI or reg database, or when user select +// an MRU in File menu +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL GetMenuItem (LPMRUMENU lpMruMenu,WORD wItem, + BOOL fIDMBased,LPSTR lpItem,UINT uiSize) +{ + if (fIDMBased) + wItem -= (lpMruMenu->wIdMru + 1); + if (wItem >= lpMruMenu->wNbItemFill) + return FALSE; + _fstrncpy(lpItem,(lpMruMenu->lpMRU) + + ((lpMruMenu->wMaxSizeLruItem) * (UINT)(wItem)),uiSize); + *(lpItem+uiSize-1) = '\0'; + return TRUE; +} + +//************************************************************* +// +// AddNewItem() +// +// Purpose: +// Add an item at the begin of the list +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// LPSTR lpItem - String contain the filename to add +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// Used when used open a file (using File Open common +// dialog, Drag and drop or MRU) +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +void AddNewItem (LPMRUMENU lpMruMenu,LPSTR lpItem) +{ +WORD i,j; + for (i=0;iwNbItemFill;i++) + if (lstrcmpi(lpItem,(lpMruMenu->lpMRU) + + ((lpMruMenu->wMaxSizeLruItem) * (UINT)i)) == 0) + { + // Shift the other items + for (j=i;j>0;j--) + lstrcpy((lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)j), + (lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)(j-1))); + _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1); + return ; + } + lpMruMenu->wNbItemFill = min(lpMruMenu->wNbItemFill+1,lpMruMenu->wNbLruMenu); + for (i=lpMruMenu->wNbItemFill-1;i>0;i--) + lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i), + lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i-1))); + _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1); +} + +//************************************************************* +// +// DelMenuItem() +// +// Purpose: +// Delete an item +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// WORD wItem - Number of Item to set, zero based +// BOOL fIDMBased - TRUE : wItem is based on ID menu item +// FALSE : wItem is zero-based +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// Used when used open a file, using MRU, and when an error +// occured (by example, when file was deleted) +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL DelMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased) +{ +WORD i; + if (fIDMBased) + wItem -= (lpMruMenu->wIdMru + 1); + if (lpMruMenu->wNbItemFill <= wItem) + return FALSE; + lpMruMenu->wNbItemFill--; + for (i=wItem;iwNbItemFill;i++) + lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i), + lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i+1))); + return TRUE; +} + +//************************************************************* +// +// PlaceMenuMRUItem() +// +// Purpose: +// Add MRU at the end of a menu +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// HMENU hMenu - Handle of menu where MRU must be added +// UINT uiItem - Item of menu entry where MRU must be added +// +// Return: void +// +// +// Comments: +// Used MRU is modified, for refresh the File menu +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem) +{ +int i; +WORD wNbShow; + if (hMenu == NULL) + return; + // remove old MRU in menu + for (i=0;i<=(int)(lpMruMenu->wNbLruMenu);i++) + RemoveMenu(hMenu,i+lpMruMenu->wIdMru,MF_BYCOMMAND); + + if (lpMruMenu->wNbItemFill == 0) + return; + + // If they are item, insert a separator before the files + InsertMenu(hMenu,uiItem,MF_SEPARATOR,lpMruMenu->wIdMru,NULL); + + wNbShow = min(lpMruMenu->wNbItemFill,lpMruMenu->wNbLruShow); + for (i=(int)wNbShow-1;i>=0;i--) + { + LPSTR lpTxt; + if (lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20)) + { + wsprintf(lpTxt,"&%lu %s", + (DWORD)(i+1),lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem*(UINT)i)); + InsertMenu(hMenu,(((WORD)i)!=(wNbShow-1)) ? (lpMruMenu->wIdMru+i+2) : lpMruMenu->wIdMru, + MF_STRING,lpMruMenu->wIdMru+i+1,lpTxt); + GlobalFreePtr(lpTxt); + } + } + +} + +/////////////////////////////////////////// + + + +//************************************************************* +// +// SaveMruInIni() +// +// Purpose: +// Save MRU in a private .INI +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// LPSTR lpszSection - Points to a null-terminated string containing +// the name of the section +// LPSTR lpszFile - Points to a null-terminated string that names +// the initialization file. +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// See WritePrivateProfileString API for more info on lpszSection and lpszFile +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL SaveMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile) +{ +LPSTR lpTxt; +WORD i; + + lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20); + if (lpTxt == NULL) + return FALSE; + + for (i=0;iwNbLruMenu;i++) + { + char szEntry[16]; + wsprintf(szEntry,"File%lu",(DWORD)i+1); + if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10)) + *lpTxt = '\0'; + WritePrivateProfileString(lpszSection,szEntry,lpTxt,lpszFile); + } + GlobalFreePtr(lpTxt); + WritePrivateProfileString(NULL,NULL,NULL,lpszFile); // flush cache + return TRUE; +} + + +//************************************************************* +// +// LoadMruInIni() +// +// Purpose: +// Load MRU from a private .INI +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// LPSTR lpszSection - Points to a null-terminated string containing +// the name of the section +// LPSTR lpszFile - Points to a null-terminated string that names +// the initialization file. +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// See GetPrivateProfileString API for more info on lpszSection and lpszFile +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL LoadMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile) +{ +LPSTR lpTxt; +WORD i; + lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20); + if (lpTxt == NULL) + return FALSE; + + for (i=0;iwNbLruMenu;i++) + { + char szEntry[16]; + + wsprintf(szEntry,"File%lu",(DWORD)i+1); + GetPrivateProfileString(lpszSection,szEntry,"",lpTxt, + lpMruMenu->wMaxSizeLruItem + 10,lpszFile); + if (*lpTxt == '\0') + break; + SetMenuItem(lpMruMenu,i,lpTxt); + } + GlobalFreePtr(lpTxt); + return TRUE; +} + +#ifdef WIN32 + +BOOL IsWin395OrHigher(void) +{ + WORD wVer; + + wVer = LOWORD(GetVersion()); + wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer); + + return (wVer >= 0x035F); // 5F = 95 dec +} + + +//************************************************************* +// +// SaveMruInReg() +// +// Purpose: +// Save MRU in the registry +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// LPSTR lpszKey - Points to a null-terminated string +// specifying the name of a key that +// this function opens or creates. +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// Win32 function designed for Windows NT and Windows 95 +// See RegCreateKeyEx API for more info on lpszKey +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL SaveMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey) +{ +LPSTR lpTxt; +WORD i; +HKEY hCurKey; +DWORD dwDisp; + + lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20); + if (lpTxt == NULL) + return FALSE; + + RegCreateKeyEx(HKEY_CURRENT_USER,lpszKey,0,NULL, + REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hCurKey,&dwDisp); + + for (i=0;iwNbLruMenu;i++) + { + char szEntry[16]; + wsprintf(szEntry,"File%lu",(DWORD)i+1); + if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10)) + *lpTxt = '\0'; + RegSetValueEx(hCurKey,szEntry,0,REG_SZ,lpTxt,lstrlen(lpTxt)); + } + RegCloseKey(hCurKey); + GlobalFreePtr(lpTxt); + return TRUE; +} + +//************************************************************* +// +// LoadMruInReg() +// +// Purpose: +// Load MRU from the registry +// +// Parameters: +// LPMRUMENU lpMruMenu - pointer on MRUMENU +// LPSTR lpszKey - Points to a null-terminated string +// specifying the name of a key that +// this function opens or creates. +// +// Return: (BOOL) +// TRUE - Function run successfully +// FALSE - Function don't run successfully +// +// +// Comments: +// Win32 function designed for Windows NT and Windows 95 +// See RegOpenKeyEx API for more info on lpszKey +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +BOOL LoadMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey) +{ +LPSTR lpTxt; +WORD i; +HKEY hCurKey; +DWORD dwType; + lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20); + if (lpTxt == NULL) + return FALSE; + + RegOpenKeyEx(HKEY_CURRENT_USER,lpszKey,0,KEY_READ,&hCurKey); + + + for (i=0;iwNbLruMenu;i++) + { + char szEntry[16]; + DWORD dwSizeBuf; + wsprintf(szEntry,"File%lu",(DWORD)i+1); + *lpTxt = '\0'; + dwSizeBuf = lpMruMenu->wMaxSizeLruItem + 10; + RegQueryValueEx(hCurKey,szEntry,NULL,&dwType,(LPBYTE)lpTxt,&dwSizeBuf); + *(lpTxt+dwSizeBuf)='\0'; + if (*lpTxt == '\0') + break; + SetMenuItem(lpMruMenu,i,lpTxt); + } + RegCloseKey(hCurKey); + GlobalFreePtr(lpTxt); + return TRUE; +} + + +//************************************************************* +// +// GetWin32Kind() +// +// Purpose: +// Get the Win32 platform +// +// Parameters: +// +// Return: (WIN32KIND) +// WINNT - Run under Windows NT +// WIN32S - Run under Windows 3.1x + Win32s +// WIN95ORGREATHER - Run under Windows 95 +// +// +// Comments: +// Win32 function designed for Windows NT and Windows 95 +// See RegOpenKeyEx API for more info on lpszKey +// +// History: Date Author Comment +// 09/24/94 G. Vollant Created +// +//************************************************************* +WIN32KIND GetWin32Kind() +{ +BOOL IsWin395OrHigher(void); + + WORD wVer; + + if ((GetVersion() & 0x80000000) == 0) + return WINNT; + wVer = LOWORD(GetVersion()); + wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer); + + if (wVer >= 0x035F) + return WIN95ORGREATHER; + else + return WIN32S; +} +#endif diff --git a/tools/quake2/extra/qe4/mru.h b/tools/quake2/extra/qe4/mru.h new file mode 100644 index 00000000..b78b986c --- /dev/null +++ b/tools/quake2/extra/qe4/mru.h @@ -0,0 +1,101 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +//************************************************************* +// File name: mru.h +// +// Description: +// +// Header for MRU support +// +// Development Team: +// +// Gilles Vollant (100144.2636@compuserve.com) +// +//************************************************************* + +#ifndef __MRU_H__ +#define __MRU_H__ + +#define NBMRUMENUSHOW 6 // Default number of MRU showed in the menu File +#define NBMRUMENU 9 // Default number of MRU stored +#define IDMRU 8000 // Default First ID of MRU +#ifdef OFS_MAXPATHNAME +#define MAXSIZEMRUITEM OFS_MAXPATHNAME +#else +#define MAXSIZEMRUITEM 128 // Default max size of an entry +#endif + +typedef struct +{ +WORD wNbItemFill; +WORD wNbLruShow; +WORD wNbLruMenu; +WORD wMaxSizeLruItem; +WORD wIdMru; +LPSTR lpMRU; +} MRUMENU; + +typedef MRUMENU FAR * LPMRUMENU; + +#ifdef __cplusplus +LPMRUMENU CreateMruMenu (WORD wNbLruShowInit=NBMRUMENUSHOW, + WORD wNbLruMenuInit=NBMRUMENU, + WORD wMaxSizeLruItemInit=MAXSIZEMRUITEM, + WORD wIdMruInit=IDMRU); +#else +LPMRUMENU CreateMruMenu (WORD wNbLruShowInit, + WORD wNbLruMenuInit, + WORD wMaxSizeLruItemInit, + WORD wIdMruInit); +#endif + +LPMRUMENU CreateMruMenuDefault(); +void DeleteMruMenu (LPMRUMENU lpMruMenu); + +void SetNbLruShow (LPMRUMENU lpMruMenu,WORD wNbLruShowInit); +BOOL SetMenuItem (LPMRUMENU lpMruMenu,WORD wItem, + LPSTR lpItem); +BOOL GetMenuItem (LPMRUMENU lpMruMenu,WORD wItem, + BOOL fIDMBased,LPSTR lpItem,UINT uiSize); +BOOL DelMenuItem (LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased); +void AddNewItem (LPMRUMENU lpMruMenu,LPSTR lpItem); +void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem); + +BOOL SaveMruInIni (LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile); +BOOL LoadMruInIni (LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile); +#ifdef WIN32 +BOOL SaveMruInReg (LPMRUMENU lpMruMenu,LPSTR lpszKey); +BOOL LoadMruInReg (LPMRUMENU lpMruMenu,LPSTR lpszKey); + +typedef enum +{ +WIN32S, +WINNT, +WIN95ORGREATHER +} WIN32KIND; +WIN32KIND GetWin32Kind(); +#endif + + +////////////////////////////////////////////////////////////// +#endif diff --git a/tools/quake2/extra/qe4/parse.c b/tools/quake2/extra/qe4/parse.c new file mode 100644 index 00000000..8258a4ad --- /dev/null +++ b/tools/quake2/extra/qe4/parse.c @@ -0,0 +1,141 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +char token[MAXTOKEN]; +qboolean unget; +char *script_p; +int scriptline; + +void StartTokenParsing (char *data) +{ + scriptline = 1; + script_p = data; + unget = false; +} + +qboolean GetToken (qboolean crossline) +{ + char *token_p; + + if (unget) // is a token allready waiting? + return true; + +// +// skip space +// +skipspace: + while (*script_p <= 32) + { + if (!*script_p) + { + if (!crossline) + Error ("Line %i is incomplete",scriptline); + return false; + } + if (*script_p++ == '\n') + { + if (!crossline) + Error ("Line %i is incomplete",scriptline); + scriptline++; + } + } + + if (script_p[0] == '/' && script_p[1] == '/') // comment field + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script_p++ != '\n') + if (!*script_p) + { + if (!crossline) + Error ("Line %i is incomplete",scriptline); + return false; + } + goto skipspace; + } + +// +// copy token +// + token_p = token; + + if (*script_p == '"') + { + script_p++; + while ( *script_p != '"' ) + { + if (!*script_p) + Error ("EOF inside quoted token"); + *token_p++ = *script_p++; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i",scriptline); + } + script_p++; + } + else while ( *script_p > 32 ) + { + *token_p++ = *script_p++; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i",scriptline); + } + + *token_p = 0; + + return true; +} + +void UngetToken (void) +{ + unget = true; +} + + +/* +============== +TokenAvailable + +Returns true if there is another token on the line +============== +*/ +qboolean TokenAvailable (void) +{ + char *search_p; + + search_p = script_p; + + while ( *search_p <= 32) + { + if (*search_p == '\n') + return false; + if (*search_p == 0) + return false; + search_p++; + } + + if (*search_p == ';') + return false; + + return true; +} + diff --git a/tools/quake2/extra/qe4/parse.h b/tools/quake2/extra/qe4/parse.h new file mode 100644 index 00000000..0d5d3e1c --- /dev/null +++ b/tools/quake2/extra/qe4/parse.h @@ -0,0 +1,34 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// parse.h -- text file parsing routines + +#define MAXTOKEN 1024 + +extern char token[MAXTOKEN]; +extern int scriptline; + +void StartTokenParsing (char *data); +qboolean GetToken (qboolean crossline); +void UngetToken (void); +qboolean TokenAvailable (void); + diff --git a/tools/quake2/extra/qe4/points.c b/tools/quake2/extra/qe4/points.c new file mode 100644 index 00000000..deaae483 --- /dev/null +++ b/tools/quake2/extra/qe4/points.c @@ -0,0 +1,155 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + + +#define MAX_POINTFILE 8192 +static vec3_t s_pointvecs[MAX_POINTFILE]; +static int s_num_points, s_check_point; + +void Pointfile_Delete (void) +{ + char name[1024]; + + strcpy (name, currentmap); + StripExtension (name); + strcat (name, ".lin"); + + remove(name); +} + +// advance camera to next point +void Pointfile_Next (void) +{ + vec3_t dir; + + if (s_check_point >= s_num_points-2) + { + Sys_Status ("End of pointfile", 0); + return; + } + s_check_point++; + VectorCopy (s_pointvecs[s_check_point], camera.origin); + VectorCopy (s_pointvecs[s_check_point], g_qeglobals.d_xy.origin); + VectorSubtract (s_pointvecs[s_check_point+1], camera.origin, dir); + VectorNormalize (dir); + camera.angles[1] = atan2 (dir[1], dir[0])*180/3.14159; + camera.angles[0] = asin (dir[2])*180/3.14159; + + Sys_UpdateWindows (W_ALL); +} + +// advance camera to previous point +void Pointfile_Prev (void) +{ + vec3_t dir; + + if ( s_check_point == 0) + { + Sys_Status ("Start of pointfile", 0); + return; + } + s_check_point--; + VectorCopy (s_pointvecs[s_check_point], camera.origin); + VectorCopy (s_pointvecs[s_check_point], g_qeglobals.d_xy.origin); + VectorSubtract (s_pointvecs[s_check_point+1], camera.origin, dir); + VectorNormalize (dir); + camera.angles[1] = atan2 (dir[1], dir[0])*180/3.14159; + camera.angles[0] = asin (dir[2])*180/3.14159; + + Sys_UpdateWindows (W_ALL); +} + +void Pointfile_Check (void) +{ + char name[1024]; + FILE *f; + vec3_t v; + + strcpy (name, currentmap); + StripExtension (name); + strcat (name, ".lin"); + + f = fopen (name, "r"); + if (!f) + return; + + Sys_Printf ("Reading pointfile %s\n", name); + + if (!g_qeglobals.d_pointfile_display_list) + g_qeglobals.d_pointfile_display_list = glGenLists(1); + + s_num_points = 0; + glNewList (g_qeglobals.d_pointfile_display_list, GL_COMPILE); + glColor3f (1, 0, 0); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glLineWidth (4); + glBegin(GL_LINE_STRIP); + do + { + if (fscanf (f, "%f %f %f\n", &v[0], &v[1], &v[2]) != 3) + break; + if (s_num_points < MAX_POINTFILE) + { + VectorCopy (v, s_pointvecs[s_num_points]); + s_num_points++; + } + glVertex3fv (v); + } while (1); + glEnd(); + glLineWidth (1); + glEndList (); + + s_check_point = 0; + fclose (f); + Pointfile_Next (); +} + +void Pointfile_Draw( void ) +{ + int i; + + glColor3f( 1.0F, 0.0F, 0.0F ); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glLineWidth (4); + glBegin(GL_LINE_STRIP); + for ( i = 0; i < s_num_points; i++ ) + { + glVertex3fv( s_pointvecs[i] ); + } + glEnd(); + glLineWidth( 1 ); +} + +void Pointfile_Clear (void) +{ + if (!g_qeglobals.d_pointfile_display_list) + return; + + glDeleteLists (g_qeglobals.d_pointfile_display_list, 1); + g_qeglobals.d_pointfile_display_list = 0; + Sys_UpdateWindows (W_ALL); +} + diff --git a/tools/quake2/extra/qe4/q.bmp b/tools/quake2/extra/qe4/q.bmp new file mode 100644 index 0000000000000000000000000000000000000000..598971a27f28da3e04d05e2847c615a612f9fac5 GIT binary patch literal 13878 zcmbtZv9{Z|5k<~Pkpq^}_AFDU*qSGuvCPXWu0$G!B5ye zg>&zn0SHQbdVU-D4KSD)%$)&1fRz9Gx1WCwDnI`*gg=8DLH_{#A^Zt7%3rK`tVc5* zM~z_(Hq7%J=Ksv$w|{>Lp>99}2#R_F&7dWOCV*-Xm}UTtpb0dCmJo&jszD71onZt` zpc%9{ZjH794WJP;fo9MW0@yIspawL6M$iPBK?{Nmpc>SG2G9taKr?6w0e@ksK@DgC zji3oMgO<<)gc)iO{|%rKG=XN&VyV?N+6FX$M$iPBL5ro`)My*f02)CPXa+4dB}0w2 z0S%xLG=XN&V$(I&XdBP~8bK3i1}!#~Q;oI(4WJP;fo9NR(>&K`8_)n6K@(^OEn0$R zsnIr|0W^Xp&v<+wgji3oMgBIJaV~w@}4WJP;fo9NRTY0L{HlP7Cf+o-mT5Oxo zHQEL=fJV?1e*5qD@Gsbn@E5{&{e|z}$${{XB34h!={2nxus)^g6u_Z(x}ZLtF09TJ zl3^X9%&iAg+P|R)NcMSL78wkEvLrxA6^jczl(Pbm;s04FDNjSWi}&cL6lp4$e(H+T zR5^amC&!Z$%aX*b8f6JzDQQ^HGmF^Nvp8IXWxNrNc0kffvIq4BlhKl8tvvv{O@02U*oszW=i%qZ3nxKw$_R zhhnR460QaZuKu?C>a^ra>qB+D3&34EG-Cipw5!fgJr+ViS9)`l2U%fr&&Jql2j9zy zPyeW$lo|n9h_rH>?4&CtC2s>uNlXWT&|GiG4vl4IH0aq&n4U)UY4#MZ1lr?~eTWD8 z@^lC(mlW_%Pn=+sZn$v68B1)wgvfHw`|Gm4k0`W*R|B*NEHC0{kFm=Rt8?Ch3Y7!P za^Ej?vyD!nObe>G%RBekd1V&vSD4s7o5nL651` z^k+M!rWkBe60fr^hjO`a@)1p$e|GVV0lI)o8_QpDS#V~doMA_hjLhc&xpN}WD#p^) zTlvlHDJ)Bv?g?spO!XRrGKUW06|Z1d;d2f{&gU4~bOAF@Bc;m+T}=AQQ2&A(2mx3~ zWdILYG~X?*U~|U9pSB+}PO~js&H)QMS%6#6*Il|hkhN=E>ZjJ@DZ0St26Pl#P^_$d z;y9|!3Uw9^Z|SwT&)?Nx`hhRU4$VjiW6+Lh9e?tnwCMN%(DIFCGl0_{&)GwQm0$C2 zB1T|voE)jqAz>nVd_B)&ur{{s_2OrL^KwLJSZABg2t#qQY0k6m?)U98^2jQKe} zxP%Nb+4VOd3q+28pfbd8J%sqJ`uz2Zw;xOeUa&p_7rQcc*oxh;!#5f63B*v;(Q$yA zhkK7FuqK~u_>OL1_8kug3dn7N8}KL2cAlBr?rQPg|ZUoNyKcRc=cOLt2M^ zYd==EkJtr$%2h3Po%iwj$$+%{cn{J2qv6>{W(cIhS9pHw3o8lHD*x@2gm2ZiD}NPI z0NiVud?c4-ph8fTr&6#ho1^?zVKsD#mrbkbU!B$WB=c}{&?)t3J_86efsp^MgZ|8_>5vc zz21)iTb|dAerko`YQ!CJF6Upf9YTw}a_eq4*xCZH)$y+|I2D|W^937VgTHoGxjyl@ zQP+}q;J0`jiJFySV>}$%TlCMd&c@RivegDRoEHKQc_kH{_S`@_aARx z(?P4XCMbUa&|2^zH=PpbPD-pqv5D@2(qJxV&k#w z7#3zY9Q01%?h6wjv{iT)w9h&9DM9ifeh#0oYk-#?J9`F!3?&~w?!j$Fg>z>C|KaLS zUTJ&e&TFd{D}aaa7fdGyC<32p{Wel*<_O8c8T4lX%$e8Es~Zp}OrOFskknh-GB9Bf zC*UH+T?Cy^i?zsGCagFCtCu|vxgGj-@6%)h<^uX$Rn`er-*;b*366NWb`XGV0gHql zUM`mk-xj+uDh!W>8RfW4#=5;;HFq8Ylhw)V3xqAe5MC&*zz!--o;zFFu*!@Kke~#8 zs4CtW?4u}1v;buUIRCIQcXL}|__`w#Ib7wB+-g8haJaMEBVr?%VAbNt;SyXTD$t{+ zLek>m;hW4(u?e@~dGgT}@0CtRhgZr90GJ2>H;Q^Yt|gM^10S-D#Tu`$%(P(L7_PzH z@I`h+EM73(X*MwTwhqsqKRkS$TdcrvTy~TzVN0R)Kk#dSi-AAKvrsS@elnNqfA0V< zQC*}b7A55Drm>FAy9c2($>WoVKaUchT?Bz_bo6oZc?myax<54tehr{hz!?i`xS;>+ z$e<|W4^;Rh%_d~<63m;=|3?Bxp!~d49oqh-?I-^lCuCHTSQzR-dBplbY#M-*v*O$F zmGeLLS6nVTMXm&Ci5qM-Bp?-i-@kJ}H4t*=S>c`hO8%!?e(TG=El+geg|+^YmLF6e z3)P>o|JV{x_Rd&%+5>6iZi~;!?c*ma2k<}~FyUG}9u>bC2#JEMiKkF<1LkQtwCe*< z7(R@0fhWnS;jBp7I@lJN-<}Gp@VdkP%6G44g%A$T)>%Qb+v96kDNE_;GZJ1skWuoq z;1%ns9vI03@p3eBjP;KPaKg#0CIVk$YV+t9Q1}L?l2DSJqY)Ep>(Yep=%;YJ;04Tq zEDj6UH$@SB@_X0DV>*BC1K?P=roADM5l4X+{7i$`xc69OKx>PL-E5gg+_ks>?j-1P zkPXy$^KG^1ve#pkw!f<}P#e!eLS&ELw-UbpmL++vGv1<#l^^ErfBth0N#HYyl{L>iCOaL4q9c!0J3(z^8`r# z&}w`73<;KS)LS5GOOG~ml@#3N@uxRx(+Gc;&k~{V#YIRCq`7x!p1xET5Zg|vARjqd zR>-8GNvOU$NfIi4_{o%6ThTZK2L=CJXl`Grcea2p9#PDp+T`b*%L$_!kAUnj2(LMk zWBvdw2H$$1oQqowFcA89r}}DfLR5 z24?OY&3~xmUx8A(X;el}0{rshUKJrL{F9kOo7w|W#Chz?%=S}YFK)r{e+uA4dRBx? z0VoXXn~L=hm(3EStaiofJ!P}~fSlMNw~jbbFW0Lq3k+7+7Jk;0#;@@9ATneNdlP(~ sdU__1BP3I{%-_Up49%NYpi4Cq;5GJQQHIpp^rL3MPr!;m!xYK?06|>+H~;_u literal 0 HcmV?d00001 diff --git a/tools/quake2/extra/qe4/qe3.c b/tools/quake2/extra/qe4/qe3.c new file mode 100644 index 00000000..153640d1 --- /dev/null +++ b/tools/quake2/extra/qe4/qe3.c @@ -0,0 +1,451 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +QEGlobals_t g_qeglobals; + +void QE_CheckOpenGLForErrors(void) +{ + int i; + + while ( ( i = glGetError() ) != GL_NO_ERROR ) + { + char buffer[100]; + + sprintf( buffer, "OpenGL Error: %s", gluErrorString( i ) ); + + MessageBox( g_qeglobals.d_hwndMain, buffer , "QuakeEd Error", MB_OK | MB_ICONEXCLAMATION ); + exit( 1 ); + } +} + + +char *ExpandReletivePath (char *p) +{ + static char temp[1024]; + char *base; + + if (!p || !p[0]) + return NULL; + if (p[0] == '/' || p[0] == '\\') + return p; + + base = ValueForKey(g_qeglobals.d_project_entity, "basepath"); + sprintf (temp, "%s/%s", base, p); + return temp; +} + + + +void *qmalloc (int size) +{ + void *b; + b = malloc(size); + memset (b, 0, size); + return b; +} + +char *copystring (char *s) +{ + char *b; + b = malloc(strlen(s)+1); + strcpy (b,s); + return b; +} + +/* +=============== +QE_CheckAutoSave + +If five minutes have passed since making a change +and the map hasn't been saved, save it out. +=============== +*/ +void QE_CheckAutoSave( void ) +{ + static clock_t s_start; + clock_t now; + + now = clock(); + + if ( modified != 1 || !s_start) + { + s_start = now; + return; + } + + if ( now - s_start > ( CLOCKS_PER_SEC * 60 * QE_AUTOSAVE_INTERVAL ) ) + { + Sys_Printf ("Autosaving...\n"); + Sys_Status ("Autosaving...", 0 ); + + Map_SaveFile (ValueForKey(g_qeglobals.d_project_entity, "autosave"), false); + + Sys_Status ("Autosaving...Saved.", 0 ); + modified = 2; + s_start = now; + } +} + + + +/* +=========== +QE_LoadProject +=========== +*/ +qboolean QE_LoadProject (char *projectfile) +{ + char *data; + + Sys_Printf ("QE_LoadProject (%s)\n", projectfile); + + if ( LoadFileNoCrash (projectfile, (void *)&data) == -1) + return false; + StartTokenParsing (data); + g_qeglobals.d_project_entity = Entity_Parse (true); + if (!g_qeglobals.d_project_entity) + Error ("Couldn't parse %s", projectfile); + free (data); + + Eclass_InitForSourceDirectory (ValueForKey (g_qeglobals.d_project_entity, "entitypath")); + + FillClassList (); // list in entity window + + Map_New (); + + FillTextureMenu (); + FillBSPMenu (); + + return true; +} + +/* +=========== +QE_KeyDown +=========== +*/ +#define SPEED_MOVE 32 +#define SPEED_TURN 22.5 + +qboolean QE_KeyDown (int key) +{ + switch (key) + { + case 'K': + PostMessage( g_qeglobals.d_hwndMain, WM_COMMAND, ID_MISC_SELECTENTITYCOLOR, 0 ); + break; + + case VK_UP: + VectorMA (camera.origin, SPEED_MOVE, camera.forward, camera.origin); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case VK_DOWN: + VectorMA (camera.origin, -SPEED_MOVE, camera.forward, camera.origin); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case VK_LEFT: + camera.angles[1] += SPEED_TURN; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case VK_RIGHT: + camera.angles[1] -= SPEED_TURN; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case 'D': + camera.origin[2] += SPEED_MOVE; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z_OVERLAY); + break; + case 'C': + camera.origin[2] -= SPEED_MOVE; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z_OVERLAY); + break; + case 'A': + camera.angles[0] += SPEED_TURN; + if (camera.angles[0] > 85) + camera.angles[0] = 85; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case 'Z': + camera.angles[0] -= SPEED_TURN; + if (camera.angles[0] < -85) + camera.angles[0] = -85; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case VK_COMMA: + VectorMA (camera.origin, -SPEED_MOVE, camera.right, camera.origin); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + case VK_PERIOD: + VectorMA (camera.origin, SPEED_MOVE, camera.right, camera.origin); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + + case '0': + g_qeglobals.d_showgrid = !g_qeglobals.d_showgrid; + PostMessage( g_qeglobals.d_hwndXY, WM_PAINT, 0, 0 ); + break; + case '1': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_1, 0); + break; + case '2': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_2, 0); + break; + case '3': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_4, 0); + break; + case '4': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_8, 0); + break; + case '5': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_16, 0); + break; + case '6': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_32, 0); + break; + case '7': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_64, 0); + break; + + case 'E': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DRAGEDGES, 0); + break; + case 'V': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DRAGVERTECIES, 0); + break; + + case 'N': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ENTITY, 0); + break; + case 'O': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_CONSOLE, 0); + break; + case 'T': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_TEXTURE, 0); + break; + case 'S': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_TEXTURES_INSPECTOR, 0); + break; + + case ' ': + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_CLONE, 0); + break; + + case VK_BACK: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DELETE, 0); + break; + case VK_ESCAPE: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DESELECT, 0); + break; + case VK_END: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_CENTER, 0); + break; + + case VK_DELETE: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ZOOMIN, 0); + break; + case VK_INSERT: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ZOOMOUT, 0); + break; + + case VK_NEXT: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_DOWNFLOOR, 0); + break; + case VK_PRIOR: + PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_UPFLOOR, 0); + break; + + default: + return false; + + } + + return true; +} + +/* +=============== +ConnectEntities + +Sets target / targetname on the two entities selected +from the first selected to the secon +=============== +*/ +void ConnectEntities (void) +{ + entity_t *e1, *e2, *e; + char *target, *tn; + int maxtarg, targetnum; + char newtarg[32]; + + if (g_qeglobals.d_select_count != 2) + { + Sys_Status ("Must have two brushes selected.", 0); + Sys_Beep (); + return; + } + + e1 = g_qeglobals.d_select_order[0]->owner; + e2 = g_qeglobals.d_select_order[1]->owner; + + if (e1 == world_entity || e2 == world_entity) + { + Sys_Status ("Can't connect to the world.", 0); + Sys_Beep (); + return; + } + + if (e1 == e2) + { + Sys_Status ("Brushes are from same entity.", 0); + Sys_Beep (); + return; + } + + target = ValueForKey (e1, "target"); + if (target && target[0]) + strcpy (newtarg, target); + else + { + target = ValueForKey (e2, "targetname"); + if (target && target[0]) + strcpy (newtarg, target); + else + { + // make a unique target value + maxtarg = 0; + for (e=entities.next ; e != &entities ; e=e->next) + { + tn = ValueForKey (e, "targetname"); + if (tn && tn[0]) + { + targetnum = atoi(tn+1); + if (targetnum > maxtarg) + maxtarg = targetnum; + } + } + sprintf (newtarg, "t%i", maxtarg+1); + } + } + + SetKeyValue (e1, "target", newtarg); + SetKeyValue (e2, "targetname", newtarg); + Sys_UpdateWindows (W_XY | W_CAMERA); + + Select_Deselect(); + Select_Brush (g_qeglobals.d_select_order[1]); +} + +qboolean QE_SingleBrush (void) +{ + if ( (selected_brushes.next == &selected_brushes) + || (selected_brushes.next->next != &selected_brushes) ) + { + Sys_Printf ("Error: you must have a single brush selected\n"); + return false; + } + if (selected_brushes.next->owner->eclass->fixedsize) + { + Sys_Printf ("Error: you cannot manipulate fixed size entities\n"); + return false; + } + + return true; +} + +void QE_Init (void) +{ + /* + ** initialize variables + */ + g_qeglobals.d_gridsize = 8; + g_qeglobals.d_showgrid = true; + + /* + ** other stuff + */ + Texture_Init (); + Cam_Init (); + XY_Init (); + Z_Init (); +} + +void QE_ConvertDOSToUnixName( char *dst, const char *src ) +{ + while ( *src ) + { + if ( *src == '\\' ) + *dst = '/'; + else + *dst = *src; + dst++; src++; + } + *dst = 0; +} + +int g_numbrushes, g_numentities; + +void QE_CountBrushesAndUpdateStatusBar( void ) +{ + static int s_lastbrushcount, s_lastentitycount; + static qboolean s_didonce; + + entity_t *e; + brush_t *b, *next; + + g_numbrushes = 0; + g_numentities = 0; + + if ( active_brushes.next != NULL ) + { + for ( b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next) + { + next = b->next; + if (b->brush_faces ) + { + if ( !b->owner->eclass->fixedsize) + g_numbrushes++; + else + g_numentities++; + } + } + } + + if ( entities.next != NULL ) + { + for ( e = entities.next ; e != &entities && g_numentities != MAX_MAP_ENTITIES ; e = e->next) + { + g_numentities++; + } + } + + if ( ( ( g_numbrushes != s_lastbrushcount ) || ( g_numentities != s_lastentitycount ) ) || ( !s_didonce ) ) + { + Sys_UpdateStatusBar(); + + s_lastbrushcount = g_numbrushes; + s_lastentitycount = g_numentities; + s_didonce = true; + } +} + diff --git a/tools/quake2/extra/qe4/qe3.h b/tools/quake2/extra/qe4/qe3.h new file mode 100644 index 00000000..67930599 --- /dev/null +++ b/tools/quake2/extra/qe4/qe3.h @@ -0,0 +1,306 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#ifndef __QE3_H__ +#define __QE3_H__ + +// disable data conversion warnings for gl +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#include + +#include +#include +#include +#include "glingr.h" +#include +#include + +#include "cmdlib.h" +#include "mathlib.h" +#include "parse.h" +#include "lbmlib.h" + +#include +#include "afxres.h" +#include "resource.h" + +#include "qedefs.h" + +typedef struct +{ + vec3_t normal; + double dist; + int type; +} plane_t; + +#include "qfiles.h" + +#include "textures.h" +#include "brush.h" +#include "entity.h" +#include "map.h" +#include "select.h" + +#include "camera.h" +#include "xy.h" +#include "z.h" +#include "mru.h" + +typedef struct +{ + int p1, p2; + face_t *f1, *f2; +} pedge_t; + +typedef struct +{ + int iSize; + int iTexMenu; // nearest, linear, etc + float fGamma; // gamma for textures + char szProject[256]; // last project loaded + vec3_t colors[COLOR_LAST]; + qboolean show_names, + show_coordinates; + int exclude; +} SavedInfo_t; + +// +// system functions +// +void Sys_UpdateStatusBar( void ); +void Sys_UpdateWindows (int bits); +void Sys_Beep (void); +void Sys_ClearPrintf (void); +void Sys_Printf (char *text, ...); +double Sys_DoubleTime (void); +void Sys_GetCursorPos (int *x, int *y); +void Sys_SetCursorPos (int x, int y); +void Sys_SetTitle (char *text); +void Sys_BeginWait (void); +void Sys_EndWait (void); +void Sys_Status(const char *psz, int part); + +/* +** most of the QE globals are stored in this structure +*/ +typedef struct +{ + qboolean d_showgrid; + int d_gridsize; + + int d_num_entities; + + entity_t *d_project_entity; + + float d_new_brush_bottom_z, + d_new_brush_top_z; + + HINSTANCE d_hInstance; + + HGLRC d_hglrcBase; + HDC d_hdcBase; + + HWND d_hwndMain; + HWND d_hwndCamera; + HWND d_hwndEdit; + HWND d_hwndEntity; + HWND d_hwndTexture; + HWND d_hwndXY; + HWND d_hwndZ; + HWND d_hwndStatus; + + vec3_t d_points[MAX_POINTS]; + int d_numpoints; + pedge_t d_edges[MAX_EDGES]; + int d_numedges; + + int d_num_move_points; + float *d_move_points[1024]; + + qtexture_t *d_qtextures; + + texturewin_t d_texturewin; + + int d_pointfile_display_list; + + xy_t d_xy; + + LPMRUMENU d_lpMruMenu; + + SavedInfo_t d_savedinfo; + + int d_workcount; + + // connect entities uses the last two brushes selected + int d_select_count; + brush_t *d_select_order[2]; + vec3_t d_select_translate; // for dragging w/o making new display lists + select_t d_select_mode; + + int d_font_list; + + int d_parsed_brushes; + + qboolean show_blocks; +} QEGlobals_t; + +void *qmalloc (int size); +char *copystring (char *s); +char *ExpandReletivePath (char *p); + +void Pointfile_Delete (void); +void Pointfile_Check (void); +void Pointfile_Next (void); +void Pointfile_Prev (void); +void Pointfile_Clear (void); +void Pointfile_Draw( void ); +void Pointfile_Load( void ); + +// +// drag.c +// +void Drag_Begin (int x, int y, int buttons, + vec3_t xaxis, vec3_t yaxis, + vec3_t origin, vec3_t dir); +void Drag_MouseMoved (int x, int y, int buttons); +void Drag_MouseUp (void); + +// +// csg.c +// +void CSG_MakeHollow (void); +void CSG_Subtract (void); + +// +// vertsel.c +// + +void SetupVertexSelection (void); +void SelectEdgeByRay (vec3_t org, vec3_t dir); +void SelectVertexByRay (vec3_t org, vec3_t dir); + +void ConnectEntities (void); + +extern int update_bits; + +extern int screen_width; +extern int screen_height; + +extern HANDLE bsp_process; + +char *TranslateString (char *buf); + +void ProjectDialog (void); + +void FillTextureMenu (void); +void FillBSPMenu (void); + +BOOL CALLBACK Win_Dialog ( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter +); + + +// +// win_cam.c +// +void WCam_Create (HINSTANCE hInstance); + + +// +// win_xy.c +// +void WXY_Create (HINSTANCE hInstance); + +// +// win_z.c +// +void WZ_Create (HINSTANCE hInstance); + +// +// win_ent.c +// + + +// +// win_main.c +// +void Main_Create (HINSTANCE hInstance); +extern BOOL SaveWindowState(HWND hWnd, const char *pszName); +extern BOOL LoadWindowState(HWND hWnd, const char *pszName); + +extern BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize); +extern BOOL loadRegistryInfo(const char *pszName, void *pvBuf, long *plSize); + +// +// entityw.c +// +BOOL CreateEntityWindow(HINSTANCE hInstance); +void FillClassList (void); +BOOL UpdateEntitySel(eclass_t *pec); +void SetInspectorMode(int iType); +int DrawTexControls(HWND hWnd); +void SetSpawnFlags(void); +void GetSpawnFlags(void); +void SetKeyValuePairs(void); +extern void BuildGammaTable(float g); + + +// win_dlg.c + +void DoGamma(void); +void DoFind(void); +void DoRotate(void); +void DoSides(void); +void DoAbout(void); +void DoSurface(void); + +/* +** QE function declarations +*/ +void QE_CheckAutoSave( void ); +void QE_ConvertDOSToUnixName( char *dst, const char *src ); +void QE_CountBrushesAndUpdateStatusBar( void ); +void QE_CheckOpenGLForErrors(void); +void QE_ExpandBspString (char *bspaction, char *out, char *mapname); +void QE_Init (void); +qboolean QE_KeyDown (int key); +qboolean QE_LoadProject (char *projectfile); +qboolean QE_SingleBrush (void); + +/* +** QE Win32 function declarations +*/ +int QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer ); +void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC ); + +/* +** extern declarations +*/ +extern QEGlobals_t g_qeglobals; + +#endif diff --git a/tools/quake2/extra/qe4/qe4.mak b/tools/quake2/extra/qe4/qe4.mak new file mode 100644 index 00000000..9032cfa4 --- /dev/null +++ b/tools/quake2/extra/qe4/qe4.mak @@ -0,0 +1,3716 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 +# TARGTYPE "Win32 (ALPHA) Application" 0x0601 + +!IF "$(CFG)" == "" +CFG=qe3 - Win32 (ALPHA) Debug +!MESSAGE No configuration specified. Defaulting to qe3 - Win32 (ALPHA) Debug. +!ENDIF + +!IF "$(CFG)" != "qe3 - Win32 Release" && "$(CFG)" != "qe3 - Win32 Debug" &&\ + "$(CFG)" != "qe3 - Win32 (ALPHA) Debug" && "$(CFG)" !=\ + "qe3 - Win32 (ALPHA) Release" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "qe4.mak" CFG="qe3 - Win32 (ALPHA) Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "qe3 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "qe3 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "qe3 - Win32 (ALPHA) Debug" (based on "Win32 (ALPHA) Application") +!MESSAGE "qe3 - Win32 (ALPHA) Release" (based on "Win32 (ALPHA) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "qe3 - Win32 Debug" + +!IF "$(CFG)" == "qe3 - 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 "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\qe4.exe" "$(OUTDIR)\qe4.bsc" + +CLEAN : + -@erase "$(INTDIR)\brush.obj" + -@erase "$(INTDIR)\brush.sbr" + -@erase "$(INTDIR)\camera.obj" + -@erase "$(INTDIR)\camera.sbr" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\cmdlib.sbr" + -@erase "$(INTDIR)\csg.obj" + -@erase "$(INTDIR)\csg.sbr" + -@erase "$(INTDIR)\drag.obj" + -@erase "$(INTDIR)\drag.sbr" + -@erase "$(INTDIR)\eclass.obj" + -@erase "$(INTDIR)\eclass.sbr" + -@erase "$(INTDIR)\entity.obj" + -@erase "$(INTDIR)\entity.sbr" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\lbmlib.sbr" + -@erase "$(INTDIR)\map.obj" + -@erase "$(INTDIR)\map.sbr" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\mathlib.sbr" + -@erase "$(INTDIR)\mru.obj" + -@erase "$(INTDIR)\mru.sbr" + -@erase "$(INTDIR)\parse.obj" + -@erase "$(INTDIR)\parse.sbr" + -@erase "$(INTDIR)\points.obj" + -@erase "$(INTDIR)\points.sbr" + -@erase "$(INTDIR)\qe3.obj" + -@erase "$(INTDIR)\qe3.sbr" + -@erase "$(INTDIR)\select.obj" + -@erase "$(INTDIR)\select.sbr" + -@erase "$(INTDIR)\textures.obj" + -@erase "$(INTDIR)\textures.sbr" + -@erase "$(INTDIR)\vertsel.obj" + -@erase "$(INTDIR)\vertsel.sbr" + -@erase "$(INTDIR)\win_cam.obj" + -@erase "$(INTDIR)\win_cam.sbr" + -@erase "$(INTDIR)\win_dlg.obj" + -@erase "$(INTDIR)\win_dlg.sbr" + -@erase "$(INTDIR)\win_ent.obj" + -@erase "$(INTDIR)\win_ent.sbr" + -@erase "$(INTDIR)\win_main.obj" + -@erase "$(INTDIR)\win_main.sbr" + -@erase "$(INTDIR)\win_qe3.obj" + -@erase "$(INTDIR)\win_qe3.res" + -@erase "$(INTDIR)\win_qe3.sbr" + -@erase "$(INTDIR)\win_xy.obj" + -@erase "$(INTDIR)\win_xy.sbr" + -@erase "$(INTDIR)\win_z.obj" + -@erase "$(INTDIR)\win_z.sbr" + -@erase "$(INTDIR)\xy.obj" + -@erase "$(INTDIR)\xy.sbr" + -@erase "$(INTDIR)\z.obj" + -@erase "$(INTDIR)\z.sbr" + -@erase "$(OUTDIR)\qe4.bsc" + -@erase "$(OUTDIR)\qe4.exe" + -@erase "$(OUTDIR)\qe4.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /Zd /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fr /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /Zd /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fr"$(INTDIR)/" /Fp"$(INTDIR)/qe4.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\Release/ + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qe4.bsc" +BSC32_SBRS= \ + "$(INTDIR)\brush.sbr" \ + "$(INTDIR)\camera.sbr" \ + "$(INTDIR)\cmdlib.sbr" \ + "$(INTDIR)\csg.sbr" \ + "$(INTDIR)\drag.sbr" \ + "$(INTDIR)\eclass.sbr" \ + "$(INTDIR)\entity.sbr" \ + "$(INTDIR)\lbmlib.sbr" \ + "$(INTDIR)\map.sbr" \ + "$(INTDIR)\mathlib.sbr" \ + "$(INTDIR)\mru.sbr" \ + "$(INTDIR)\parse.sbr" \ + "$(INTDIR)\points.sbr" \ + "$(INTDIR)\qe3.sbr" \ + "$(INTDIR)\select.sbr" \ + "$(INTDIR)\textures.sbr" \ + "$(INTDIR)\vertsel.sbr" \ + "$(INTDIR)\win_cam.sbr" \ + "$(INTDIR)\win_dlg.sbr" \ + "$(INTDIR)\win_ent.sbr" \ + "$(INTDIR)\win_main.sbr" \ + "$(INTDIR)\win_qe3.sbr" \ + "$(INTDIR)\win_xy.sbr" \ + "$(INTDIR)\win_z.sbr" \ + "$(INTDIR)\xy.sbr" \ + "$(INTDIR)\z.sbr" + +"$(OUTDIR)\qe4.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib opengl32.lib glu32.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:windows /debug /machine:I386 +LINK32_FLAGS=comctl32.lib opengl32.lib glu32.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:windows\ + /incremental:no /pdb:"$(OUTDIR)/qe4.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/qe4.exe" +LINK32_OBJS= \ + "$(INTDIR)\brush.obj" \ + "$(INTDIR)\camera.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\drag.obj" \ + "$(INTDIR)\eclass.obj" \ + "$(INTDIR)\entity.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\mru.obj" \ + "$(INTDIR)\parse.obj" \ + "$(INTDIR)\points.obj" \ + "$(INTDIR)\qe3.obj" \ + "$(INTDIR)\select.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\vertsel.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_dlg.obj" \ + "$(INTDIR)\win_ent.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_qe3.obj" \ + "$(INTDIR)\win_qe3.res" \ + "$(INTDIR)\win_xy.obj" \ + "$(INTDIR)\win_z.obj" \ + "$(INTDIR)\xy.obj" \ + "$(INTDIR)\z.obj" + +"$(OUTDIR)\qe4.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qe3 - 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 "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\qe4.exe" "$(OUTDIR)\qe4.bsc" + +CLEAN : + -@erase "$(INTDIR)\brush.obj" + -@erase "$(INTDIR)\brush.sbr" + -@erase "$(INTDIR)\camera.obj" + -@erase "$(INTDIR)\camera.sbr" + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\cmdlib.sbr" + -@erase "$(INTDIR)\csg.obj" + -@erase "$(INTDIR)\csg.sbr" + -@erase "$(INTDIR)\drag.obj" + -@erase "$(INTDIR)\drag.sbr" + -@erase "$(INTDIR)\eclass.obj" + -@erase "$(INTDIR)\eclass.sbr" + -@erase "$(INTDIR)\entity.obj" + -@erase "$(INTDIR)\entity.sbr" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\lbmlib.sbr" + -@erase "$(INTDIR)\map.obj" + -@erase "$(INTDIR)\map.sbr" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\mathlib.sbr" + -@erase "$(INTDIR)\mru.obj" + -@erase "$(INTDIR)\mru.sbr" + -@erase "$(INTDIR)\parse.obj" + -@erase "$(INTDIR)\parse.sbr" + -@erase "$(INTDIR)\points.obj" + -@erase "$(INTDIR)\points.sbr" + -@erase "$(INTDIR)\qe3.obj" + -@erase "$(INTDIR)\qe3.sbr" + -@erase "$(INTDIR)\select.obj" + -@erase "$(INTDIR)\select.sbr" + -@erase "$(INTDIR)\textures.obj" + -@erase "$(INTDIR)\textures.sbr" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\vertsel.obj" + -@erase "$(INTDIR)\vertsel.sbr" + -@erase "$(INTDIR)\win_cam.obj" + -@erase "$(INTDIR)\win_cam.sbr" + -@erase "$(INTDIR)\win_dlg.obj" + -@erase "$(INTDIR)\win_dlg.sbr" + -@erase "$(INTDIR)\win_ent.obj" + -@erase "$(INTDIR)\win_ent.sbr" + -@erase "$(INTDIR)\win_main.obj" + -@erase "$(INTDIR)\win_main.sbr" + -@erase "$(INTDIR)\win_qe3.obj" + -@erase "$(INTDIR)\win_qe3.res" + -@erase "$(INTDIR)\win_qe3.sbr" + -@erase "$(INTDIR)\win_xy.obj" + -@erase "$(INTDIR)\win_xy.sbr" + -@erase "$(INTDIR)\win_z.obj" + -@erase "$(INTDIR)\win_z.sbr" + -@erase "$(INTDIR)\xy.obj" + -@erase "$(INTDIR)\xy.sbr" + -@erase "$(INTDIR)\z.obj" + -@erase "$(INTDIR)\z.sbr" + -@erase "$(OUTDIR)\qe4.bsc" + -@erase "$(OUTDIR)\qe4.exe" + -@erase "$(OUTDIR)\qe4.map" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /FR"$(INTDIR)/" /Fp"$(INTDIR)/qe4.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\Debug/ + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qe4.bsc" +BSC32_SBRS= \ + "$(INTDIR)\brush.sbr" \ + "$(INTDIR)\camera.sbr" \ + "$(INTDIR)\cmdlib.sbr" \ + "$(INTDIR)\csg.sbr" \ + "$(INTDIR)\drag.sbr" \ + "$(INTDIR)\eclass.sbr" \ + "$(INTDIR)\entity.sbr" \ + "$(INTDIR)\lbmlib.sbr" \ + "$(INTDIR)\map.sbr" \ + "$(INTDIR)\mathlib.sbr" \ + "$(INTDIR)\mru.sbr" \ + "$(INTDIR)\parse.sbr" \ + "$(INTDIR)\points.sbr" \ + "$(INTDIR)\qe3.sbr" \ + "$(INTDIR)\select.sbr" \ + "$(INTDIR)\textures.sbr" \ + "$(INTDIR)\vertsel.sbr" \ + "$(INTDIR)\win_cam.sbr" \ + "$(INTDIR)\win_dlg.sbr" \ + "$(INTDIR)\win_ent.sbr" \ + "$(INTDIR)\win_main.sbr" \ + "$(INTDIR)\win_qe3.sbr" \ + "$(INTDIR)\win_xy.sbr" \ + "$(INTDIR)\win_z.sbr" \ + "$(INTDIR)\xy.sbr" \ + "$(INTDIR)\z.sbr" + +"$(OUTDIR)\qe4.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 comctl32.lib opengl32.lib glu32.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:windows /profile /map /debug /machine:I386 +LINK32_FLAGS=comctl32.lib opengl32.lib glu32.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:windows\ + /profile /map:"$(INTDIR)/qe4.map" /debug /machine:I386 /out:"$(OUTDIR)/qe4.exe"\ + +LINK32_OBJS= \ + "$(INTDIR)\brush.obj" \ + "$(INTDIR)\camera.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\drag.obj" \ + "$(INTDIR)\eclass.obj" \ + "$(INTDIR)\entity.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\mru.obj" \ + "$(INTDIR)\parse.obj" \ + "$(INTDIR)\points.obj" \ + "$(INTDIR)\qe3.obj" \ + "$(INTDIR)\select.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\vertsel.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_dlg.obj" \ + "$(INTDIR)\win_ent.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_qe3.obj" \ + "$(INTDIR)\win_qe3.res" \ + "$(INTDIR)\win_xy.obj" \ + "$(INTDIR)\win_z.obj" \ + "$(INTDIR)\xy.obj" \ + "$(INTDIR)\z.obj" + +"$(OUTDIR)\qe4.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "qe3___Wi" +# PROP BASE Intermediate_Dir "qe3___Wi" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "debug_alpha" +# PROP Intermediate_Dir "debug_alpha" +# PROP Target_Dir "" +OUTDIR=.\debug_alpha +INTDIR=.\debug_alpha + +ALL : "$(OUTDIR)\qe3.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MLd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/qe3.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\debug_alpha/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /alpha +# ADD MTL /nologo /D "_DEBUG" /alpha +MTL_PROJ=/nologo /D "_DEBUG" /alpha +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qe3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:ALPHA +# SUBTRACT BASE LINK32 /incremental:no +# ADD LINK32 comctl32.lib opengl32.lib glu32.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:windows /debug /machine:ALPHA +# SUBTRACT LINK32 /incremental:no +LINK32_FLAGS=comctl32.lib opengl32.lib glu32.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:windows /incremental:yes /pdb:"$(OUTDIR)/qe3.pdb" /debug\ + /machine:ALPHA /out:"$(OUTDIR)/qe3.exe" +LINK32_OBJS= \ + "$(INTDIR)\brush.obj" \ + "$(INTDIR)\camera.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\drag.obj" \ + "$(INTDIR)\eclass.obj" \ + "$(INTDIR)\entity.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\mru.obj" \ + "$(INTDIR)\parse.obj" \ + "$(INTDIR)\points.obj" \ + "$(INTDIR)\qe3.obj" \ + "$(INTDIR)\select.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\vertsel.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_dlg.obj" \ + "$(INTDIR)\win_ent.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_qe3.obj" \ + "$(INTDIR)\win_qe3.res" \ + "$(INTDIR)\win_xy.obj" \ + "$(INTDIR)\win_z.obj" \ + "$(INTDIR)\xy.obj" \ + "$(INTDIR)\z.obj" + +"$(OUTDIR)\qe3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "qe3___W0" +# PROP BASE Intermediate_Dir "qe3___W0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "release_alpha" +# PROP Intermediate_Dir "release_alpha" +# PROP Target_Dir "" +OUTDIR=.\release_alpha +INTDIR=.\release_alpha + +ALL : "$(OUTDIR)\qe3.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /ML /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/qe3.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\release_alpha/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /alpha +# ADD MTL /nologo /D "NDEBUG" /alpha +MTL_PROJ=/nologo /D "NDEBUG" /alpha +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/qe3.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:ALPHA +# ADD LINK32 comctl32.lib opengl32.lib glu32.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:windows /machine:ALPHA +LINK32_FLAGS=comctl32.lib opengl32.lib glu32.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:windows\ + /incremental:no /pdb:"$(OUTDIR)/qe3.pdb" /machine:ALPHA\ + /out:"$(OUTDIR)/qe3.exe" +LINK32_OBJS= \ + "$(INTDIR)\brush.obj" \ + "$(INTDIR)\camera.obj" \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\csg.obj" \ + "$(INTDIR)\drag.obj" \ + "$(INTDIR)\eclass.obj" \ + "$(INTDIR)\entity.obj" \ + "$(INTDIR)\map.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\mru.obj" \ + "$(INTDIR)\parse.obj" \ + "$(INTDIR)\points.obj" \ + "$(INTDIR)\qe3.obj" \ + "$(INTDIR)\select.obj" \ + "$(INTDIR)\textures.obj" \ + "$(INTDIR)\vertsel.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_dlg.obj" \ + "$(INTDIR)\win_ent.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_qe3.obj" \ + "$(INTDIR)\win_qe3.res" \ + "$(INTDIR)\win_xy.obj" \ + "$(INTDIR)\win_z.obj" \ + "$(INTDIR)\xy.obj" \ + "$(INTDIR)\z.obj" + +"$(OUTDIR)\qe3.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +################################################################################ +# Begin Target + +# Name "qe3 - Win32 Release" +# Name "qe3 - Win32 Debug" +# Name "qe3 - Win32 (ALPHA) Debug" +# Name "qe3 - Win32 (ALPHA) Release" + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\textures.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\textures.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_TEXTU=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\textures.obj" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + +"$(INTDIR)\textures.sbr" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_TEXTU=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\textures.obj" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + +"$(INTDIR)\textures.sbr" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_TEXTU=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\textures.obj" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_TEXTU=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\textures.obj" : $(SOURCE) $(DEP_CPP_TEXTU) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\resource.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\mathlib.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\mathlib.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_MATHL=\ + ".\cmdlib.h"\ + ".\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + +"$(INTDIR)\mathlib.sbr" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_MATHL=\ + ".\cmdlib.h"\ + ".\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + +"$(INTDIR)\mathlib.sbr" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_MATHL=\ + ".\cmdlib.h"\ + ".\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_MATHL=\ + ".\cmdlib.h"\ + ".\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\map.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\map.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_MAP_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\map.obj" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + +"$(INTDIR)\map.sbr" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_MAP_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\map.obj" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + +"$(INTDIR)\map.sbr" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_MAP_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\map.obj" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_MAP_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\map.obj" : $(SOURCE) $(DEP_CPP_MAP_C) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\cmdlib.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\cmdlib.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_CMDLI=\ + ".\cmdlib.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + +"$(INTDIR)\cmdlib.sbr" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_CMDLI=\ + ".\cmdlib.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + +"$(INTDIR)\cmdlib.sbr" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_CMDLI=\ + ".\cmdlib.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_CMDLI=\ + ".\cmdlib.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\brush.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\brush.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_BRUSH=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\brush.obj" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + +"$(INTDIR)\brush.sbr" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_BRUSH=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\brush.obj" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + +"$(INTDIR)\brush.sbr" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_BRUSH=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\brush.obj" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_BRUSH=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\brush.obj" : $(SOURCE) $(DEP_CPP_BRUSH) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\notes.txt + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_cam.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_cam.obj" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + +"$(INTDIR)\win_cam.sbr" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_cam.obj" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + +"$(INTDIR)\win_cam.sbr" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_cam.obj" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_cam.obj" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qe3.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\parse.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\parse.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_PARSE=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\parse.obj" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + +"$(INTDIR)\parse.sbr" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_PARSE=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\parse.obj" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + +"$(INTDIR)\parse.sbr" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_PARSE=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\parse.obj" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_PARSE=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\parse.obj" : $(SOURCE) $(DEP_CPP_PARSE) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\camera.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\camera.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_CAMER=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\camera.obj" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + +"$(INTDIR)\camera.sbr" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_CAMER=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\camera.obj" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + +"$(INTDIR)\camera.sbr" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_CAMER=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\camera.obj" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_CAMER=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\camera.obj" : $(SOURCE) $(DEP_CPP_CAMER) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_qe3.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_xy.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_X=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_xy.obj" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + +"$(INTDIR)\win_xy.sbr" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_X=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_xy.obj" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + +"$(INTDIR)\win_xy.sbr" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_X=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_xy.obj" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_X=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_xy.obj" : $(SOURCE) $(DEP_CPP_WIN_X) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_qe3.rc + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_RSC_WIN_Q=\ + ".\icon1.ico"\ + ".\q.bmp"\ + ".\toolbar1.bmp"\ + + +"$(INTDIR)\win_qe3.res" : $(SOURCE) $(DEP_RSC_WIN_Q) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_RSC_WIN_Q=\ + ".\icon1.ico"\ + ".\q.bmp"\ + ".\toolbar1.bmp"\ + + +"$(INTDIR)\win_qe3.res" : $(SOURCE) $(DEP_RSC_WIN_Q) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_RSC_WIN_Q=\ + ".\icon1.ico"\ + ".\toolbar1.bmp"\ + + +"$(INTDIR)\win_qe3.res" : $(SOURCE) $(DEP_RSC_WIN_Q) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "_DEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_RSC_WIN_Q=\ + ".\icon1.ico"\ + ".\toolbar1.bmp"\ + + +"$(INTDIR)\win_qe3.res" : $(SOURCE) $(DEP_RSC_WIN_Q) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/win_qe3.res" /d "NDEBUG" $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\xy.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_XY_C14=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\xy.obj" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + +"$(INTDIR)\xy.sbr" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_XY_C14=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\xy.obj" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + +"$(INTDIR)\xy.sbr" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_XY_C14=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\xy.obj" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_XY_C14=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\xy.obj" : $(SOURCE) $(DEP_CPP_XY_C14) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\xy.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\select.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_SELEC=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\select.obj" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + +"$(INTDIR)\select.sbr" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_SELEC=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\select.obj" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + +"$(INTDIR)\select.sbr" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_SELEC=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\select.obj" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_SELEC=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\select.obj" : $(SOURCE) $(DEP_CPP_SELEC) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_qe3.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_QE=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_qe3.obj" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + +"$(INTDIR)\win_qe3.sbr" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_QE=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_qe3.obj" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + +"$(INTDIR)\win_qe3.sbr" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_QE=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_qe3.obj" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_QE=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_qe3.obj" : $(SOURCE) $(DEP_CPP_WIN_QE) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\select.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qe3.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_QE3_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\qe3.obj" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + +"$(INTDIR)\qe3.sbr" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_QE3_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\qe3.obj" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + +"$(INTDIR)\qe3.sbr" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_QE3_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\qe3.obj" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_QE3_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\qe3.obj" : $(SOURCE) $(DEP_CPP_QE3_C) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\eclass.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_ECLAS=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\eclass.obj" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + +"$(INTDIR)\eclass.sbr" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_ECLAS=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\eclass.obj" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + +"$(INTDIR)\eclass.sbr" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_ECLAS=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\eclass.obj" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_ECLAS=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\eclass.obj" : $(SOURCE) $(DEP_CPP_ECLAS) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\eclass.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\entity.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_ENTIT=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\entity.obj" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + +"$(INTDIR)\entity.sbr" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_ENTIT=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\entity.obj" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + +"$(INTDIR)\entity.sbr" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_ENTIT=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\entity.obj" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_ENTIT=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\entity.obj" : $(SOURCE) $(DEP_CPP_ENTIT) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\entity.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_dlg.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_D=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_dlg.obj" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + +"$(INTDIR)\win_dlg.sbr" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_D=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_dlg.obj" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + +"$(INTDIR)\win_dlg.sbr" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_D=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_dlg.obj" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_D=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_dlg.obj" : $(SOURCE) $(DEP_CPP_WIN_D) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\points.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_POINT=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\points.obj" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + +"$(INTDIR)\points.sbr" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_POINT=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\points.obj" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + +"$(INTDIR)\points.sbr" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_POINT=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\points.obj" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_POINT=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\points.obj" : $(SOURCE) $(DEP_CPP_POINT) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_z.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_Z=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_z.obj" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + +"$(INTDIR)\win_z.sbr" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_Z=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_z.obj" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + +"$(INTDIR)\win_z.sbr" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_Z=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_z.obj" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_Z=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_z.obj" : $(SOURCE) $(DEP_CPP_WIN_Z) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\z.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_Z_C26=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\z.obj" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + +"$(INTDIR)\z.sbr" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_Z_C26=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\z.obj" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + +"$(INTDIR)\z.sbr" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_Z_C26=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\z.obj" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_Z_C26=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\z.obj" : $(SOURCE) $(DEP_CPP_Z_C26) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\z.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\drag.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_DRAG_=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\drag.obj" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + +"$(INTDIR)\drag.sbr" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_DRAG_=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\drag.obj" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + +"$(INTDIR)\drag.sbr" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_DRAG_=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\drag.obj" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_DRAG_=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\drag.obj" : $(SOURCE) $(DEP_CPP_DRAG_) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_main.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_M=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_main.obj" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + +"$(INTDIR)\win_main.sbr" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_M=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_main.obj" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + +"$(INTDIR)\win_main.sbr" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_M=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_main.obj" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_M=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_main.obj" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\csg.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_CSG_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\csg.obj" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + +"$(INTDIR)\csg.sbr" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_CSG_C=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\csg.obj" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + +"$(INTDIR)\csg.sbr" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_CSG_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\csg.obj" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_CSG_C=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\csg.obj" : $(SOURCE) $(DEP_CPP_CSG_C) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\vertsel.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_VERTS=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\vertsel.obj" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + +"$(INTDIR)\vertsel.sbr" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_VERTS=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\vertsel.obj" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + +"$(INTDIR)\vertsel.sbr" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_VERTS=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\vertsel.obj" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_VERTS=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\vertsel.obj" : $(SOURCE) $(DEP_CPP_VERTS) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\mru.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_MRU_C=\ + ".\mru.h"\ + + +"$(INTDIR)\mru.obj" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + +"$(INTDIR)\mru.sbr" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_MRU_C=\ + ".\mru.h"\ + + +"$(INTDIR)\mru.obj" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + +"$(INTDIR)\mru.sbr" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_MRU_C=\ + ".\mru.h"\ + + +"$(INTDIR)\mru.obj" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_MRU_C=\ + ".\mru.h"\ + + +"$(INTDIR)\mru.obj" : $(SOURCE) $(DEP_CPP_MRU_C) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_ent.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_WIN_E=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_ent.obj" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + +"$(INTDIR)\win_ent.sbr" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_WIN_E=\ + ".\brush.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\glingr.h"\ + ".\lbmlib.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\mru.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\qedefs.h"\ + ".\qfiles.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_ent.obj" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + +"$(INTDIR)\win_ent.sbr" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +DEP_CPP_WIN_E=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_ent.obj" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +DEP_CPP_WIN_E=\ + ".\brush.h"\ + ".\bspfile.h"\ + ".\camera.h"\ + ".\cmdlib.h"\ + ".\entity.h"\ + ".\entityw.h"\ + ".\gl\GL.H"\ + ".\gl\GLAUX.H"\ + ".\gl\GLU.H"\ + ".\glingr.h"\ + ".\map.h"\ + ".\mathlib.h"\ + ".\parse.h"\ + ".\qe3.h"\ + ".\select.h"\ + ".\textures.h"\ + ".\xy.h"\ + ".\z.h"\ + + +"$(INTDIR)\win_ent.obj" : $(SOURCE) $(DEP_CPP_WIN_E) "$(INTDIR)" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\lbmlib.c + +!IF "$(CFG)" == "qe3 - Win32 Release" + +DEP_CPP_LBMLI=\ + ".\cmdlib.h"\ + ".\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + +"$(INTDIR)\lbmlib.sbr" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +DEP_CPP_LBMLI=\ + ".\cmdlib.h"\ + ".\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + +"$(INTDIR)\lbmlib.sbr" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\qfiles.h + +!IF "$(CFG)" == "qe3 - Win32 Release" + +!ELSEIF "$(CFG)" == "qe3 - Win32 Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Debug" + +!ELSEIF "$(CFG)" == "qe3 - Win32 (ALPHA) Release" + +!ENDIF + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/tools/quake2/extra/qe4/qedefs.h b/tools/quake2/extra/qe4/qedefs.h new file mode 100644 index 00000000..041aaab6 --- /dev/null +++ b/tools/quake2/extra/qe4/qedefs.h @@ -0,0 +1,117 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#ifndef __QEDEFS_H__ +#define __QEDEFS_H__ + +#define QE_VERSION 0x0401 + +#define QE3_STYLE (WS_OVERLAPPED| WS_CAPTION | WS_THICKFRAME | \ + /* WS_MINIMIZEBOX | */ WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | \ + WS_CLIPCHILDREN | WS_CHILD) + +#define QE_AUTOSAVE_INTERVAL 5 // number of minutes between autosaves + +#define CAMERA_WINDOW_CLASS "QCamera" +#define XY_WINDOW_CLASS "QXY" +#define Z_WINDOW_CLASS "QZ" +#define ENT_WINDOW_CLASS "QENT" + +#define ZWIN_WIDTH 40 +#define CWIN_SIZE (0.4) + +#define MAX_EDGES 256 +#define MAX_POINTS 512 + +#define CMD_TEXTUREWAD 60000 +#define CMD_BSPCOMMAND 61000 + +#define PITCH 0 +#define YAW 1 +#define ROLL 2 + +#define QE_TIMER0 1 + +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +#define ON_EPSILON 0.01 + +#define KEY_FORWARD 1 +#define KEY_BACK 2 +#define KEY_TURNLEFT 4 +#define KEY_TURNRIGHT 8 +#define KEY_LEFT 16 +#define KEY_RIGHT 32 +#define KEY_LOOKUP 64 +#define KEY_LOOKDOWN 128 +#define KEY_UP 256 +#define KEY_DOWN 512 + +// xy.c +#define EXCLUDE_LIGHTS 1 +#define EXCLUDE_ENT 2 +#define EXCLUDE_PATHS 4 +#define EXCLUDE_WATER 8 +#define EXCLUDE_WORLD 16 +#define EXCLUDE_CLIP 32 +#define EXCLUDE_DETAIL 64 + + +// +// menu indexes for modifying menus +// +#define MENU_VIEW 2 +#define MENU_BSP 4 +#define MENU_TEXTURE 6 + + +// odd things not in windows header... +#define VK_COMMA 188 +#define VK_PERIOD 190 + +/* +** window bits +*/ +#define W_CAMERA 0x0001 +#define W_XY 0x0002 +#define W_XY_OVERLAY 0x0004 +#define W_Z 0x0008 +#define W_TEXTURE 0x0010 +#define W_Z_OVERLAY 0x0020 +#define W_CONSOLE 0x0040 +#define W_ENTITY 0x0080 +#define W_ALL 0xFFFFFFFF + +#define COLOR_TEXTUREBACK 0 +#define COLOR_GRIDBACK 1 +#define COLOR_GRIDMINOR 2 +#define COLOR_GRIDMAJOR 3 +#define COLOR_CAMERABACK 4 +#define COLOR_ENTITY 5 +#define COLOR_LAST 6 + +#endif diff --git a/tools/quake2/extra/qe4/qfiles.h b/tools/quake2/extra/qe4/qfiles.h new file mode 100644 index 00000000..e7dbbdfe --- /dev/null +++ b/tools/quake2/extra/qe4/qfiles.h @@ -0,0 +1,389 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// +// qfiles.h: quake file formats +// This file must be identical in the quake and utils directories +// + +/* +======================================================================== + +.MD2 triangle model file format + +======================================================================== +*/ + +#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I') +#define ALIAS_VERSION 8 + +#define MAX_TRIANGLES 4096 +#define MAX_VERTS 2048 +#define MAX_FRAMES 512 +#define MAX_MD2SKINS 32 +#define MAX_SKINNAME 64 + +typedef struct +{ + short s; + short t; +} dstvert_t; + +typedef struct +{ + short index_xyz[3]; + short index_st[3]; +} dtriangle_t; + +typedef struct +{ + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; +} dtrivertx_t; + +typedef struct +{ + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + dtrivertx_t verts[1]; // variable sized +} daliasframe_t; + + +// the glcmd format: +// a positive integer starts a tristrip command, followed by that many +// vertex structures. +// a negative integer starts a trifan command, followed by -x vertexes +// a zero indicates the end of the command list. +// a vertex consists of a floating point s, a floating point t, +// and an integer vertex index. + + +typedef struct +{ + int ident; + int version; + + int skinwidth; + int skinheight; + int framesize; // byte size of each frame + + int num_skins; + int num_xyz; + int num_st; // greater than num_xyz for seams + int num_tris; + int num_glcmds; // dwords in strip/fan command list + int num_frames; + + int ofs_skins; // each skin is a MAX_SKINNAME string + int ofs_st; // byte offset from start for stverts + int ofs_tris; // offset for dtriangles + int ofs_frames; // offset for first frame + int ofs_glcmds; + int ofs_end; // end of file + +} dmdl_t; + +/* +======================================================================== + +.SP2 sprite file format + +======================================================================== +*/ + +#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I') + // little-endian "IDS2" +#define SPRITE_VERSION 2 + +typedef struct +{ + int width, height; + int origin_x, origin_y; // raster coordinates inside pic + char name[MAX_SKINNAME]; // name of pcx file +} dsprframe_t; + +typedef struct { + int ident; + int version; + int numframes; + dsprframe_t frames[1]; // variable sized +} dsprite_t; + +/* +============================================================================== + + .WAL texture file format + +============================================================================== +*/ + + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[32]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored + char animname[32]; // next frame in animation chain + int flags; + int contents; + int value; +} miptex_t; + + + +/* +============================================================================== + + .BSP file format + +============================================================================== +*/ + +#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') + // little-endian "IBSP" + +#define BSPVERSION 36 + + +// upper design bounds +// leaffaces, leafbrushes, planes, and verts are still bounded by +// 16 bit short limits +#define MAX_MAP_MODELS 1024 +#define MAX_MAP_BRUSHES 8192 +#define MAX_MAP_ENTITIES 2048 +#define MAX_MAP_ENTSTRING 0x20000 +#define MAX_MAP_TEXINFO 8192 + +#define MAX_MAP_PLANES 65536 +#define MAX_MAP_NODES 65536 +#define MAX_MAP_BRUSHSIDES 65536 +#define MAX_MAP_LEAFS 65536 +#define MAX_MAP_VERTS 65536 +#define MAX_MAP_FACES 65536 +#define MAX_MAP_LEAFFACES 65536 +#define MAX_MAP_LEAFBRUSHES 65536 +#define MAX_MAP_PORTALS 65536 +#define MAX_MAP_EDGES 128000 +#define MAX_MAP_SURFEDGES 256000 +#define MAX_MAP_LIGHTING 0x200000 +#define MAX_MAP_VISIBILITY 0x100000 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 1024 + +//============================================================================= + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_VERTEXES 2 +#define LUMP_VISIBILITY 3 +#define LUMP_NODES 4 +#define LUMP_TEXINFO 5 +#define LUMP_FACES 6 +#define LUMP_LIGHTING 7 +#define LUMP_LEAFS 8 +#define LUMP_LEAFFACES 9 +#define LUMP_LEAFBRUSHES 10 +#define LUMP_EDGES 11 +#define LUMP_SURFEDGES 12 +#define LUMP_MODELS 13 +#define LUMP_BRUSHES 14 +#define LUMP_BRUSHSIDES 15 +#define LUMP_POP 16 + +#define HEADER_LUMPS 17 + +typedef struct +{ + int ident; + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; // for sounds or lights + int headnode; + int firstface, numfaces; // submodels just draw faces + // without walking the bsp tree +} dmodel_t; + + +typedef struct +{ + float point[3]; +} dvertex_t; + + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +// planes (x&~1) and (x&~1)+1 are allways opposites + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + + +// contents flags are seperate bits +// a given brush can contribute multiple content bits +// multiple brushes can be in a single leaf + +// lower bits are stronger, and will eat weaker brushes completely +#define CONTENTS_SOLID 1 // an eye is never valid in a solid +#define CONTENTS_WINDOW 2 // translucent, but not watery +#define CONTENTS_AUX 4 +#define CONTENTS_LAVA 8 +#define CONTENTS_SLIME 16 +#define CONTENTS_WATER 32 +#define CONTENTS_MIST 64 +#define LAST_VISIBLE_CONTENTS 64 + +// remaining contents are non-visible, and don't eat brushes +#define CONTENTS_PLAYERCLIP 0x10000 +#define CONTENTS_MONSTERCLIP 0x20000 + +// currents can be added to any other contents, and may be mixed +#define CONTENTS_CURRENT_0 0x40000 +#define CONTENTS_CURRENT_90 0x80000 +#define CONTENTS_CURRENT_180 0x100000 +#define CONTENTS_CURRENT_270 0x200000 +#define CONTENTS_CURRENT_UP 0x400000 +#define CONTENTS_CURRENT_DOWN 0x800000 + +#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity + +#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game +#define CONTENTS_DEADMONSTER 0x4000000 +#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs +#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans + + + +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for frustom culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int flags; // miptex flags + overrides + int value; // light emission, etc + char texture[32]; // texture name (textures/*.wal) + int nexttexinfo; // for animations, -1 = end of chain +} texinfo_t; + + +#define SURF_LIGHT 0x1 // value will hold the light strength + +#define SURF_SLICK 0x2 // effects game physics + +#define SURF_SKY 0x4 // don't draw, but add to skybox +#define SURF_WARP 0x8 // turbulent water warp +#define SURF_TRANS33 0x10 +#define SURF_TRANS66 0x20 +#define SURF_FLOWING 0x40 // scroll towards angle +#define SURF_NODRAW 0x80 // don't bother referencing the texture + + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 +typedef struct +{ + unsigned short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + +typedef struct +{ + int contents; // OR of all brushes (not needed?) + + int pvsofs; // -1 = no info + int phsofs; // -1 = no info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstleafface; + unsigned short numleaffaces; + + unsigned short firstleafbrush; + unsigned short numleafbrushes; +} dleaf_t; + +typedef struct +{ + unsigned short planenum; // facing out of the leaf + short texinfo; +} dbrushside_t; + +typedef struct +{ + int firstside; + int numsides; + int contents; +} dbrush_t; + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + diff --git a/tools/quake2/extra/qe4/resource.h b/tools/quake2/extra/qe4/resource.h new file mode 100644 index 00000000..0a65eca2 --- /dev/null +++ b/tools/quake2/extra/qe4/resource.h @@ -0,0 +1,308 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by win_qe3.rc +// +#define IDAPPLY 3 +#define IDR_MENU1 101 +#define IDR_ACCELERATOR1 104 +#define IDD_CREATE_ENTITY 107 +#define IDD_EDIT_ENTITY 108 +#define IDR_TOOLBAR1 109 +#define IDD_FINDTEXTURE 111 +#define IDD_ENTITY 115 +#define IDR_E_MENU 116 +#define IDD_EDITPROP 117 +#define IDD_GAMMA 118 +#define IDD_FINDBRUSH 119 +#define IDI_ICON1 120 +#define IDD_ROTATE 121 +#define IDD_SIDES 122 +#define IDD_ABOUT 123 +#define IDB_BITMAP1 127 +#define IDD_SURFACE 129 +#define IDC_ENTITY_COMMENT 1018 +#define IDC_VALUE 1021 +#define IDC_KEY 1022 +#define IDC_ENTITY_LIST 1023 +#define IDC_PAIRS 1024 +#define IDC_CHECK1 1026 +#define IDC_CHECK2 1027 +#define IDC_CHECK3 1028 +#define IDC_CHECK4 1029 +#define IDC_CHECK5 1030 +#define IDC_CHECK6 1031 +#define IDC_CHECK7 1032 +#define IDC_CHECK8 1033 +#define IDC_CHECK9 1034 +#define IDC_CHECK10 1035 +#define IDC_CHECK11 1036 +#define IDC_CHECK12 1037 +#define IDC_ANGLE90 1038 +#define IDC_CHECK13 1038 +#define IDC_ANGLE45 1039 +#define IDC_CHECK14 1039 +#define IDC_ANGLE135 1040 +#define IDC_CHECK15 1040 +#define IDC_ANGLE225 1041 +#define IDC_CHECK16 1041 +#define IDC_ANGLEUP 1042 +#define IDC_CHECK17 1042 +#define IDC_ANGLE180 1043 +#define IDC_CHECK18 1043 +#define IDC_ANGLE315 1044 +#define IDC_CHECK19 1044 +#define IDC_ANGLE0 1045 +#define IDC_CHECK20 1045 +#define IDC_ANGLE270 1046 +#define IDC_CHECK21 1046 +#define IDC_ANGLEDOWN 1047 +#define IDC_CHECK22 1047 +#define IDC_DELETEKEY 1048 +#define IDC_ADDPAIR 1048 +#define IDC_CHECK23 1048 +#define IDC_DELETEPAIR 1049 +#define IDC_CHECK24 1049 +#define IDC_CHECK25 1050 +#define IDC_SPAWN1 1051 +#define IDC_CHECK26 1051 +#define IDC_SPAWN2 1052 +#define IDC_CHECK27 1052 +#define IDC_SPAWN3 1053 +#define IDC_CHECK28 1053 +#define IDC_SPAWN4 1054 +#define IDC_CHECK29 1054 +#define IDC_SPAWN5 1055 +#define IDC_CHECK30 1055 +#define IDC_SPAWN6 1056 +#define IDC_CHECK31 1056 +#define IDC_SPAWN7 1057 +#define IDC_CHECK32 1057 +#define IDC_SPAWN8 1058 +#define IDC_CHECK33 1058 +#define IDC_EDIT1 1059 +#define IDC_CHECK34 1059 +#define IDC_ROTATE_BOX 1060 +#define IDC_ROTZ 1060 +#define IDC_CHECK35 1060 +#define IDC_SCALE_BOX 1061 +#define IDC_ROTY 1061 +#define IDC_CHECK36 1061 +#define IDC_E_VALUE_FIELD 1062 +#define IDC_CHECK37 1062 +#define IDC_CHECK38 1063 +#define IDC_E_LIST 1064 +#define IDC_CHECK39 1064 +#define IDC_E_COMMENT 1065 +#define IDC_CHECK40 1065 +#define IDC_CHECK41 1066 +#define IDC_E_PROPS 1067 +#define IDC_CHECK42 1067 +#define IDC_E_135 1068 +#define IDC_CHECK43 1068 +#define IDC_E_180 1069 +#define IDC_CHECK44 1069 +#define IDC_E_225 1070 +#define IDC_CHECK45 1070 +#define IDC_E_270 1071 +#define IDC_CHECK46 1071 +#define IDC_E_90 1072 +#define IDC_CHECK47 1072 +#define IDC_E_45 1073 +#define IDC_CHECK48 1073 +#define IDC_E_0 1074 +#define IDC_CHECK49 1074 +#define IDC_E_315 1075 +#define IDC_CHECK50 1075 +#define IDC_E_UP 1076 +#define IDC_CHECK51 1076 +#define IDC_E_DOWN 1077 +#define IDC_CHECK52 1077 +#define IDC_CHECK53 1078 +#define IDC_CHECK54 1079 +#define IDC_E_ADDPROP 1080 +#define IDC_CHECK55 1080 +#define IDC_E_DELPROP 1081 +#define IDC_CHECK56 1081 +#define IDC_E_CREATE 1082 +#define IDC_CHECK57 1082 +#define IDC_E_STATUS 1083 +#define IDC_CHECK58 1083 +#define IDC_CHECK59 1084 +#define IDC_CHECK60 1085 +#define IDC_CHECK61 1086 +#define IDC_CHECK62 1087 +#define IDC_CHECK63 1088 +#define IDC_CHECK64 1089 +#define IDC_SHIFT_BOX 1090 +#define IDC_HSHIFT 1090 +#define IDC_VSHIFT 1091 +#define IDC_ROTATEV 1092 +#define IDC_SCALEV 1093 +#define IDC_SCALEH 1094 +#define IDC_SHIFTV 1095 +#define IDC_HSHIFTA 1095 +#define IDC_SHIFTH 1096 +#define IDC_VSHIFTA 1097 +#define IDC_HSCALE 1098 +#define IDC_HSCALEA 1099 +#define IDC_VSCALE 1100 +#define IDC_VSCALEA 1101 +#define IDC_ROTATE 1102 +#define IDC_G_EDIT 1103 +#define IDC_ROTATEA 1103 +#define IDC_STATIC_KEY 1104 +#define IDC_FIND_BRUSH 1104 +#define IDC_STATIC_VALUE 1105 +#define IDC_E_KEY_FIELD 1106 +#define IDC_FIND_ENTITY 1107 +#define IDC_SIDES 1108 +#define IDC_ROTX 1109 +#define IDC_E_COLOR 1111 +#define IDC_ABOUT_GLVENDOR 1112 +#define IDC_ABOUT_GLVERSION 1113 +#define IDC_ABOUT_GLRENDERER 1114 +#define IDC_TEXTURE 1114 +#define IDC_ABOUT_GLEXTENSIONS 1115 +#define ID_FILE_EXIT 40002 +#define ID_FILE_SAVEAS 40004 +#define ID_VIEW_CENTER 40005 +#define ID_VIEW_UPFLOOR 40006 +#define ID_VIEW_DOWNFLOOR 40007 +#define ID_BRUSH_FLIPX 40008 +#define ID_BRUSH_FLIPY 40009 +#define ID_BRUSH_FLIPZ 40010 +#define ID_BRUSH_ROTATEX 40011 +#define ID_BRUSH_ROTATEY 40012 +#define ID_BRUSH_ROTATEZ 40013 +#define ID_BSP_FULLVIS 40016 +#define ID_BSP_FASTVIS 40017 +#define ID_BSP_NOVIS 40018 +#define ID_BSP_RELIGHT 40019 +#define ID_BSP_ENTITIES 40020 +#define ID_FILE_POINTFILE 40021 +#define ID_VIEW_100 40022 +#define ID_VIEW_75 40023 +#define ID_VIEW_50 40024 +#define ID_VIEW_25 40025 +#define ID_VIEW_12 40026 +#define ID_GRID_1 40028 +#define ID_GRID_2 40029 +#define ID_GRID_4 40030 +#define ID_GRID_8 40031 +#define ID_GRID_16 40032 +#define ID_TEXTURES_SHOWALL 40033 +#define ID_TEXTURES_SHOWINUSE 40034 +#define ID_TEXTURES_TOGGLEVIEW 40037 +#define ID_SELECTION_CREATEENTITY 40039 +#define ID_SELECTION_EDITENTITY 40040 +#define ID_MISC_BENCHMARK 40041 +#define ID_REGION_OFF 40043 +#define ID_REGION_SETXY 40044 +#define ID_REGION_SETBRUSH 40045 +#define ID_SELECTION_MAKEHOLLOW 40046 +#define ID_SELECTION_SELECTPARTIALTALL 40047 +#define ID_SELECTION_SELECTCOMPLETETALL 40048 +#define ID_SELECTION_CSGSUBTRACT 40049 +#define ID_SELECTION_SELECTTOUCHING 40050 +#define ID_VIEW_NEAREST 40052 +#define ID_VIEW_LINEAR 40053 +#define ID_VIEW_BILINEAR 40054 +#define ID_VIEW_TRILINEAR 40055 +#define ID_VIEW_NEARESTMIPMAP 40056 +#define ID_VIEW_BILINEARMIPMAP 40057 +#define ID_VIEW_SHOWNAMES 40058 +#define ID_VIEW_ZOOMIN 40059 +#define ID_VIEW_ZOOMOUT 40060 +#define ID_VIEW_SHOWCOORDINATES 40061 +#define ID_VIEW_Z100 40062 +#define ID_VIEW_ZZOOMIN 40063 +#define ID_VIEW_ZZOOMOUT 40064 +#define ID_SELECTION_CLONE 40065 +#define ID_SELECTION_DESELECT 40066 +#define ID_SELECTION_DELETE 40067 +#define ID_BUTTON40068 40068 +#define ID_TEXTURES_WIREFRAME 40072 +#define ID_TEXTURES_FLATSHADE 40073 +#define ID_SELECTION_DRAGVERTECIES 40074 +#define ID_SELECTION_DRAGEDGES 40075 +#define ID_REGION_SETTALLBRUSH 40076 +#define ID_SELECTION_SELECTINSIDE 40092 +#define ID_PROJECT_RELEAD 40094 +#define ID_PROJECT_CHANGE 40095 +#define ID_MISC_GAMMA 40097 +#define ID_VIEW_SHOWENT 40098 +#define ID_VIEW_SHOWPATH 40099 +#define ID_VIEW_SHOWLIGHTS 40100 +#define ID_VIEW_SHOWCLIP 40101 +#define ID_VIEW_SHOWWATER 40102 +#define ID_VIEW_SHOWWORLD 40103 +#define ID_MISC_TEXTUREBACKGROUN 40104 +#define ID_TEXTUREBK 40105 +#define ID_COLORS_XYBK 40106 +#define ID_FILE_ABOUT 40107 +#define ID_VIEW_CONSOLE 40108 +#define ID_VIEW_ENTITY 40109 +#define ID_VIEW_TEXTURE 40110 +#define ID_COLORS_MAJOR 40111 +#define ID_COLORS_MINOR 40113 +#define ID_SELECTION_CONNECT 40114 +#define ID_FILE_LOADPROJECT 40115 +#define ID_MISC_FINDBRUSH 40116 +#define ID_MISC_NEXTLEAKSPOT 40117 +#define ID_MISC_PREVIOUSLEAKSPOT 40118 +#define ID_BRUSH_3SIDED 40119 +#define ID_BRUSH_4SIDED 40120 +#define ID_BRUSH_5SIDED 40121 +#define ID_BRUSH_6SIDED 40122 +#define ID_BRUSH_7SIDED 40123 +#define ID_BRUSH_8SIDED 40124 +#define ID_BRUSH_9SIDED 40125 +#define ID_SELECTION_ARBITRARYROTATION 40126 +#define ID_BRUSH_ARBITRARYSIDED 40127 +#define ID_GRID_32 40128 +#define ID_GRID_64 40129 +#define ID_SELECTION_UNGROUPENTITY 40130 +#define ID_MISC_SELECTENTITYCOLOR 40131 +#define ID_MISC_PRINTXY 40132 +#define ID_HELP_ABOUT 40134 +#define ID_EDIT_COPYBRUSH 40135 +#define ID_EDIT_PASTEBRUSH 40136 +#define ID_TEXTURES_INSPECTOR 40137 +#define ID_VIEW_SHOWDETAIL 40138 +#define ID_SELECTION_MAKE_DETAIL 40139 +#define ID_SELECTION_MAKE_STRUCTURAL 40140 +#define ID_REGION_SETSELECTION 40142 +#define ID_VIEW_SHOWBLOCKS 40143 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 40144 +#define _APS_NEXT_CONTROL_VALUE 1115 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/tools/quake2/extra/qe4/select.c b/tools/quake2/extra/qe4/select.c new file mode 100644 index 00000000..2761ecb3 --- /dev/null +++ b/tools/quake2/extra/qe4/select.c @@ -0,0 +1,706 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// select.c + +#include "qe3.h" + +/* +=========== +Test_Ray +=========== +*/ +#define DIST_START 999999 +trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags) +{ + brush_t *brush; + face_t *face; + float dist; + trace_t t; + + memset (&t, 0, sizeof(t)); + t.dist = DIST_START; + + if (! (flags & SF_SELECTED_ONLY) ) + for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) + { + if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) + continue; + if (FilterBrush (brush)) + continue; + face = Brush_Ray (origin, dir, brush, &dist); + if (dist > 0 && dist < t.dist) + { + t.dist = dist; + t.brush = brush; + t.face = face; + t.selected = false; + } + } + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + { + if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) + continue; + if (FilterBrush (brush)) + continue; + face = Brush_Ray (origin, dir, brush, &dist); + if (dist > 0 && dist < t.dist) + { + t.dist = dist; + t.brush = brush; + t.face = face; + t.selected = true; + } + } + + // if entites first, but didn't find any, check regular + + if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL) + return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST); + + return t; +} + + +/* +============ +Select_Brush + +============ +*/ +void Select_Brush (brush_t *brush) +{ + brush_t *b; + entity_t *e; + + selected_face = NULL; + if (g_qeglobals.d_select_count < 2) + g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush; + g_qeglobals.d_select_count++; + + e = brush->owner; + if (e) + { + // select complete entity on first click + if (e != world_entity) + { + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + if (b->owner == e) + goto singleselect; + for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + else + { +singleselect: + Brush_RemoveFromList (brush); + Brush_AddToList (brush, &selected_brushes); + } + + if (e->eclass) + { + UpdateEntitySel(brush->owner->eclass); + } + } +} + +/* +============ +Select_Ray + +If the origin is inside a brush, that brush will be ignored. +============ +*/ +void Select_Ray (vec3_t origin, vec3_t dir, int flags) +{ + trace_t t; + + t = Test_Ray (origin, dir, flags); + if (!t.brush) + return; + + if (flags == SF_SINGLEFACE) + { + selected_face = t.face; + selected_face_brush = t.brush; + Sys_UpdateWindows (W_ALL); + g_qeglobals.d_select_mode = sel_brush; + return; + } + + // move the brush to the other list + + g_qeglobals.d_select_mode = sel_brush; + + if (t.selected) + { + Brush_RemoveFromList (t.brush); + Brush_AddToList (t.brush, &active_brushes); + } else + { + Select_Brush (t.brush); + } + + Sys_UpdateWindows (W_ALL); +} + + +void Select_Delete (void) +{ + brush_t *brush; + + selected_face = NULL; + g_qeglobals.d_select_mode = sel_brush; + + g_qeglobals.d_select_count = 0; + g_qeglobals.d_num_move_points = 0; + while (selected_brushes.next != &selected_brushes) + { + brush = selected_brushes.next; + Brush_Free (brush); + } + + // FIXME: remove any entities with no brushes + + Sys_UpdateWindows (W_ALL); +} + +void Select_Deselect (void) +{ + brush_t *b; + + g_qeglobals.d_workcount++; + g_qeglobals.d_select_count = 0; + g_qeglobals.d_num_move_points = 0; + b = selected_brushes.next; + + if (b == &selected_brushes) + { + if (selected_face) + { + selected_face = NULL; + Sys_UpdateWindows (W_ALL); + } + return; + } + + selected_face = NULL; + g_qeglobals.d_select_mode = sel_brush; + + // grab top / bottom height for new brushes + if (b->mins[2] < b->maxs[2]) + { + g_qeglobals.d_new_brush_bottom_z = b->mins[2]; + g_qeglobals.d_new_brush_top_z = b->maxs[2]; + } + + selected_brushes.next->prev = &active_brushes; + selected_brushes.prev->next = active_brushes.next; + active_brushes.next->prev = selected_brushes.prev; + active_brushes.next = selected_brushes.next; + selected_brushes.prev = selected_brushes.next = &selected_brushes; + + Sys_UpdateWindows (W_ALL); +} + +/* +============ +Select_Move +============ +*/ +void Select_Move (vec3_t delta) +{ + brush_t *b; + +// actually move the selected brushes + for (b = selected_brushes.next ; b != &selected_brushes ; b=b->next) + Brush_Move (b, delta); +// Sys_UpdateWindows (W_ALL); +} + +/* +============ +Select_Clone + +Creates an exact duplicate of the selection in place, then moves +the selected brushes off of their old positions +============ +*/ +void Select_Clone (void) +{ + brush_t *b, *b2, *n, *next, *next2; + vec3_t delta; + entity_t *e; + + g_qeglobals.d_workcount++; + g_qeglobals.d_select_mode = sel_brush; + + delta[0] = g_qeglobals.d_gridsize; + delta[1] = g_qeglobals.d_gridsize; + delta[2] = 0; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=next) + { + next = b->next; + // if the brush is a world brush, handle simply + if (b->owner == world_entity) + { + n = Brush_Clone (b); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (world_entity, n); + Brush_Build( n ); + Brush_Move (b, delta); + continue; + } + + e = Entity_Clone (b->owner); + // clear the target / targetname + DeleteKey (e, "target"); + DeleteKey (e, "targetname"); + + // if the brush is a fixed size entity, create a new entity + if (b->owner->eclass->fixedsize) + { + n = Brush_Clone (b); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (e, n); + Brush_Build( n ); + Brush_Move (b, delta); + continue; + } + + // brush is a complex entity, grab all the other ones now + + next = &selected_brushes; + + for ( b2 = b ; b2 != &selected_brushes ; b2=next2) + { + next2 = b2->next; + if (b2->owner != b->owner) + { + if (next == &selected_brushes) + next = b2; + continue; + } + + // move b2 to the start of selected_brushes, + // so it won't be hit again + Brush_RemoveFromList (b2); + Brush_AddToList (b2, &selected_brushes); + + n = Brush_Clone (b2); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (e, n); + Brush_Build( n ); + Brush_Move (b2, delta); + } + + } + Sys_UpdateWindows (W_ALL); +} + + + +/* +============ +Select_SetTexture +============ +*/ +void Select_SetTexture (texdef_t *texdef) +{ + brush_t *b; + + if (selected_face) + { + selected_face->texdef = *texdef; + Brush_Build(selected_face_brush); + } + else + { + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + if (!b->owner->eclass->fixedsize) + Brush_SetTexture (b, texdef); + } + Sys_UpdateWindows (W_ALL); +} + + +/* +================================================================ + + TRANSFORMATIONS + +================================================================ +*/ + +void Select_GetBounds (vec3_t mins, vec3_t maxs) +{ + brush_t *b; + int i; + + for (i=0 ; i<3 ; i++) + { + mins[i] = 99999; + maxs[i] = -99999; + } + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (i=0 ; i<3 ; i++) + { + if (b->mins[i] < mins[i]) + mins[i] = b->mins[i]; + if (b->maxs[i] > maxs[i]) + maxs[i] = b->maxs[i]; + } +} + +void Select_GetMid (vec3_t mid) +{ + vec3_t mins, maxs; + int i; + + Select_GetBounds (mins, maxs); + for (i=0 ; i<3 ; i++) + mid[i] = g_qeglobals.d_gridsize*floor ( ( (mins[i] + maxs[i])*0.5 )/g_qeglobals.d_gridsize ); +} + +vec3_t select_origin; +vec3_t select_matrix[3]; +qboolean select_fliporder; + +void Select_AplyMatrix (void) +{ + brush_t *b; + face_t *f; + int i, j; + vec3_t temp; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (f=b->brush_faces ; f ; f=f->next) + { + for (i=0 ; i<3 ; i++) + { + VectorSubtract (f->planepts[i], select_origin, temp); + for (j=0 ; j<3 ; j++) + f->planepts[i][j] = DotProduct(temp, select_matrix[j]) + + select_origin[j]; + } + if (select_fliporder) + { + VectorCopy (f->planepts[0], temp); + VectorCopy (f->planepts[2], f->planepts[0]); + VectorCopy (temp, f->planepts[2]); + } + } + Brush_Build( b ); + } + Sys_UpdateWindows (W_ALL); +} + + +void Select_FlipAxis (int axis) +{ + int i; + + Select_GetMid (select_origin); + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + select_matrix[axis][axis] = -1; + + select_fliporder = true; + Select_AplyMatrix (); +} + +void Select_RotateAxis (int axis, float deg) +{ + vec3_t temp; + int i, j; + vec_t c, s; + + if (deg == 0) + return; + + Select_GetMid (select_origin); + select_fliporder = false; + + if (deg == 90) + { + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + i = (axis+1)%3; + j = (axis+2)%3; + VectorCopy (select_matrix[i], temp); + VectorCopy (select_matrix[j], select_matrix[i]); + VectorSubtract (vec3_origin, temp, select_matrix[j]); + } + else + { + deg = -deg; + if (deg == -180) + { + c = -1; + s = 0; + } + else if (deg == -270) + { + c = 0; + s = -1; + } + else + { + c = cos(deg/180*3.14159); + s = sin (deg/180*3.14159); + } + + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + + switch (axis) + { + case 0: + select_matrix[1][1] = c; + select_matrix[1][2] = -s; + select_matrix[2][1] = s; + select_matrix[2][2] = c; + break; + case 1: + select_matrix[0][0] = c; + select_matrix[0][2] = s; + select_matrix[2][0] = -s; + select_matrix[2][2] = c; + break; + case 2: + select_matrix[0][0] = c; + select_matrix[0][1] = -s; + select_matrix[1][0] = s; + select_matrix[1][1] = c; + break; + } + } + + Select_AplyMatrix (); +} + +/* +================================================================ + +GROUP SELECTIONS + +================================================================ +*/ + +void Select_CompleteTall (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + g_qeglobals.d_select_mode = sel_brush; + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + for (i=0 ; i<2 ; i++) + if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) + break; + if (i == 2) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +void Select_PartialTall (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + g_qeglobals.d_select_mode = sel_brush; + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + for (i=0 ; i<2 ; i++) + if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i]) + break; + if (i == 2) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +void Select_Touching (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + g_qeglobals.d_select_mode = sel_brush; + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + for (i=0 ; i<3 ; i++) + if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1) + break; + if (i == 3) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +void Select_Inside (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + g_qeglobals.d_select_mode = sel_brush; + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + for (i=0 ; i<3 ; i++) + if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) + break; + if (i == 3) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +/* +============= +Select_Ungroup + +Turn the currently selected entity back into normal brushes +============= +*/ +void Select_Ungroup (void) +{ + entity_t *e; + brush_t *b; + + e = selected_brushes.next->owner; + + if (!e || e == world_entity || e->eclass->fixedsize) + { + Sys_Status ("Not a grouped entity.", 0); + return; + } + + for (b=e->brushes.onext ; b != &e->brushes ; b=e->brushes.onext) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &active_brushes); + Entity_UnlinkBrush (b); + Entity_LinkBrush (world_entity, b); + Brush_Build( b ); + b->owner = world_entity; + } + + Entity_Free (e); + Sys_UpdateWindows (W_ALL); +} + +/* +==================== +Select_MakeStructural +==================== +*/ +void Select_MakeStructural (void) +{ + brush_t *b; + face_t *f; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + f->texdef.contents &= ~CONTENTS_DETAIL; + Select_Deselect (); + Sys_UpdateWindows (W_ALL); +} + +void Select_MakeDetail (void) +{ + brush_t *b; + face_t *f; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + f->texdef.contents |= CONTENTS_DETAIL; + Select_Deselect (); + Sys_UpdateWindows (W_ALL); +} + + diff --git a/tools/quake2/extra/qe4/select.h b/tools/quake2/extra/qe4/select.h new file mode 100644 index 00000000..003902a2 --- /dev/null +++ b/tools/quake2/extra/qe4/select.h @@ -0,0 +1,62 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +typedef enum +{ + sel_brush, + // sel_sticky_brush, + // sel_face, + sel_vertex, + sel_edge +} select_t; + +typedef struct +{ + brush_t *brush; + face_t *face; + float dist; + qboolean selected; +} trace_t; + +#define SF_SELECTED_ONLY 1 +#define SF_ENTITIES_FIRST 2 +#define SF_SINGLEFACE 4 + + +trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags); + +void Select_GetBounds (vec3_t mins, vec3_t maxs); +void Select_Brush (brush_t *b); +void Select_Ray (vec3_t origin, vec3_t dir, int flags); +void Select_Delete (void); +void Select_Deselect (void); +void Select_Clone (void); +void Select_Move (vec3_t delta); +void Select_SetTexture (texdef_t *texdef); +void Select_FlipAxis (int axis); +void Select_RotateAxis (int axis, float deg); +void Select_CompleteTall (void); +void Select_PartialTall (void); +void Select_Touching (void); +void Select_Inside (void); +void Select_MakeStructural (void); +void Select_MakeDetail (void); diff --git a/tools/quake2/extra/qe4/textures.c b/tools/quake2/extra/qe4/textures.c new file mode 100644 index 00000000..21fa8ce0 --- /dev/null +++ b/tools/quake2/extra/qe4/textures.c @@ -0,0 +1,1147 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" +#include "io.h" + +#define TYP_MIPTEX 68 +static unsigned tex_palette[256]; + +static qtexture_t *notexture; + +static qboolean nomips; + +#define FONT_HEIGHT 10 + +static HGLRC s_hglrcTexture; +static HDC s_hdcTexture; + +//int texture_mode = GL_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; +//int texture_mode = GL_LINEAR; +//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; +int texture_mode = GL_LINEAR_MIPMAP_LINEAR; + +int texture_extension_number = 1; + +// current active texture directory. if empty, show textures in use +char texture_directory[32]; // use if texture_showinuse is false +qboolean texture_showinuse; + +// texture layout functions +qtexture_t *current_texture; +int current_x, current_y, current_row; + +int texture_nummenus; +#define MAX_TEXTUREDIRS 100 +char texture_menunames[MAX_TEXTUREDIRS][64]; + +qboolean g_dontuse; // set to true to load the texture but not flag as used + +void SelectTexture (int mx, int my); + +void Texture_MouseDown (int x, int y, int buttons); +void Texture_MouseUp (int x, int y, int buttons); +void Texture_MouseMoved (int x, int y, int buttons); + +//===================================================== + +void SortTextures(void) +{ + qtexture_t *q, *qtemp, *qhead, *qcur, *qprev; + + // standard insertion sort + // Take the first texture from the list and + // add it to our new list + if ( g_qeglobals.d_qtextures == NULL) + return; + + qhead = g_qeglobals.d_qtextures; + q = g_qeglobals.d_qtextures->next; + qhead->next = NULL; + + // while there are still things on the old + // list, keep adding them to the new list + while (q) + { + qtemp = q; + q = q->next; + + qprev = NULL; + qcur = qhead; + + while (qcur) + { + // Insert it here? + if (strcmp(qtemp->name, qcur->name) < 0) + { + qtemp->next = qcur; + if (qprev) + qprev->next = qtemp; + else + qhead = qtemp; + break; + } + + // Move on + + qprev = qcur; + qcur = qcur->next; + + + // is this one at the end? + + if (qcur == NULL) + { + qprev->next = qtemp; + qtemp->next = NULL; + } + } + + + } + + g_qeglobals.d_qtextures = qhead; +} + +//===================================================== + + +/* +============== +Texture_InitPalette +============== +*/ +void Texture_InitPalette (byte *pal) +{ + int r,g,b,v; + int i; + int inf; + byte gammatable[256]; + float gamma; + + gamma = g_qeglobals.d_savedinfo.fGamma; + + if (gamma == 1.0) + { + for (i=0 ; i<256 ; i++) + gammatable[i] = i; + } + else + { + for (i=0 ; i<256 ; i++) + { + inf = 255 * pow ( (i+0.5)/255.5 , gamma ) + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + gammatable[i] = inf; + } + } + + for (i=0 ; i<256 ; i++) + { + r = gammatable[pal[0]]; + g = gammatable[pal[1]]; + b = gammatable[pal[2]]; + pal += 3; + + v = (r<<24) + (g<<16) + (b<<8) + 255; + v = BigLong (v); + + tex_palette[i] = v; + } +} + +void SetTexParameters (void) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode ); + + switch ( texture_mode ) + { + case GL_NEAREST: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + break; + case GL_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + break; + } +} + +/* +============ +Texture_SetMode +============ +*/ +void Texture_SetMode(int iMenu) +{ + int i, iMode; + HMENU hMenu; + qboolean texturing = true; + + hMenu = GetMenu(g_qeglobals.d_hwndMain); + + switch(iMenu) { + case ID_VIEW_NEAREST: + iMode = GL_NEAREST; + break; + case ID_VIEW_NEARESTMIPMAP: + iMode = GL_NEAREST_MIPMAP_NEAREST; + break; + case ID_VIEW_LINEAR: + iMode = GL_NEAREST_MIPMAP_LINEAR; + break; + case ID_VIEW_BILINEAR: + iMode = GL_LINEAR; + break; + case ID_VIEW_BILINEARMIPMAP: + iMode = GL_LINEAR_MIPMAP_NEAREST; + break; + case ID_VIEW_TRILINEAR: + iMode = GL_LINEAR_MIPMAP_LINEAR; + break; + + case ID_TEXTURES_WIREFRAME: + iMode = 0; + texturing = false; + break; + + case ID_TEXTURES_FLATSHADE: + iMode = 0; + texturing = false; + break; + + } + + CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED); + + CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED); + + g_qeglobals.d_savedinfo.iTexMenu = iMenu; + texture_mode = iMode; + if ( texturing ) + SetTexParameters (); + + if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME) + { + camera.draw_mode = cd_wire; + Map_BuildBrushData(); + Sys_UpdateWindows (W_ALL); + return; + + } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) { + + camera.draw_mode = cd_solid; + Map_BuildBrushData(); + Sys_UpdateWindows (W_ALL); + return; + } + + for (i=1 ; iwidth); + height = LittleLong(qtex->height); + + q->width = width; + q->height = height; + + q->flags = qtex->flags; + q->value = qtex->value; + q->contents = qtex->contents; + + dest = qmalloc (width*height*4); + + count = width*height; + source = (byte *)qtex + LittleLong(qtex->offsets[0]); + + // The dib is upside down so we want to copy it into + // the buffer bottom up. + + total[0] = total[1] = total[2] = 0; + for (i=0 ; icolor[0] = (float)total[0]/(count*255); + q->color[1] = (float)total[1]/(count*255); + q->color[2] = (float)total[2]/(count*255); + + q->texture_number = texture_extension_number++; + + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + SetTexParameters (); + + if (nomips) + glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest); + else + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest); + + free (dest); + + glBindTexture( GL_TEXTURE_2D, 0 ); + + return q; +} + +/* +=============== +Texture_CreateSolid + +Create a single pixel texture of the apropriate color +=============== +*/ +qtexture_t *Texture_CreateSolid (char *name) +{ + byte data[4]; + qtexture_t *q; + + q = qmalloc(sizeof(*q)); + + sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]); + + data[0] = q->color[0]*255; + data[1] = q->color[1]*255; + data[2] = q->color[2]*255; + data[3] = 255; + + q->width = q->height = 1; + q->texture_number = texture_extension_number++; + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + SetTexParameters (); + + if (nomips) + glTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + else + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data); + + glBindTexture( GL_TEXTURE_2D, 0 ); + + return q; +} + + +/* +================= +Texture_MakeNotexture +================= +*/ +void Texture_MakeNotexture (void) +{ + qtexture_t *q; + byte data[4][4]; + + notexture = q = qmalloc(sizeof(*q)); + strcpy (q->name, "notexture"); + q->width = q->height = 64; + + memset (data, 0, sizeof(data)); + data[0][2] = data[3][2] = 255; + + q->color[0] = 0; + q->color[1] = 0; + q->color[2] = 0.5; + + q->texture_number = texture_extension_number++; + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + SetTexParameters (); + + if (nomips) + glTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + else + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data); + + glBindTexture( GL_TEXTURE_2D, 0 ); +} + + + +/* +=============== +Texture_ForName +=============== +*/ +qtexture_t *Texture_ForName (char *name) +{ + byte *lump; + qtexture_t *q; + char filename[1024]; + +//return notexture; + for (q=g_qeglobals.d_qtextures ; q ; q=q->next) + { + if (!strcmp(name, q->name)) + { + if (!g_dontuse) + q->inuse = true; + return q; + } + } + + if (name[0] == '(') + { + q = Texture_CreateSolid (name); + strncpy (q->name, name, sizeof(q->name)-1); + } + else + { + // load the file + sprintf (filename, "%s/%s.wal", + ValueForKey (g_qeglobals.d_project_entity, "texturepath"), + name); + Sys_Printf ("Loading %s\n", name); + if (LoadFile (filename, &lump) == -1) + { + Sys_Printf (" load failed!\n"); + return notexture; + } + q = Texture_LoadTexture ((miptex_t *)lump); + free (lump); + strncpy (q->name, name, sizeof(q->name)-1); + StripExtension (q->name); + } + + if (!g_dontuse) + q->inuse = true; + q->next = g_qeglobals.d_qtextures; + g_qeglobals.d_qtextures = q; + + return q; +} + +/* +================== +FillTextureMenu + +================== +*/ +void FillTextureMenu (void) +{ + HMENU hmenu; + int i; + struct _finddata_t fileinfo; + int handle; + char dirstring[1024]; + char *path; + + hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE); + + // delete everything + for (i=0 ; inext) + { + q->inuse = false; + } +} + + + +/* +============== +Texture_ShowDirectory +============== +*/ +void Texture_ShowDirectory (int menunum) +{ + struct _finddata_t fileinfo; + int handle; + char name[1024]; + char dirstring[1024]; + + texture_showinuse = false; + strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]); + + g_qeglobals.d_texturewin.originy = 0; + Sys_Status("loading all textures\n", 0); + + // load all .wal files + sprintf (dirstring, "%s/textures/%s*.wal", + ValueForKey (g_qeglobals.d_project_entity, "basepath"), + texture_menunames[menunum-CMD_TEXTUREWAD]); + + Sys_Printf ("Scanning %s\n", dirstring); + + handle = _findfirst (dirstring, &fileinfo); + if (handle == -1) + return; + + g_dontuse = true; + do + { + sprintf (name, "%s%s", texture_directory, fileinfo.name); + StripExtension (name); + Texture_ForName (name); + } while (_findnext( handle, &fileinfo ) != -1); + g_dontuse = false; + + _findclose (handle); + + SortTextures(); + SetInspectorMode(W_TEXTURE); + Sys_UpdateWindows(W_TEXTURE); + + sprintf (name, "Textures: %s", texture_directory); + SetWindowText(g_qeglobals.d_hwndEntity, name); + + // select the first texture in the list + if (!g_qeglobals.d_texturewin.texdef.name[0]) + SelectTexture (16, g_qeglobals.d_texturewin.height -16); +} + +/* +============== +Texture_ShowInuse +============== +*/ +void Texture_ShowInuse (void) +{ + char name[1024]; + face_t *f; + brush_t *b; + + texture_showinuse = true; + + g_qeglobals.d_texturewin.originy = 0; + Sys_Status("Selecting active textures\n", 0); + Texture_ClearInuse (); + + for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + Texture_ForName (f->texdef.name); + + for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + Texture_ForName (f->texdef.name); + + SortTextures(); + SetInspectorMode(W_TEXTURE); + Sys_UpdateWindows (W_TEXTURE); + + sprintf (name, "Textures: in use"); + SetWindowText(g_qeglobals.d_hwndEntity, name); + + // select the first texture in the list + if (!g_qeglobals.d_texturewin.texdef.name[0]) + SelectTexture (16, g_qeglobals.d_texturewin.height -16); +} + +/* +============================================================================ + +TEXTURE LAYOUT + +============================================================================ +*/ + +void Texture_StartPos (void) +{ + current_texture = g_qeglobals.d_qtextures; + current_x = 8; + current_y = -8; + current_row = 0; +} + +qtexture_t *Texture_NextPos (int *x, int *y) +{ + qtexture_t *q; + + while (1) + { + q = current_texture; + if (!q) + return q; + current_texture = current_texture->next; + if (q->name[0] == '(') // fake color texture + continue; + if (q->inuse) + break; // allways show in use + if (!texture_showinuse && strncmp (q->name, texture_directory, strlen(texture_directory))) + continue; + break; + } + + if (current_x + q->width > g_qeglobals.d_texturewin.width-8 && current_row) + { // go to the next row unless the texture is the first on the row + current_x = 8; + current_y -= current_row + FONT_HEIGHT + 4; + current_row = 0; + } + + *x = current_x; + *y = current_y; + + // Is our texture larger than the row? If so, grow the + // row height to match it + + if (current_row < q->height) + current_row = q->height; + + // never go less than 64, or the names get all crunched up + current_x += q->width < 64 ? 64 : q->width; + current_x += 8; + + return q; +} + +/* +============================================================================ + + MOUSE ACTIONS + +============================================================================ +*/ + +static int textures_cursorx, textures_cursory; + + +/* +============ +Texture_SetTexture + +============ +*/ +void Texture_SetTexture (texdef_t *texdef) +{ + qtexture_t *q; + int x,y; + char sz[256]; + + if (texdef->name[0] == '(') + { + Sys_Status("Can't select an entity texture\n", 0); + return; + } + g_qeglobals.d_texturewin.texdef = *texdef; + + Sys_UpdateWindows (W_TEXTURE); + sprintf(sz, "Selected texture: %s\n", texdef->name); + Sys_Status(sz, 0); + Select_SetTexture(texdef); + +// scroll origin so the texture is completely on screen + Texture_StartPos (); + while (1) + { + q = Texture_NextPos (&x, &y); + if (!q) + break; + if (!strcmpi(texdef->name, q->name)) + { + if (y > g_qeglobals.d_texturewin.originy) + { + g_qeglobals.d_texturewin.originy = y; + Sys_UpdateWindows (W_TEXTURE); + return; + } + + if (y-q->height-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height) + { + g_qeglobals.d_texturewin.originy = y-q->height-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height; + Sys_UpdateWindows (W_TEXTURE); + return; + } + + return; + } + } +} + + +/* +============== +SelectTexture + + By mouse click +============== +*/ +void SelectTexture (int mx, int my) +{ + int x, y; + qtexture_t *q; + texdef_t tex; + + my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height; + + Texture_StartPos (); + while (1) + { + q = Texture_NextPos (&x, &y); + if (!q) + break; + if (mx > x && mx - x < q->width + && my < y && y - my < q->height + FONT_HEIGHT) + { + memset (&tex, 0, sizeof(tex)); + tex.scale[0] = 1; + tex.scale[1] = 1; + tex.flags = q->flags; + tex.value = q->value; + tex.contents = q->contents; + strcpy (tex.name, q->name); + Texture_SetTexture (&tex); + return; + } + } + + Sys_Status("Did not select a texture\n", 0); +} + +/* +============== +Texture_MouseDown +============== +*/ +void Texture_MouseDown (int x, int y, int buttons) +{ + Sys_GetCursorPos (&textures_cursorx, &textures_cursory); + + // lbutton = select texture + if (buttons == MK_LBUTTON ) + { + SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y); + return; + } + +} + +/* +============== +Texture_MouseUp +============== +*/ +void Texture_MouseUp (int x, int y, int buttons) +{ +} + +/* +============== +Texture_MouseMoved +============== +*/ +void Texture_MouseMoved (int x, int y, int buttons) +{ + int scale = 1; + + if ( buttons & MK_SHIFT ) + scale = 4; + + // rbutton = drag texture origin + if (buttons & MK_RBUTTON) + { + Sys_GetCursorPos (&x, &y); + if ( y != textures_cursory) + { + g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale; + if (g_qeglobals.d_texturewin.originy > 0) + g_qeglobals.d_texturewin.originy = 0; + Sys_SetCursorPos (textures_cursorx, textures_cursory); + Sys_UpdateWindows (W_TEXTURE); + } + return; + } +} + + +/* +============================================================================ + +DRAWING + +============================================================================ +*/ + +int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; } +HFONT ghFont = NULL; + +/* +============ +Texture_Draw2 +============ +*/ +void Texture_Draw2 (int width, int height) +{ + qtexture_t *q; + int x, y; + char *name; + + glClearColor ( + g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0], + g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1], + g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2], + 0); + glViewport (0,0,width,height); + glClear (GL_COLOR_BUFFER_BIT); + glDisable (GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glLoadIdentity (); + glOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100); + glEnable (GL_TEXTURE_2D); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + g_qeglobals.d_texturewin.width = width; + g_qeglobals.d_texturewin.height = height; + Texture_StartPos (); + + while (1) + { + q = Texture_NextPos (&x, &y); + if (!q) + break; + + // Is this texture visible? + if ( (y-q->height-FONT_HEIGHT < g_qeglobals.d_texturewin.originy) + && (y > g_qeglobals.d_texturewin.originy - height) ) + { + + // if in use, draw a background + if (q->inuse && !texture_showinuse) + { + glLineWidth (1); + glColor3f (0.5,1,0.5); + glDisable (GL_TEXTURE_2D); + + glBegin (GL_LINE_LOOP); + glVertex2f (x-1,y+1-FONT_HEIGHT); + glVertex2f (x-1,y-q->height-1-FONT_HEIGHT); + glVertex2f (x+1+q->width,y-q->height-1-FONT_HEIGHT); + glVertex2f (x+1+q->width,y+1-FONT_HEIGHT); + glEnd (); + + glEnable (GL_TEXTURE_2D); + } + + // Draw the texture + glColor3f (1,1,1); + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + glBegin (GL_QUADS); + glTexCoord2f (0,0); + glVertex2f (x,y-FONT_HEIGHT); + glTexCoord2f (1,0); + glVertex2f (x+q->width,y-FONT_HEIGHT); + glTexCoord2f (1,1); + glVertex2f (x+q->width,y-FONT_HEIGHT-q->height); + glTexCoord2f (0,1); + glVertex2f (x,y-FONT_HEIGHT-q->height); + glEnd (); + + // draw the selection border + if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name)) + { + glLineWidth (3); + glColor3f (1,0,0); + glDisable (GL_TEXTURE_2D); + + glBegin (GL_LINE_LOOP); + glVertex2f (x-4,y-FONT_HEIGHT+4); + glVertex2f (x-4,y-FONT_HEIGHT-q->height-4); + glVertex2f (x+4+q->width,y-FONT_HEIGHT-q->height-4); + glVertex2f (x+4+q->width,y-FONT_HEIGHT+4); + glEnd (); + + glEnable (GL_TEXTURE_2D); + glLineWidth (1); + } + + // draw the texture name + glColor3f (0,0,0); + glRasterPos2f (x, y-FONT_HEIGHT+2); + + // don't draw the directory name + for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++) + ; + if (!*name) + name = q->name; + else + name++; + glCallLists (strlen(name), GL_UNSIGNED_BYTE, name); + } + } + + // reset the current texture + glBindTexture( GL_TEXTURE_2D, 0 ); + glFinish(); +} + +/* +============ +WTexWndProc +============ +*/ +LONG WINAPI WTex_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + int xPos, yPos; + RECT rect; + + GetClientRect(hWnd, &rect); + + switch (uMsg) + { + case WM_CREATE: + s_hdcTexture = GetDC(hWnd); + QEW_SetupPixelFormat(s_hdcTexture, false); + + if ( ( s_hglrcTexture = wglCreateContext( s_hdcTexture ) ) == 0 ) + Error( "wglCreateContext in WTex_WndProc failed" ); + + if (!wglMakeCurrent( s_hdcTexture, s_hglrcTexture )) + Error ("wglMakeCurrent in WTex_WndProc failed"); + + if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) ) + Error( "wglShareLists in WTex_WndProc failed" ); + + return 0; + + case WM_DESTROY: + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( s_hglrcTexture ); + ReleaseDC( hWnd, s_hdcTexture ); + return 0; + + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + + if ( !wglMakeCurrent( s_hdcTexture, s_hglrcTexture ) ) + Error ("wglMakeCurrent failed"); + Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top); + SwapBuffers(s_hdcTexture); + + EndPaint(hWnd, &ps); + } + return 0; + + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONDOWN: + SetCapture( g_qeglobals.d_hwndTexture ); + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + + Texture_MouseDown (xPos, yPos, wParam); + return 0; + + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONUP: + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + + Texture_MouseUp (xPos, yPos, wParam); + if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) + ReleaseCapture (); + return 0; + + case WM_MOUSEMOVE: + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + + Texture_MouseMoved (xPos, yPos, wParam); + return 0; + } + + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + + + +/* +================== +CreateTextureWindow + +We need to create a seperate window for the textures +in the inspector window, because we can't share +gl and gdi drawing in a single window +================== +*/ +#define TEXTURE_WINDOW_CLASS "QTEX" +HWND CreateTextureWindow (void) +{ + WNDCLASS wc; + HWND hwnd; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WTex_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = g_qeglobals.d_hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = TEXTURE_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Error ("WCam_Register: failed"); + + hwnd = CreateWindow (TEXTURE_WINDOW_CLASS , + "Texture View", + WS_BORDER|WS_CHILD|WS_VISIBLE, + 20, + 20, + 64, + 64, // size + + g_qeglobals.d_hwndEntity, // parent window + 0, // no menu + g_qeglobals.d_hInstance, + 0); + if (!hwnd) + Error ("Couldn't create texturewindow"); + + return hwnd; +} + +/* +================== +Texture_Flush +================== +*/ +void Texture_Flush (void) +{ +} + + +/* +================== +Texture_Init +================== +*/ +void Texture_Init (void) +{ + char name[1024]; + byte *pal; + + // load the palette + sprintf (name, "%s/pics/colormap.pcx", + ValueForKey (g_qeglobals.d_project_entity, "basepath")); + Load256Image (name, NULL, &pal, NULL, NULL); + if (!pal) + Error ("Couldn't load %s", name); + Texture_InitPalette (pal); + free (pal); + + // create the fallback texture + Texture_MakeNotexture (); + + g_qeglobals.d_qtextures = NULL; +} + diff --git a/tools/quake2/extra/qe4/textures.h b/tools/quake2/extra/qe4/textures.h new file mode 100644 index 00000000..e85353fc --- /dev/null +++ b/tools/quake2/extra/qe4/textures.h @@ -0,0 +1,70 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +typedef struct +{ + char name[32]; + float shift[2]; + float rotate; + float scale[2]; + int contents; + int flags; + int value; +} texdef_t; + + +typedef struct +{ + int width, height; + int originy; + texdef_t texdef; +} texturewin_t; + +typedef struct qtexture_s +{ + struct qtexture_s *next; + char name[64]; // includes partial directory and extension + int width, height; + int contents; + int flags; + int value; + int texture_number; // gl bind number + vec3_t color; // for flat shade mode + qboolean inuse; // true = is present on the level +} qtexture_t; + + +// a texturename of the form (0 0 0) will +// create a solid color texture + +void Texture_Init (void); +void Texture_Flush (void); +void Texture_ClearInuse (void); +void Texture_ShowInuse (void); +void Texture_ShowDirectory (int menunum); + +qtexture_t *Texture_ForName (char *name); + +void Texture_Init (void); +void Texture_SetTexture (texdef_t *texdef); + +void Texture_SetMode(int iMenu); // GL_TEXTURE_NEAREST, etc.. diff --git a/tools/quake2/extra/qe4/toolbar1.bmp b/tools/quake2/extra/qe4/toolbar1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f942898ba036cc606153f137daa2503e2cc489d7 GIT binary patch literal 1918 zcmb7^L2lbX3`JQZfCz7L1tF`Rqx;@Pt17Evc9~;z?Nj(jy@C7wpONIKfebSq{^4-Q zPf}8T{QNzHo4n-^(|h|5!wAVKB*GHFG^{EX3HvZy=(r8%-UUgoUA1@N!^&J!b;Q+W^u zl1!3a4B>|39BO#?nmx2l&}PJ|l;nf)o>!Ig02sSy;bnyQYs`}yj>{i6EcY`4Tbl?K zuoG|47UV2ZTHW(P&Bd5!#sFR}@diFCye52UifS)vz++x=o6;(E+8op*s|+-p;F*Rw zBSx}dH+xH*YnJkN^u>i&4)seVE=TFx^L=0E>|Rxc8crb%gTYp^VA@)F_jP>Y4T9k1 zGQ6oz2KVwEC9j(bEJ@KMRl`cIhCv-k7ED_kFS#rmZgYmE{reEFo8EX^R03q?hiV@% z4a2+4cg3E+&57zX6J$YA^`bOi9Jm^#_BL#zgbMZhESD_sOxV-1@wU)z7t?&5P31`z HI`RJlI#}rz literal 0 HcmV?d00001 diff --git a/tools/quake2/extra/qe4/vertsel.c b/tools/quake2/extra/qe4/vertsel.c new file mode 100644 index 00000000..613824f7 --- /dev/null +++ b/tools/quake2/extra/qe4/vertsel.c @@ -0,0 +1,245 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +int FindPoint (vec3_t point) +{ + int i, j; + + for (i=0 ; i 0.1) + break; + if (j == 3) + return i; + } + + VectorCopy (point, g_qeglobals.d_points[g_qeglobals.d_numpoints]); + g_qeglobals.d_numpoints++; + + return g_qeglobals.d_numpoints-1; +} + +int FindEdge (int p1, int p2, face_t *f) +{ + int i; + + for (i=0 ; inumpoints ; i++) + pnum[i] = FindPoint (w->points[i]); + for (i=0 ; inumpoints ; i++) + FindEdge (pnum[i], pnum[(i+1)%w->numpoints], f); + + free (w); +} + +void SetupVertexSelection (void) +{ + face_t *f; + brush_t *b; + + g_qeglobals.d_numpoints = 0; + g_qeglobals.d_numedges = 0; + if (!QE_SingleBrush()) + return; + b = selected_brushes.next; + for (f=b->brush_faces ; f ; f=f->next) + MakeFace (f); + + Sys_UpdateWindows (W_ALL); +} + + +void SelectFaceEdge (face_t *f, int p1, int p2) +{ + winding_t *w; + int i, j, k; + int pnum[128]; + + w = MakeFaceWinding (selected_brushes.next, f); + if (!w) + return; + for (i=0 ; inumpoints ; i++) + pnum[i] = FindPoint (w->points[i]); + for (i=0 ; inumpoints ; i++) + if (pnum[i] == p1 && pnum[(i+1)%w->numpoints] == p2) + { + VectorCopy (g_qeglobals.d_points[pnum[i]], f->planepts[0]); + VectorCopy (g_qeglobals.d_points[pnum[(i+1)%w->numpoints]], f->planepts[1]); + VectorCopy (g_qeglobals.d_points[pnum[(i+2)%w->numpoints]], f->planepts[2]); + for (j=0 ; j<3 ; j++) + { + for (k=0 ; k<3 ; k++) + { + f->planepts[j][k] = floor(f->planepts[j][k]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; + } + } + + AddPlanept (f->planepts[0]); + AddPlanept (f->planepts[1]); + break; + } + + if (i == w->numpoints) + Sys_Printf ("SelectFaceEdge: failed\n"); + free (w); +} + +void SelectVertex (int p1) +{ + brush_t *b; + winding_t *w; + int i, j, k; + face_t *f; + + b = selected_brushes.next; + for (f=b->brush_faces ; f ; f=f->next) + { + w = MakeFaceWinding (b, f); + if (!w) + continue; + for (i=0 ; inumpoints ; i++) + { + if (FindPoint (w->points[i]) == p1) + { + VectorCopy (w->points[(i+w->numpoints-1)%w->numpoints], f->planepts[0]); + VectorCopy (w->points[i], f->planepts[1]); + VectorCopy (w->points[(i+1)%w->numpoints], f->planepts[2]); + for (j=0 ; j<3 ; j++) + { + for (k=0 ; k<3 ; k++) + { + f->planepts[j][k] = floor(f->planepts[j][k]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; + } + } + + AddPlanept (f->planepts[1]); + break; + } + } + free (w); + } +} + +void SelectEdgeByRay (vec3_t org, vec3_t dir) +{ + int i, j, besti; + float d, bestd; + vec3_t mid, temp; + pedge_t *e; + + // find the edge closest to the ray + besti = -1; + bestd = 8; + + for (i=0 ; if1, e->p1, e->p2); + SelectFaceEdge (e->f2, e->p2, e->p1); +} + +void SelectVertexByRay (vec3_t org, vec3_t dir) +{ + int i, besti; + float d, bestd; + vec3_t temp; + + // find the point closest to the ray + besti = -1; + bestd = 8; + + for (i=0 ; inext; + if (e == &entities) + { + Sys_Status ("No such entity.", 0); + return; + } + } + } + + b = e->brushes.onext; + if (b == &e->brushes) + { + Sys_Status ("No such brush.", 0); + return; + } + while (brushnum--) + { + b=b->onext; + if (b == &e->brushes) + { + Sys_Status ("No such brush.", 0); + return; + } + } + + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + + + Sys_UpdateWindows (W_ALL); + for (i=0 ; i<3 ; i++) + g_qeglobals.d_xy.origin[i] = (b->mins[i] + b->maxs[i])/2; + + Sys_Status ("Selected.", 0); +} + +/* +================= +GetSelectionIndex +================= +*/ +void GetSelectionIndex (int *ent, int *brush) +{ + brush_t *b, *b2; + entity_t *entity; + + *ent = *brush = 0; + + b = selected_brushes.next; + if (b == &selected_brushes) + return; + + // find entity + if (b->owner != world_entity) + { + (*ent)++; + for (entity = entities.next ; entity != &entities + ; entity=entity->next, (*ent)++) + ; + } + + // find brush + for (b2=b->owner->brushes.onext + ; b2 != b && b2 != &b->owner->brushes + ; b2=b2->onext, (*brush)++) + ; +} + +BOOL CALLBACK FindBrushDlgProc ( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + char entstr[256]; + char brushstr[256]; + HWND h; + int ent, brush; + + switch (uMsg) + { + case WM_INITDIALOG: + // set entity and brush number + GetSelectionIndex (&ent, &brush); + sprintf (entstr, "%i", ent); + sprintf (brushstr, "%i", brush); + SetWindowText(GetDlgItem(hwndDlg, IDC_FIND_ENTITY), entstr); + SetWindowText(GetDlgItem(hwndDlg, IDC_FIND_BRUSH), brushstr); + + h = GetDlgItem(hwndDlg, IDC_FIND_ENTITY); + SetFocus (h); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + GetWindowText(GetDlgItem(hwndDlg, IDC_FIND_ENTITY), entstr, 255); + GetWindowText(GetDlgItem(hwndDlg, IDC_FIND_BRUSH), brushstr, 255); + SelectBrush (atoi(entstr), atoi(brushstr)); + EndDialog(hwndDlg, 1); + return TRUE; + + case IDCANCEL: + EndDialog(hwndDlg, 0); + return TRUE; + } + } + return FALSE; +} + + + +void DoFind(void) +{ + DialogBox(g_qeglobals.d_hInstance, (char *)IDD_FINDBRUSH, g_qeglobals.d_hwndMain, FindBrushDlgProc); +} + +/* +=================================================== + + ARBITRARY ROTATE + +=================================================== +*/ + + +BOOL CALLBACK RotateDlgProc ( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + char str[256]; + HWND h; + float v; + + switch (uMsg) + { + case WM_INITDIALOG: + h = GetDlgItem(hwndDlg, IDC_FIND_ENTITY); + SetFocus (h); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + + case IDOK: + GetWindowText(GetDlgItem(hwndDlg, IDC_ROTX), str, 255); + v = atof(str); + if (v) + Select_RotateAxis (0, v); + + GetWindowText(GetDlgItem(hwndDlg, IDC_ROTY), str, 255); + v = atof(str); + if (v) + Select_RotateAxis (1, v); + + GetWindowText(GetDlgItem(hwndDlg, IDC_ROTZ), str, 255); + v = atof(str); + if (v) + Select_RotateAxis (2, v); + + EndDialog(hwndDlg, 1); + return TRUE; + + case IDCANCEL: + EndDialog(hwndDlg, 0); + return TRUE; + } + } + + return FALSE; +} + + + +void DoRotate(void) +{ + DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ROTATE, g_qeglobals.d_hwndMain, RotateDlgProc); +} + +/* +=================================================== + + ARBITRARY SIDES + +=================================================== +*/ + + +BOOL CALLBACK SidesDlgProc ( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + char str[256]; + HWND h; + + switch (uMsg) + { + case WM_INITDIALOG: + h = GetDlgItem(hwndDlg, IDC_FIND_ENTITY); + SetFocus (h); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + + case IDOK: + GetWindowText(GetDlgItem(hwndDlg, IDC_SIDES), str, 255); + Brush_MakeSided (atoi(str)); + + EndDialog(hwndDlg, 1); + break; + + case IDCANCEL: + EndDialog(hwndDlg, 0); + break; + } + default: + return FALSE; + } +} + + + +void DoSides(void) +{ + DialogBox(g_qeglobals.d_hInstance, (char *)IDD_SIDES, g_qeglobals.d_hwndMain, SidesDlgProc); +} + +//====================================================================== + +/* +=================== +DoAbout +=================== +*/ +BOOL CALLBACK AboutDlgProc( HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam ) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + char renderer[1024]; + char version[1024]; + char vendor[1024]; + char extensions[4096]; + + sprintf( renderer, "Renderer:\t%s", glGetString( GL_RENDERER ) ); + sprintf( version, "Version:\t\t%s", glGetString( GL_VERSION ) ); + sprintf( vendor, "Vendor:\t\t%s", glGetString( GL_VENDOR ) ); + sprintf( extensions, "\n%s", glGetString( GL_EXTENSIONS ) ); + + SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLRENDERER ), renderer ); + SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLVERSION ), version ); + SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLVENDOR ), vendor ); + SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLEXTENSIONS ), extensions ); + } + return TRUE; + + case WM_CLOSE: + EndDialog( hwndDlg, 1 ); + return TRUE; + + case WM_COMMAND: + if ( LOWORD( wParam ) == IDOK ) + EndDialog(hwndDlg, 1); + return TRUE; + } + return FALSE; +} + +void DoAbout(void) +{ + DialogBox( g_qeglobals.d_hInstance, ( char * ) IDD_ABOUT, g_qeglobals.d_hwndMain, AboutDlgProc ); +} + + +/* +=================================================== + + SURFACE INSPECTOR + +=================================================== +*/ + +texdef_t g_old_texdef; +HWND g_surfwin; +qboolean g_changed_surface; + +int g_checkboxes[64] = { + IDC_CHECK1, IDC_CHECK2, IDC_CHECK3, IDC_CHECK4, + IDC_CHECK5, IDC_CHECK6, IDC_CHECK7, IDC_CHECK8, + IDC_CHECK9, IDC_CHECK10, IDC_CHECK11, IDC_CHECK12, + IDC_CHECK13, IDC_CHECK14, IDC_CHECK15, IDC_CHECK16, + IDC_CHECK17, IDC_CHECK18, IDC_CHECK19, IDC_CHECK20, + IDC_CHECK21, IDC_CHECK22, IDC_CHECK23, IDC_CHECK24, + IDC_CHECK25, IDC_CHECK26, IDC_CHECK27, IDC_CHECK28, + IDC_CHECK29, IDC_CHECK30, IDC_CHECK31, IDC_CHECK32, + + IDC_CHECK33, IDC_CHECK34, IDC_CHECK35, IDC_CHECK36, + IDC_CHECK37, IDC_CHECK38, IDC_CHECK39, IDC_CHECK40, + IDC_CHECK41, IDC_CHECK42, IDC_CHECK43, IDC_CHECK44, + IDC_CHECK45, IDC_CHECK46, IDC_CHECK47, IDC_CHECK48, + IDC_CHECK49, IDC_CHECK50, IDC_CHECK51, IDC_CHECK52, + IDC_CHECK53, IDC_CHECK54, IDC_CHECK55, IDC_CHECK56, + IDC_CHECK57, IDC_CHECK58, IDC_CHECK59, IDC_CHECK60, + IDC_CHECK61, IDC_CHECK62, IDC_CHECK63, IDC_CHECK64 + }; + +/* +============== +SetTexMods + +Set the fields to the current texdef +=============== +*/ +void SetTexMods(void) +{ + char sz[128]; + texdef_t *pt; + int i; + + pt = &g_qeglobals.d_texturewin.texdef; + + SendMessage (g_surfwin, WM_SETREDRAW, 0, 0); + + SetWindowText(GetDlgItem(g_surfwin, IDC_TEXTURE), pt->name); + + sprintf(sz, "%d", (int)pt->shift[0]); + SetWindowText(GetDlgItem(g_surfwin, IDC_HSHIFT), sz); + + sprintf(sz, "%d", (int)pt->shift[1]); + SetWindowText(GetDlgItem(g_surfwin, IDC_VSHIFT), sz); + + sprintf(sz, "%4.2f", pt->scale[0]); + SetWindowText(GetDlgItem(g_surfwin, IDC_HSCALE), sz); + + sprintf(sz, "%4.2f", pt->scale[1]); + SetWindowText(GetDlgItem(g_surfwin, IDC_VSCALE), sz); + + sprintf(sz, "%d", (int)pt->rotate); + SetWindowText(GetDlgItem(g_surfwin, IDC_ROTATE), sz); + + sprintf(sz, "%d", (int)pt->value); + SetWindowText(GetDlgItem(g_surfwin, IDC_VALUE), sz); + + for (i=0 ; i<32 ; i++) + SendMessage(GetDlgItem(g_surfwin, g_checkboxes[i]), BM_SETCHECK, !!(pt->flags&(1<contents&(1<name, sz, sizeof(pt->name)-1); + if (pt->name[0] <= ' ') + { + strcpy (pt->name, "none"); + SetWindowText(GetDlgItem(g_surfwin, IDC_TEXTURE), pt->name); + } + + GetWindowText (GetDlgItem(g_surfwin, IDC_HSHIFT), sz, 127); + pt->shift[0] = atof(sz); + + GetWindowText (GetDlgItem(g_surfwin, IDC_VSHIFT), sz, 127); + pt->shift[1] = atof(sz); + + GetWindowText(GetDlgItem(g_surfwin, IDC_HSCALE), sz, 127); + pt->scale[0] = atof(sz); + + GetWindowText(GetDlgItem(g_surfwin, IDC_VSCALE), sz, 127); + pt->scale[1] = atof(sz); + + GetWindowText(GetDlgItem(g_surfwin, IDC_ROTATE), sz, 127); + pt->rotate = atof(sz); + + GetWindowText(GetDlgItem(g_surfwin, IDC_VALUE), sz, 127); + pt->value = atof(sz); + + pt->flags = 0; + for (i=0 ; i<32 ; i++) + { + b = SendMessage(GetDlgItem(g_surfwin, g_checkboxes[i]), BM_GETCHECK, 0, 0); + if (b != 1 && b != 0) + continue; + pt->flags |= b<contents = 0; + for (i=0 ; i<32 ; i++) + { + b = SendMessage(GetDlgItem(g_surfwin, g_checkboxes[32+i]), BM_GETCHECK, 0, 0); + if (b != 1 && b != 0) + continue; + pt->contents |= b<rotate += 45; + else + pt->rotate -= 45; + + if (pt->rotate < 0) + pt->rotate += 360; + + if (pt->rotate >= 360) + pt->rotate -= 360; + } + + else if (hwnd == GetDlgItem(g_surfwin, IDC_HSCALEA)) + { + if (nScrollCode == SB_LINEDOWN) + pt->scale[0] -= 0.1; + else + pt->scale[0] += 0.1; + } + + else if (hwnd == GetDlgItem(g_surfwin, IDC_VSCALEA)) + { + if (nScrollCode == SB_LINEUP) + pt->scale[1] += 0.1; + else + pt->scale[1] -= 0.1; + } + + else if (hwnd == GetDlgItem(g_surfwin, IDC_HSHIFTA)) + { + if (nScrollCode == SB_LINEDOWN) + pt->shift[0] -= 8; + else + pt->shift[0] += 8; + } + + else if (hwnd == GetDlgItem(g_surfwin, IDC_VSHIFTA)) + { + if (nScrollCode == SB_LINEUP) + pt->shift[1] += 8; + else + pt->shift[1] -= 8; + } + + SetTexMods(); + g_changed_surface = true; + Select_SetTexture(pt); +} + + + +BOOL CALLBACK SurfaceDlgProc ( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter + ) +{ + switch (uMsg) + { + case WM_INITDIALOG: + g_surfwin = hwndDlg; + SetTexMods (); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + + case IDOK: + GetTexMods (); + EndDialog(hwndDlg, 1); + break; + + case IDAPPLY: + GetTexMods (); + InvalidateRect(g_qeglobals.d_hwndCamera, NULL, false); + UpdateWindow (g_qeglobals.d_hwndCamera); + break; + + case IDCANCEL: + g_qeglobals.d_texturewin.texdef = g_old_texdef; + if (g_changed_surface) + Select_SetTexture(&g_qeglobals.d_texturewin.texdef); + EndDialog(hwndDlg, 0); + break; + } + break; + + case WM_HSCROLL: + case WM_VSCROLL: + UpdateSpinners(uMsg, wParam, lParam); + InvalidateRect(g_qeglobals.d_hwndCamera, NULL, false); + UpdateWindow (g_qeglobals.d_hwndCamera); + return 0; + + default: + return FALSE; + } +} + + + +void DoSurface (void) +{ + // save current state for cancel + g_old_texdef = g_qeglobals.d_texturewin.texdef; + g_changed_surface = false; + + DialogBox(g_qeglobals.d_hInstance, (char *)IDD_SURFACE, g_qeglobals.d_hwndMain, SurfaceDlgProc); +} + diff --git a/tools/quake2/extra/qe4/win_ent.c b/tools/quake2/extra/qe4/win_ent.c new file mode 100644 index 00000000..74fa9589 --- /dev/null +++ b/tools/quake2/extra/qe4/win_ent.c @@ -0,0 +1,1137 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" +#include "entityw.h" + +int rgIds[EntLast] = { + IDC_E_LIST, + IDC_E_COMMENT, + IDC_CHECK1, + IDC_CHECK2, + IDC_CHECK3, + IDC_CHECK4, + IDC_CHECK5, + IDC_CHECK6, + IDC_CHECK7, + IDC_CHECK8, + IDC_CHECK9, + IDC_CHECK10, + IDC_CHECK11, + IDC_CHECK12, + IDC_E_PROPS, + IDC_E_0, + IDC_E_45, + IDC_E_90, + IDC_E_135, + IDC_E_180, + IDC_E_225, + IDC_E_270, + IDC_E_315, + IDC_E_UP, + IDC_E_DOWN, + IDC_E_DELPROP, + + IDC_STATIC_KEY, + IDC_E_KEY_FIELD, + IDC_STATIC_VALUE, + IDC_E_VALUE_FIELD, + + IDC_E_COLOR +}; + +HWND hwndEnt[EntLast]; + +int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE + +qboolean multiple_entities; + +entity_t *edit_entity; + +HWND CreateTextureWindow (void); + +BOOL CALLBACK EntityWndProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam); // second message parameter + +void SizeEntityDlg(int iWidth, int iHeight); +void AddProp(void); +void GetTexMods(void); + + +LRESULT (CALLBACK* OldFieldWindowProc) (HWND, UINT, WPARAM, LPARAM); +LRESULT (CALLBACK* OldEntityListWindowProc) (HWND, UINT, WPARAM, LPARAM); + +/* +========================= +FieldWndProc + +Just to handle tab and enter... +========================= +*/ +BOOL CALLBACK FieldWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_CHAR: + if (LOWORD(wParam) == VK_TAB) + return FALSE; + if (LOWORD(wParam) == VK_RETURN) + return FALSE; + if (LOWORD(wParam) == VK_ESCAPE) + { + SetFocus (g_qeglobals.d_hwndCamera); + return FALSE; + } + break; + + case WM_KEYDOWN: + if (LOWORD(wParam) == VK_TAB) + { + if (hwnd == hwndEnt[EntKeyField]) + { + SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)""); + SetFocus (hwndEnt[EntValueField]); + } + else + SetFocus (hwndEnt[EntKeyField]); + } + if (LOWORD(wParam) == VK_RETURN) + { + if (hwnd == hwndEnt[EntKeyField]) + { + SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)""); + SetFocus (hwndEnt[EntValueField]); + } + else + { + AddProp (); + SetFocus (g_qeglobals.d_hwndCamera); + } + } + break; +// case WM_NCHITTEST: + case WM_LBUTTONDOWN: + SetFocus (hwnd); + break; + } + return CallWindowProc (OldFieldWindowProc, hwnd, uMsg, wParam, lParam); +} + + +/* +========================= +EntityListWndProc + +Just to handle enter... +========================= +*/ +BOOL CALLBACK EntityListWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_KEYDOWN: + if (LOWORD(wParam) == VK_RETURN) + { + SendMessage ( g_qeglobals.d_hwndEntity, + WM_COMMAND, + (LBN_DBLCLK<<16) + IDC_E_LIST, + 0 ); + return 0; + } + break; + } + return CallWindowProc (OldEntityListWindowProc, hwnd, uMsg, wParam, lParam); +} + + +/* +================ +GetEntityControls + +Finds the controls from the dialog and +moves them to the window +================ +*/ +void GetEntityControls(HWND ghwndEntity) +{ + int i; + + for (i = 0; i < EntLast; i++) + { + if (i == EntList || i == EntProps || i == EntComment) + continue; + if (i == EntKeyField || i == EntValueField) + continue; + hwndEnt[i] = GetDlgItem(ghwndEntity, rgIds[i]); + if (hwndEnt[i]) + SetParent (hwndEnt[i], g_qeglobals.d_hwndEntity ); + } + + + // SetParent apears to not modify some internal state + // on listboxes, so create it from scratch... + + hwndEnt[EntList] = CreateWindow ("listbox", NULL, + LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT + | WS_VSCROLL | WS_CHILD | WS_VISIBLE, + 5, 5, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_LIST, + g_qeglobals.d_hInstance, + NULL); + if (!hwndEnt[EntList]) + Error ("CreateWindow failed"); + + hwndEnt[EntProps] = CreateWindow ("listbox", NULL, + LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS + | WS_VSCROLL | WS_CHILD | WS_VISIBLE, + 5, 100, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_PROPS, + g_qeglobals.d_hInstance, + NULL); + if (!hwndEnt[EntProps]) + Error ("CreateWindow failed"); + + hwndEnt[EntComment] = CreateWindow ("edit", NULL, + ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER, + 5, 100, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_COMMENT, + g_qeglobals.d_hInstance, + NULL); + if (!hwndEnt[EntComment]) + Error ("CreateWindow failed"); + + hwndEnt[EntKeyField] = CreateWindow ("edit", NULL, + WS_CHILD | WS_VISIBLE | WS_BORDER, + 5, 100, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_KEY_FIELD, + g_qeglobals.d_hInstance, + NULL); + if (!hwndEnt[EntKeyField]) + Error ("CreateWindow failed"); + + hwndEnt[EntValueField] = CreateWindow ("edit", NULL, + WS_CHILD | WS_VISIBLE | WS_BORDER, + 5, 100, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_VALUE_FIELD, + g_qeglobals.d_hInstance, + NULL); + if (!hwndEnt[EntValueField]) + Error ("CreateWindow failed"); + + g_qeglobals.d_hwndEdit = CreateWindow ("edit", NULL, + ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER, + 5, 100, 180, 99, + g_qeglobals.d_hwndEntity, + (void *)IDC_E_STATUS, + g_qeglobals.d_hInstance, + NULL); + if (!g_qeglobals.d_hwndEdit) + Error ("CreateWindow failed"); + + g_qeglobals.d_hwndTexture = CreateTextureWindow (); + +#if 0 + for (i=0 ; i<12 ; i++) + { + hwndEnt[EntCheck1 + i] = CreateWindow ("button", NULL, + BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, + 5, 100, 180, 99, + entwindow, + (void *)IDC_E_STATUS, + main_instance, + NULL); + if (!hwndEnt[EntCheck1 + i]) + Error ("CreateWindow failed"); + } +#endif +} + + + +/* +=============================================================== + +ENTITY WINDOW + +=============================================================== +*/ + + +void FillClassList (void) +{ + eclass_t *pec; + int iIndex; + + SendMessage(hwndEnt[EntList], LB_RESETCONTENT, 0 , 0); + + for (pec = eclass ; pec ; pec = pec->next) + { + iIndex = SendMessage(hwndEnt[EntList], LB_ADDSTRING, 0 , (LPARAM)pec->name); + SendMessage(hwndEnt[EntList], LB_SETITEMDATA, iIndex, (LPARAM)pec); + } + +} + + +/* +============== +WEnt_Create +============== +*/ +void WEnt_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)EntityWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = GetStockObject (LTGRAY_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = ENT_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Error ("RegisterClass: failed"); + + g_qeglobals.d_hwndEntity = CreateWindow (ENT_WINDOW_CLASS , + "Entity", + QE3_STYLE , + 20, + 20, + 100, + 480, // size + + g_qeglobals.d_hwndMain, // parent + 0, // no menu + hInstance, + NULL); + + if (!g_qeglobals.d_hwndEntity ) + Error ("Couldn't create Entity window"); +} + +/* +============== +CreateEntityWindow +============== +*/ +BOOL CreateEntityWindow(HINSTANCE hInstance) +{ + HWND hwndEntityPalette; + + inspector_mode = W_ENTITY; + + WEnt_Create (hInstance); + + hwndEntityPalette = CreateDialog(hInstance, (char *)IDD_ENTITY, g_qeglobals.d_hwndMain, (DLGPROC)NULL); + if (!hwndEntityPalette) + Error ("CreateDialog failed"); + + GetEntityControls (hwndEntityPalette); + DestroyWindow (hwndEntityPalette); + + OldFieldWindowProc = (void *)GetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC); + SetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC, (long)FieldWndProc); + SetWindowLong (hwndEnt[EntValueField], GWL_WNDPROC, (long)FieldWndProc); + + OldEntityListWindowProc = (void *)GetWindowLong (hwndEnt[EntList], GWL_WNDPROC); + SetWindowLong (hwndEnt[EntList], GWL_WNDPROC, (long)EntityListWndProc); + + FillClassList (); + + LoadWindowState(g_qeglobals.d_hwndEntity, "EntityWindow"); + + ShowWindow (g_qeglobals.d_hwndEntity, SW_SHOW); + SetInspectorMode (W_CONSOLE); + + return TRUE; +} + +/* +============== +SetInspectorMode +============== +*/ +void SetInspectorMode(int iType) +{ + RECT rc; + HMENU hMenu = GetMenu( g_qeglobals.d_hwndMain ); + + // Is the caller asking us to cycle to the next window? + + if (iType == -1) + { + if (inspector_mode == W_ENTITY) + iType = W_TEXTURE; + else if (inspector_mode == W_TEXTURE) + iType = W_CONSOLE; + else + iType = W_ENTITY; + } + + inspector_mode = iType; + switch(iType) + { + + case W_ENTITY: + SetWindowText(g_qeglobals.d_hwndEntity, "Entity"); + EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_ENABLED | MF_BYCOMMAND ); + break; + + case W_TEXTURE: +// title is set by textures.c SetWindowText(g_qeglobals.d_hwndEntity, "Textures"); + EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND ); + break; + + case W_CONSOLE: + SetWindowText(g_qeglobals.d_hwndEntity, "Console"); + EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND ); + break; + + default: + break; + } + + GetWindowRect (g_qeglobals.d_hwndEntity, &rc); + SizeEntityDlg( rc.right - rc.left - 8, rc.bottom - rc.top - 32); + + RedrawWindow (g_qeglobals.d_hwndEntity, NULL, NULL, RDW_ERASE | RDW_INVALIDATE + | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN); + +// InvalidateRect(entwindow, NULL, true); +// ShowWindow (entwindow, SW_SHOW); +// UpdateWindow (entwindow); + + SetWindowPos( g_qeglobals.d_hwndEntity, + HWND_TOP, + rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top, + SWP_NOSIZE | SWP_NOMOVE ); +} + + + + + +// SetKeyValuePairs +// +// Reset the key/value (aka property) listbox and fill it with the +// k/v pairs from the entity being edited. +// + +void SetKeyValuePairs (void) +{ + epair_t *pep; + RECT rc; + char sz[4096]; + + if (edit_entity == NULL) + return; + + // set key/value pair list + + GetWindowRect(hwndEnt[EntProps], &rc); + SendMessage(hwndEnt[EntProps], LB_SETCOLUMNWIDTH, (rc.right - rc.left)/2, 0); + SendMessage(hwndEnt[EntProps], LB_RESETCONTENT, 0, 0); + + // Walk through list and add pairs + + for (pep = edit_entity->epairs ; pep ; pep = pep->next) + { + // if the key is less than 8 chars, add a tab for alignment + if (strlen(pep->key) > 8) + sprintf (sz, "%s\t%s", pep->key, pep->value); + else + sprintf (sz, "%s\t\t%s", pep->key, pep->value); + SendMessage(hwndEnt[EntProps], LB_ADDSTRING, 0, (LPARAM)sz); + } + +} + +// SetSpawnFlags +// +// Update the checkboxes to reflect the flag state of the entity +// +void SetSpawnFlags(void) +{ + int f; + int i; + int v; + + f = atoi(ValueForKey (edit_entity, "spawnflags")); + for (i=0 ; i<12 ; i++) + { + v = !!(f&(1<next) + SetKeyValue(b->owner, "spawnflags", sz); + } + else + SetKeyValue (edit_entity, "spawnflags", sz); + SetKeyValuePairs (); +} + +// UpdateSel +// +// Update the listbox, checkboxes and k/v pairs to reflect the new selection +// + +BOOL UpdateSel(int iIndex, eclass_t *pec) +{ + int i; + brush_t *b; + + if (selected_brushes.next == &selected_brushes) + { + edit_entity = world_entity; + multiple_entities = false; + } + else + { + edit_entity = selected_brushes.next->owner; + for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next) + { + if (b->owner != edit_entity) + { + multiple_entities = true; + break; + } + } + } + + if (iIndex != LB_ERR) + SendMessage(hwndEnt[EntList], LB_SETCURSEL, iIndex, 0); + + if (pec == NULL) + return TRUE; + + // Set up the description + + SendMessage(hwndEnt[EntComment], WM_SETTEXT, 0, + (LPARAM)TranslateString(pec->comments)); + + for (i=0 ; i<8 ; i++) + { + HWND hwnd = hwndEnt[EntCheck1+i]; + if (pec->flagnames[i] && pec->flagnames[i][0] != 0) + { + EnableWindow(hwnd, TRUE); + SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)pec->flagnames[i]); + } else { + + // disable check box + SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)" "); + EnableWindow(hwnd, FALSE); + } + } + + SetSpawnFlags(); + SetKeyValuePairs(); + return TRUE; +} + +BOOL UpdateEntitySel(eclass_t *pec) +{ + int iIndex; + + iIndex = (int)SendMessage(hwndEnt[EntList], LB_FINDSTRINGEXACT, + (WPARAM)-1, (LPARAM)pec->name); + + return UpdateSel(iIndex, pec); +} + +// CreateEntity +// +// Creates a new entity based on the currently selected brush and entity type. +// + +void CreateEntity(void) +{ + eclass_t *pecNew; + entity_t *petNew; + int i; + HWND hwnd; + char sz[1024]; + + // check to make sure we have a brush + + if (selected_brushes.next == &selected_brushes) + { + MessageBox(g_qeglobals.d_hwndMain, "You must have a selected brush to create an entity" + , "info", 0); + return; + } + + + // find out what type of entity we are trying to create + + hwnd = hwndEnt[EntList]; + + i = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0); + + if (i < 0) + { + MessageBox(g_qeglobals.d_hwndMain, "You must have a selected class to create an entity" + , "info", 0); + return; + } + + SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz); + + if (!stricmp(sz, "worldspawn")) + { + MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0); + return; + } + + pecNew = Eclass_ForName(sz, false); + + // create it + + petNew = Entity_Create(pecNew); + + if (petNew == NULL) + { + MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0); + return; + } + + if (selected_brushes.next == &selected_brushes) + edit_entity = world_entity; + else + edit_entity = selected_brushes.next->owner; + + SetKeyValuePairs(); + Select_Deselect (); + Select_Brush (edit_entity->brushes.onext); +} + + + +/* +=============== +AddProp + +=============== +*/ +void AddProp(void) +{ + char key[4096]; + char value[4096]; + + if (edit_entity == NULL) + return; + + // Get current selection text + + SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(key)-1, (LPARAM)key); + SendMessage(hwndEnt[EntValueField], WM_GETTEXT, sizeof(value)-1, (LPARAM)value); + + if (multiple_entities) + { + brush_t *b; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + SetKeyValue(b->owner, key, value); + } + else + SetKeyValue(edit_entity, key, value); + + // refresh the prop listbox + + SetKeyValuePairs(); +} + +/* +=============== +DelProp + +=============== +*/ +void DelProp(void) +{ + char sz[4096]; + + if (edit_entity == NULL) + return; + + // Get current selection text + + SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(sz)-1, (LPARAM)sz); + + if (multiple_entities) + { + brush_t *b; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + DeleteKey(b->owner, sz); + } + else + DeleteKey(edit_entity, sz); + + // refresh the prop listbox + + SetKeyValuePairs(); +} + +/* +=============== +EditProp + +=============== +*/ +void EditProp(void) +{ + int i; + HWND hwnd; + char sz[4096]; + char *val; + + if (edit_entity == NULL) + return; + + hwnd = hwndEnt[EntProps]; + + // Get current selection text + + i = SendMessage(hwnd, LB_GETCURSEL, 0, 0); + + if (i < 0) + return; + + SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz); + + // strip it down to the key name + + for(i=0;sz[i] != '\t';i++) + ; + + sz[i] = '\0'; + + val = sz + i + 1; + if (*val == '\t') + val++; + + SendMessage(hwndEnt[EntKeyField], WM_SETTEXT, 0, (LPARAM)sz); + SendMessage(hwndEnt[EntValueField], WM_SETTEXT, 0, (LPARAM)val); +} + + +HDWP defer; +int col; +void MOVE(HWND e, int x, int y, int w, int h) +{ +// defer=DeferWindowPos(defer,e,HWND_TOP,col+(x),y,w,h,SWP_SHOWWINDOW); +// MoveWindow (e, col+x, y, w, h, FALSE); + SetWindowPos (e, HWND_TOP, col+x, y, w, h, + SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOZORDER); +} + + +/* +=============== +SizeEnitityDlg + +Positions all controls so that the active inspector +is displayed correctly and the inactive ones are +off the side +=============== +*/ +void SizeEntityDlg(int iWidth, int iHeight) +{ + int y, x, xCheck, yCheck; + int i, iRow; + int w, h; + + if (iWidth < 32 || iHeight < 32) + return; + + SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 0, 0); + + //========================================== + + // + // console + // + + if (inspector_mode == W_CONSOLE) + col = 0; + else + col = iWidth; + + MOVE(g_qeglobals.d_hwndEdit, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) ); + + //========================================== + + // + // texture controls + // + if (inspector_mode == W_TEXTURE) + col = 0; + else + col = iWidth; + + MOVE(g_qeglobals.d_hwndTexture, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) ); + + //========================================== + + // + // entity controls + // + if (inspector_mode == W_ENTITY) + col = 0; + else + col = iWidth; + + + // top half includes the entity list (2/3) and the + // comments (1/3) - 2 gaps, above and below. + + y = iHeight/2; + y -= 2 * DlgYBorder; + y = y / 3; + w = iWidth - (2 * DlgXBorder); + MOVE(hwndEnt[EntList], DlgXBorder, DlgYBorder, w, 2 * y); + + MOVE(hwndEnt[EntComment], + DlgXBorder, 2 * DlgYBorder + 2 * y, + w, y - (2 * DlgYBorder)); + + // bottom half includes flags (fixed), k/v pairs, + // and buttons (fixed). + + // xCheck = width of a single check box + // yCheck = distance from top of one check to the next + + xCheck = (iWidth - (2 * DlgXBorder)) / 3; + yCheck = 20; + + x = DlgXBorder; + + for (iRow = 0; iRow <= 12; iRow += 4) + { + y = iHeight/2; + + for (i = 0; i < 4; i++) + { + MOVE(hwndEnt[EntCheck1 + i + iRow], + x, y, xCheck, yCheck); + y += yCheck; + } + + x += xCheck; + } + + // + // properties scroll box + // + y = iHeight/2 + 4 * yCheck; + + w = iWidth - (2 * DlgXBorder); + h = (iHeight - (yCheck * 5 + 2 * DlgYBorder) ) - y; + + MOVE(hwndEnt[EntProps], DlgXBorder, y, w, h); + + y += h + DlgYBorder; + + // + // key / value fields + // + w = iWidth-(DlgXBorder+45); + MOVE(hwndEnt[EntKeyLabel], DlgXBorder, y, 40, yCheck); + MOVE(hwndEnt[EntKeyField], DlgXBorder+40, y, w, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntValueLabel], DlgXBorder, y, 40, yCheck); + MOVE(hwndEnt[EntValueField], DlgXBorder+40, y, w, yCheck); + y += yCheck; + + // + // angle check boxes + // + i = y; + x = DlgXBorder; + + xCheck = yCheck*2; + + MOVE(hwndEnt[EntDir135], x, y, xCheck, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntDir180], x, y, xCheck, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntDir225], x, y, xCheck, yCheck); + + y = i; + x += xCheck; + + + MOVE(hwndEnt[EntDir90], x, y, xCheck, yCheck); + y += yCheck; + y += yCheck; + + MOVE(hwndEnt[EntDir270], x, y, xCheck, yCheck); + + y = i; + x += xCheck; + + + MOVE(hwndEnt[EntDir45], x, y, xCheck, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntDir0], x, y, xCheck, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntDir315], x, y, xCheck, yCheck); + + y = i + yCheck/2; + x += xCheck + xCheck/2; + + + MOVE(hwndEnt[EntDirUp], x, y, xCheck, yCheck); + y += yCheck; + + MOVE(hwndEnt[EntDirDown], x, y, xCheck, yCheck); + + y = i; + x += 1.5 * xCheck; + + MOVE(hwndEnt[EntDelProp], x, y, xCheck*2, yCheck); + y += yCheck; + + SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 1, 0); +// InvalidateRect(entwindow, NULL, TRUE); +} + + +/* +========================= +EntityWndProc +========================= +*/ +BOOL CALLBACK EntityWndProc( + HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam) // second message parameter +{ + RECT rc; + + GetClientRect(hwndDlg, &rc); + + switch (uMsg) + { + case WM_GETMINMAXINFO: + { + LPMINMAXINFO lpmmi; + + lpmmi = (LPMINMAXINFO) lParam; + lpmmi->ptMinTrackSize.x = 320; + lpmmi->ptMinTrackSize.y = 500; + } + return 0; + + case WM_WINDOWPOSCHANGING: + { + LPWINDOWPOS lpwp; + lpwp = (LPWINDOWPOS) lParam; + + DefWindowProc (hwndDlg, uMsg, wParam, lParam); + + lpwp->flags |= SWP_NOCOPYBITS; + SizeEntityDlg(lpwp->cx-8, lpwp->cy-32); + return 0; + + } + return 0; + + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_E_DELPROP: + DelProp(); + SetFocus (g_qeglobals.d_hwndCamera); + break; + + case IDC_E_0: + SetKeyValue (edit_entity, "angle", "0"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_45: + SetKeyValue (edit_entity, "angle", "45"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_90: + SetKeyValue (edit_entity, "angle", "90"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_135: + SetKeyValue (edit_entity, "angle", "135"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_180: + SetKeyValue (edit_entity, "angle", "180"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_225: + SetKeyValue (edit_entity, "angle", "225"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_270: + SetKeyValue (edit_entity, "angle", "270"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_315: + SetKeyValue (edit_entity, "angle", "315"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_UP: + SetKeyValue (edit_entity, "angle", "-1"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + case IDC_E_DOWN: + SetKeyValue (edit_entity, "angle", "-2"); + SetFocus (g_qeglobals.d_hwndCamera); + SetKeyValuePairs (); + break; + + case IDC_CHECK1: + case IDC_CHECK2: + case IDC_CHECK3: + case IDC_CHECK4: + case IDC_CHECK5: + case IDC_CHECK6: + case IDC_CHECK7: + case IDC_CHECK8: + case IDC_CHECK9: + case IDC_CHECK10: + case IDC_CHECK11: + case IDC_CHECK12: + GetSpawnFlags(); + SetFocus (g_qeglobals.d_hwndCamera); + break; + + + case IDC_E_PROPS: + switch (HIWORD(wParam)) + { + case LBN_SELCHANGE: + + EditProp(); + return TRUE; + } + break; + + case IDC_E_LIST: + + switch (HIWORD(wParam)) { + + case LBN_SELCHANGE: + { + int iIndex; + eclass_t *pec; + + iIndex = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0); + pec = (eclass_t *)SendMessage(hwndEnt[EntList], LB_GETITEMDATA, + iIndex, 0); + + UpdateSel(iIndex, pec); + + return TRUE; + break; + } + + case LBN_DBLCLK: + CreateEntity (); + SetFocus (g_qeglobals.d_hwndCamera); + break; + } + break; + + + default: + return DefWindowProc( hwndDlg, uMsg, wParam, lParam ); + } + + return 0; + } + + return DefWindowProc (hwndDlg, uMsg, wParam, lParam); +} diff --git a/tools/quake2/extra/qe4/win_main.c b/tools/quake2/extra/qe4/win_main.c new file mode 100644 index 00000000..cde20bca --- /dev/null +++ b/tools/quake2/extra/qe4/win_main.c @@ -0,0 +1,1327 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" +#include +#include "mru.h" +#include "entityw.h" + +static HWND s_hwndToolbar; + +BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize); +BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize); + +static HWND CreateMyStatusWindow(HINSTANCE hInst); +static HWND CreateToolBar(HINSTANCE hinst); + +extern int WXY_Print( void ); + +/* +============================================================================== + + MENU + +============================================================================== +*/ + +void OpenDialog (void); +void SaveAsDialog (void); +qboolean ConfirmModified (void); +void Select_Ungroup (void); + +void QE_ExpandBspString (char *bspaction, char *out, char *mapname) +{ + char *in; + char src[1024]; + char rsh[1024]; + char base[256]; + + ExtractFileName (mapname, base); + sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base); + strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd")); + + in = ValueForKey( g_qeglobals.d_project_entity, bspaction ); + while (*in) + { + if (in[0] == '!') + { + strcpy (out, rsh); + out += strlen(rsh); + in++; + continue; + } + if (in[0] == '$') + { + strcpy (out, src); + out += strlen(src); + in++; + continue; + } + if (in[0] == '@') + { + *out++ = '"'; + in++; + continue; + } + *out++ = *in++; + } + *out = 0; +} + + + +void RunBsp (char *command) +{ + char sys[1024]; + char batpath[1024]; + char outputpath[1024]; + char temppath[512]; + char name[1024]; + FILE *hFile; + BOOL ret; + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO startupinfo; + + SetInspectorMode (W_CONSOLE); + + if (bsp_process) + { + Sys_Printf ("BSP is still going...\n"); + return; + } + + GetTempPath(512, temppath); + sprintf (outputpath, "%sjunk.txt", temppath); + + strcpy (name, currentmap); + if (region_active) + { + Map_SaveFile (name, false); + StripExtension (name); + strcat (name, ".reg"); + } + + Map_SaveFile (name, region_active); + + + QE_ExpandBspString (command, sys, name); + + Sys_ClearPrintf (); + Sys_Printf ("======================================\nRunning bsp command...\n"); + Sys_Printf ("\n%s\n", sys); + + // + // write qe3bsp.bat + // + sprintf (batpath, "%sqe3bsp.bat", temppath); + hFile = fopen(batpath, "w"); + if (!hFile) + Error ("Can't write to %s", batpath); + fprintf (hFile, sys); + fclose (hFile); + + // + // write qe3bsp2.bat + // + sprintf (batpath, "%sqe3bsp2.bat", temppath); + hFile = fopen(batpath, "w"); + if (!hFile) + Error ("Can't write to %s", batpath); + fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath); + fclose (hFile); + + Pointfile_Delete (); + + GetStartupInfo (&startupinfo); + + ret = CreateProcess( + batpath, // pointer to name of executable module + NULL, // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + 0 /*DETACHED_PROCESS*/, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &startupinfo, // pointer to STARTUPINFO + &ProcessInformation // pointer to PROCESS_INFORMATION + ); + + if (!ret) + Error ("CreateProcess failed"); + + bsp_process = ProcessInformation.hProcess; + + Sleep (100); // give the new process a chance to open it's window + + BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top + SetFocus (g_qeglobals.d_hwndCamera); +} + +/* +============= +DoColor + +============= +*/ +qboolean DoColor(int iIndex) +{ + CHOOSECOLOR cc; + static COLORREF custom[16]; + + cc.lStructSize = sizeof(cc); + cc.hwndOwner = g_qeglobals.d_hwndMain; + cc.hInstance = g_qeglobals.d_hInstance; + cc.rgbResult = + (int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) + + (((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) + + (((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16); + cc.lpCustColors = custom; + cc.Flags = CC_FULLOPEN|CC_RGBINIT; + //cc.lCustData; + //cc.lpfnHook; + //cc.lpTemplateName + + if (!ChooseColor(&cc)) + return false; + + g_qeglobals.d_savedinfo.colors[iIndex][0] = (cc.rgbResult&255)/255.0; + g_qeglobals.d_savedinfo.colors[iIndex][1] = ((cc.rgbResult>>8)&255)/255.0; + g_qeglobals.d_savedinfo.colors[iIndex][2] = ((cc.rgbResult>>16)&255)/255.0; + + /* + ** scale colors so that at least one component is at 1.0F + ** if this is meant to select an entity color + */ + if ( iIndex == COLOR_ENTITY ) + { + float largest = 0.0F; + + if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest ) + largest = g_qeglobals.d_savedinfo.colors[iIndex][0]; + if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest ) + largest = g_qeglobals.d_savedinfo.colors[iIndex][1]; + if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest ) + largest = g_qeglobals.d_savedinfo.colors[iIndex][2]; + + if ( largest == 0.0F ) + { + g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F; + g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F; + g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F; + } + else + { + float scaler = 1.0F / largest; + + g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler; + g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler; + g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler; + } + } + + Sys_UpdateWindows (W_ALL); + + return true; +} + + +/* Copied from MSDN */ + +BOOL DoMru(HWND hWnd,WORD wId) +{ + char szFileName[128]; + OFSTRUCT of; + BOOL fExist; + + GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName)); + + // Test if the file exists. + + fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR; + + if (fExist) { + + // Place the file on the top of MRU. + AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName); + + // Now perform opening this file !!! + Map_LoadFile (szFileName); + } + else + // Remove the file on MRU. + DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE); + + // Refresh the File menu. + PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0), + ID_FILE_EXIT); + + return fExist; +} + + +/* handle all WM_COMMAND messages here */ +LONG WINAPI CommandHandler ( + HWND hWnd, + WPARAM wParam, + LPARAM lParam) +{ + HMENU hMenu; + + switch (LOWORD(wParam)) + { +// +// file menu +// + case ID_FILE_EXIT: + /* exit application */ + if (!ConfirmModified()) + return TRUE; + + PostMessage (hWnd, WM_CLOSE, 0, 0L); + break; + + case ID_FILE_OPEN: + if (!ConfirmModified()) + return TRUE; + OpenDialog (); + break; + + case ID_FILE_NEW: + if (!ConfirmModified()) + return TRUE; + Map_New (); + break; + case ID_FILE_SAVE: + if (!strcmp(currentmap, "unnamed.map")) + SaveAsDialog (); + else + Map_SaveFile (currentmap, false); // ignore region + break; + case ID_FILE_SAVEAS: + SaveAsDialog (); + break; + + case ID_FILE_LOADPROJECT: + if (!ConfirmModified()) + return TRUE; + ProjectDialog (); + break; + + case ID_FILE_POINTFILE: + if (g_qeglobals.d_pointfile_display_list) + Pointfile_Clear (); + else + Pointfile_Check (); + break; + +// +// view menu +// + case ID_VIEW_ENTITY: + SetInspectorMode(W_ENTITY); + break; + case ID_VIEW_CONSOLE: + SetInspectorMode(W_CONSOLE); + break; + case ID_VIEW_TEXTURE: + SetInspectorMode(W_TEXTURE); + break; + + case ID_VIEW_100: + g_qeglobals.d_xy.scale = 1; + Sys_UpdateWindows (W_XY|W_XY_OVERLAY); + break; + case ID_VIEW_ZOOMIN: + g_qeglobals.d_xy.scale *= 5.0/4; + if (g_qeglobals.d_xy.scale > 16) + g_qeglobals.d_xy.scale = 16; + Sys_UpdateWindows (W_XY|W_XY_OVERLAY); + break; + case ID_VIEW_ZOOMOUT: + g_qeglobals.d_xy.scale *= 4.0/5; + if (g_qeglobals.d_xy.scale < 0.1) + g_qeglobals.d_xy.scale = 0.1; + Sys_UpdateWindows (W_XY|W_XY_OVERLAY); + break; + + case ID_VIEW_Z100: + z.scale = 1; + Sys_UpdateWindows (W_Z|W_Z_OVERLAY); + break; + case ID_VIEW_ZZOOMIN: + z.scale *= 5.0/4; + if (z.scale > 4) + z.scale = 4; + Sys_UpdateWindows (W_Z|W_Z_OVERLAY); + break; + case ID_VIEW_ZZOOMOUT: + z.scale *= 4.0/5; + if (z.scale < 0.125) + z.scale = 0.125; + Sys_UpdateWindows (W_Z|W_Z_OVERLAY); + break; + + case ID_VIEW_CENTER: + camera.angles[ROLL] = camera.angles[PITCH] = 0; + camera.angles[YAW] = 22.5 * + floor( (camera.angles[YAW]+11)/22.5 ); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + break; + + case ID_VIEW_UPFLOOR: + Cam_ChangeFloor (true); + break; + case ID_VIEW_DOWNFLOOR: + Cam_ChangeFloor (false); + break; + + case ID_VIEW_SHOWNAMES: + g_qeglobals.d_savedinfo.show_names = !g_qeglobals.d_savedinfo.show_names; + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWNAMES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_names ? MF_CHECKED : MF_UNCHECKED) ); + Map_BuildBrushData(); + Sys_UpdateWindows (W_XY); + break; + + case ID_VIEW_SHOWCOORDINATES: + g_qeglobals.d_savedinfo.show_coordinates ^= 1; + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_coordinates ? MF_CHECKED : MF_UNCHECKED) ); + Sys_UpdateWindows (W_XY); + break; + + case ID_VIEW_SHOWBLOCKS: + g_qeglobals.show_blocks ^= 1; + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWBLOCKS, MF_BYCOMMAND | (g_qeglobals.show_blocks ? MF_CHECKED : MF_UNCHECKED) ); + Sys_UpdateWindows (W_XY); + break; + + case ID_VIEW_SHOWLIGHTS: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_LIGHTS ) & EXCLUDE_LIGHTS ) + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED ); + else + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_CHECKED ); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWPATH: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_PATHS ) & EXCLUDE_PATHS ) + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED ); + else + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_CHECKED ); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWENT: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_ENT ) & EXCLUDE_ENT ) + CheckMenuItem( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_UNCHECKED); + else + CheckMenuItem( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_CHECKED); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWWATER: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WATER ) & EXCLUDE_WATER ) + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED ); + else + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_CHECKED ); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWCLIP: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_CLIP ) & EXCLUDE_CLIP ) + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED ); + else + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_CHECKED ); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWDETAIL: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_DETAIL ) & EXCLUDE_DETAIL ) + { + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_UNCHECKED ); + SetWindowText (g_qeglobals.d_hwndCamera, "Camera View (DETAIL EXCLUDED)"); + } + else + { + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_CHECKED ); + SetWindowText (g_qeglobals.d_hwndCamera, "Camera View"); + } + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + case ID_VIEW_SHOWWORLD: + if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WORLD ) & EXCLUDE_WORLD ) + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED ); + else + CheckMenuItem ( GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_CHECKED ); + Sys_UpdateWindows (W_XY|W_CAMERA); + break; + + +// +// grid menu +// + case ID_GRID_1: + case ID_GRID_2: + case ID_GRID_4: + case ID_GRID_8: + case ID_GRID_16: + case ID_GRID_32: + case ID_GRID_64: + { + hMenu = GetMenu(hWnd); + + CheckMenuItem(hMenu, ID_GRID_1, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_2, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_4, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_8, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_16, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_32, MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu, ID_GRID_64, MF_BYCOMMAND | MF_UNCHECKED); + + switch (LOWORD(wParam)) + { + case ID_GRID_1: g_qeglobals.d_gridsize = 0; break; + case ID_GRID_2: g_qeglobals.d_gridsize = 1; break; + case ID_GRID_4: g_qeglobals.d_gridsize = 2; break; + case ID_GRID_8: g_qeglobals.d_gridsize = 3; break; + case ID_GRID_16: g_qeglobals.d_gridsize = 4; break; + case ID_GRID_32: g_qeglobals.d_gridsize = 5; break; + case ID_GRID_64: g_qeglobals.d_gridsize = 6; break; + } + g_qeglobals.d_gridsize = 1 << g_qeglobals.d_gridsize; + + CheckMenuItem(hMenu, LOWORD(wParam), MF_BYCOMMAND | MF_CHECKED); + Sys_UpdateWindows (W_XY|W_Z); + break; + } + +// +// texture menu +// + case ID_VIEW_NEAREST: + case ID_VIEW_NEARESTMIPMAP: + case ID_VIEW_LINEAR: + case ID_VIEW_BILINEAR: + case ID_VIEW_BILINEARMIPMAP: + case ID_VIEW_TRILINEAR: + case ID_TEXTURES_WIREFRAME: + case ID_TEXTURES_FLATSHADE: + Texture_SetMode (LOWORD(wParam)); + break; + + case ID_TEXTURES_SHOWINUSE: + Sys_BeginWait (); + Texture_ShowInuse (); + SetInspectorMode(W_TEXTURE); + break; + + case ID_TEXTURES_INSPECTOR: + DoSurface (); + break; + + case CMD_TEXTUREWAD: + case CMD_TEXTUREWAD+1: + case CMD_TEXTUREWAD+2: + case CMD_TEXTUREWAD+3: + case CMD_TEXTUREWAD+4: + case CMD_TEXTUREWAD+5: + case CMD_TEXTUREWAD+6: + case CMD_TEXTUREWAD+7: + case CMD_TEXTUREWAD+8: + case CMD_TEXTUREWAD+9: + case CMD_TEXTUREWAD+10: + case CMD_TEXTUREWAD+11: + case CMD_TEXTUREWAD+12: + case CMD_TEXTUREWAD+13: + case CMD_TEXTUREWAD+14: + case CMD_TEXTUREWAD+15: + case CMD_TEXTUREWAD+16: + case CMD_TEXTUREWAD+17: + case CMD_TEXTUREWAD+18: + case CMD_TEXTUREWAD+19: + case CMD_TEXTUREWAD+20: + case CMD_TEXTUREWAD+21: + case CMD_TEXTUREWAD+22: + case CMD_TEXTUREWAD+23: + case CMD_TEXTUREWAD+24: + case CMD_TEXTUREWAD+25: + case CMD_TEXTUREWAD+26: + case CMD_TEXTUREWAD+27: + case CMD_TEXTUREWAD+28: + case CMD_TEXTUREWAD+29: + case CMD_TEXTUREWAD+30: + case CMD_TEXTUREWAD+31: + Sys_BeginWait (); + Texture_ShowDirectory (LOWORD(wParam)); + SetInspectorMode(W_TEXTURE); + break; + +// +// bsp menu +// + case CMD_BSPCOMMAND: + case CMD_BSPCOMMAND+1: + case CMD_BSPCOMMAND+2: + case CMD_BSPCOMMAND+3: + case CMD_BSPCOMMAND+4: + case CMD_BSPCOMMAND+5: + case CMD_BSPCOMMAND+6: + case CMD_BSPCOMMAND+7: + case CMD_BSPCOMMAND+8: + case CMD_BSPCOMMAND+9: + case CMD_BSPCOMMAND+10: + case CMD_BSPCOMMAND+11: + case CMD_BSPCOMMAND+12: + case CMD_BSPCOMMAND+13: + case CMD_BSPCOMMAND+14: + case CMD_BSPCOMMAND+15: + case CMD_BSPCOMMAND+16: + case CMD_BSPCOMMAND+17: + case CMD_BSPCOMMAND+18: + case CMD_BSPCOMMAND+19: + case CMD_BSPCOMMAND+20: + case CMD_BSPCOMMAND+21: + case CMD_BSPCOMMAND+22: + case CMD_BSPCOMMAND+23: + case CMD_BSPCOMMAND+24: + case CMD_BSPCOMMAND+25: + case CMD_BSPCOMMAND+26: + case CMD_BSPCOMMAND+27: + case CMD_BSPCOMMAND+28: + case CMD_BSPCOMMAND+29: + case CMD_BSPCOMMAND+30: + case CMD_BSPCOMMAND+31: + { + extern char *bsp_commands[256]; + + RunBsp (bsp_commands[LOWORD(wParam-CMD_BSPCOMMAND)]); + } + break; + +// +// misc menu +// + case ID_MISC_BENCHMARK: + SendMessage ( g_qeglobals.d_hwndCamera, + WM_USER+267, 0, 0); + break; + + case ID_TEXTUREBK: + DoColor(COLOR_TEXTUREBACK); + Sys_UpdateWindows (W_ALL); + break; + + case ID_MISC_SELECTENTITYCOLOR: + { + extern int inspector_mode; + + if ( ( inspector_mode == W_ENTITY ) && DoColor(COLOR_ENTITY) == true ) + { + extern void AddProp( void ); + + char buffer[100]; + + sprintf( buffer, "%f %f %f", g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][0], + g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][1], + g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][2] ); + + SetWindowText( hwndEnt[EntValueField], buffer ); + SetWindowText( hwndEnt[EntKeyField], "_color" ); + AddProp(); + } + Sys_UpdateWindows( W_ALL ); + } + break; + + case ID_MISC_PRINTXY: + WXY_Print(); + break; + + case ID_COLORS_XYBK: + DoColor(COLOR_GRIDBACK); + Sys_UpdateWindows (W_ALL); + break; + + case ID_COLORS_MAJOR: + DoColor(COLOR_GRIDMAJOR); + Sys_UpdateWindows (W_ALL); + break; + + case ID_COLORS_MINOR: + DoColor(COLOR_GRIDMINOR); + Sys_UpdateWindows (W_ALL); + break; + + case ID_MISC_GAMMA: + DoGamma(); + break; + + case ID_MISC_FINDBRUSH: + DoFind(); + break; + + case ID_MISC_NEXTLEAKSPOT: + Pointfile_Next(); + break; + case ID_MISC_PREVIOUSLEAKSPOT: + Pointfile_Prev(); + break; + +// +// brush menu +// + case ID_BRUSH_3SIDED: + Brush_MakeSided (3); + break; + case ID_BRUSH_4SIDED: + Brush_MakeSided (4); + break; + case ID_BRUSH_5SIDED: + Brush_MakeSided (5); + break; + case ID_BRUSH_6SIDED: + Brush_MakeSided (6); + break; + case ID_BRUSH_7SIDED: + Brush_MakeSided (7); + break; + case ID_BRUSH_8SIDED: + Brush_MakeSided (8); + break; + case ID_BRUSH_9SIDED: + Brush_MakeSided (9); + break; + case ID_BRUSH_ARBITRARYSIDED: + DoSides (); + break; + +// +// select menu +// + case ID_BRUSH_FLIPX: + Select_FlipAxis (0); + break; + case ID_BRUSH_FLIPY: + Select_FlipAxis (1); + break; + case ID_BRUSH_FLIPZ: + Select_FlipAxis (2); + break; + case ID_BRUSH_ROTATEX: + Select_RotateAxis (0, 90); + break; + case ID_BRUSH_ROTATEY: + Select_RotateAxis (1, 90); + break; + case ID_BRUSH_ROTATEZ: + Select_RotateAxis (2, 90); + break; + + case ID_SELECTION_ARBITRARYROTATION: + DoRotate (); + break; + + case ID_SELECTION_UNGROUPENTITY: + Select_Ungroup (); + break; + + case ID_SELECTION_CONNECT: + ConnectEntities (); + break; + + case ID_SELECTION_DRAGVERTECIES: + if (g_qeglobals.d_select_mode == sel_vertex) + { + g_qeglobals.d_select_mode = sel_brush; + Sys_UpdateWindows (W_ALL); + } + else + { + SetupVertexSelection (); + if (g_qeglobals.d_numpoints) + g_qeglobals.d_select_mode = sel_vertex; + } + break; + case ID_SELECTION_DRAGEDGES: + if (g_qeglobals.d_select_mode == sel_edge) + { + g_qeglobals.d_select_mode = sel_brush; + Sys_UpdateWindows (W_ALL); + } + else + { + SetupVertexSelection (); + if (g_qeglobals.d_numpoints) + g_qeglobals.d_select_mode = sel_edge; + } + break; + + case ID_SELECTION_SELECTPARTIALTALL: + Select_PartialTall (); + break; + case ID_SELECTION_SELECTCOMPLETETALL: + Select_CompleteTall (); + break; + case ID_SELECTION_SELECTTOUCHING: + Select_Touching (); + break; + case ID_SELECTION_SELECTINSIDE: + Select_Inside (); + break; + case ID_SELECTION_CSGSUBTRACT: + CSG_Subtract (); + break; + case ID_SELECTION_MAKEHOLLOW: + CSG_MakeHollow (); + break; + + case ID_SELECTION_CLONE: + Select_Clone (); + break; + case ID_SELECTION_DELETE: + Select_Delete (); + break; + case ID_SELECTION_DESELECT: + Select_Deselect (); + break; + + case ID_SELECTION_MAKE_DETAIL: + Select_MakeDetail (); + break; + case ID_SELECTION_MAKE_STRUCTURAL: + Select_MakeStructural (); + break; + + +// +// region menu +// + case ID_REGION_OFF: + Map_RegionOff (); + break; + case ID_REGION_SETXY: + Map_RegionXY (); + break; + case ID_REGION_SETTALLBRUSH: + Map_RegionTallBrush (); + break; + case ID_REGION_SETBRUSH: + Map_RegionBrush (); + break; + case ID_REGION_SETSELECTION: + Map_RegionSelectedBrushes (); + break; + + case IDMRU+1: + case IDMRU+2: + case IDMRU+3: + case IDMRU+4: + case IDMRU+5: + case IDMRU+6: + case IDMRU+7: + case IDMRU+8: + case IDMRU+9: + DoMru(hWnd,LOWORD(wParam)); + break; + +// +// help menu +// + + case ID_HELP_ABOUT: + DoAbout(); + break; + + default: + return FALSE; + } + + return TRUE; +} + +/* +============ +WMAIN_WndProc +============ +*/ +LONG WINAPI WMAIN_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 1; + RECT rect; + HDC maindc; + + GetClientRect(hWnd, &rect); + + switch (uMsg) + { + case WM_TIMER: + QE_CountBrushesAndUpdateStatusBar(); + QE_CheckAutoSave(); + return 0; + + case WM_DESTROY: + SaveMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU"); + DeleteMruMenu(g_qeglobals.d_lpMruMenu); + PostQuitMessage(0); + KillTimer( hWnd, QE_TIMER0 ); + return 0; + + case WM_CREATE: + maindc = GetDC(hWnd); +// QEW_SetupPixelFormat(maindc, false); + g_qeglobals.d_lpMruMenu = CreateMruMenuDefault(); + LoadMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU"); + + // Refresh the File menu. + PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0), + ID_FILE_EXIT); + + return 0; + + case WM_SIZE: + // resize the status window + MoveWindow( g_qeglobals.d_hwndStatus, -100, 100, 10, 10, true); + return 0; + + case WM_KEYDOWN: + return QE_KeyDown (wParam); + + case WM_CLOSE: + /* call destroy window to cleanup and go away */ + SaveWindowState(g_qeglobals.d_hwndXY, "xywindow"); + SaveWindowState(g_qeglobals.d_hwndCamera, "camerawindow"); + SaveWindowState(g_qeglobals.d_hwndZ, "zwindow"); + SaveWindowState(g_qeglobals.d_hwndEntity, "EntityWindow"); + SaveWindowState(g_qeglobals.d_hwndMain, "mainwindow"); + + // FIXME: is this right? + SaveRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, sizeof(g_qeglobals.d_savedinfo)); + DestroyWindow (hWnd); + return 0; + + case WM_COMMAND: + return CommandHandler (hWnd, wParam, lParam); + return 0; + } + + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + + + + +/* +============== +Main_Create +============== +*/ +void Main_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + int i; + HMENU hMenu; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WMAIN_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); + wc.lpszClassName = "QUAKE_MAIN"; + + if (!RegisterClass (&wc) ) + Error ("WCam_Register: failed"); + + + g_qeglobals.d_hwndMain = CreateWindow ("QUAKE_MAIN" , + "QuakeEd 3", + WS_OVERLAPPEDWINDOW | + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN, + 0,0,screen_width,screen_height+GetSystemMetrics(SM_CYSIZE), // size + 0, + 0, // no menu + hInstance, + NULL); + if (!g_qeglobals.d_hwndMain) + Error ("Couldn't create main window"); + + /* create a timer so that we can count brushes */ + SetTimer( g_qeglobals.d_hwndMain, + QE_TIMER0, + 1000, + NULL ); + + LoadWindowState(g_qeglobals.d_hwndMain, "mainwindow"); + + s_hwndToolbar = CreateToolBar(hInstance); + + g_qeglobals.d_hwndStatus = CreateMyStatusWindow(hInstance); + + // + // load misc info from registry + // + i = sizeof(g_qeglobals.d_savedinfo); + LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &i); + + if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo)) + { + // fill in new defaults + + g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo); + g_qeglobals.d_savedinfo.fGamma = 1.0; + g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_NEAREST; + + g_qeglobals.d_savedinfo.exclude = 0; + g_qeglobals.d_savedinfo.show_coordinates = true; + g_qeglobals.d_savedinfo.show_names = true; + + for (i=0 ; i<3 ; i++) + { + g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25; + g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0; + g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75; + g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5; + g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25; + } + } + + if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 ) + { + /* + ** by default all of these are checked because that's how they're defined in the menu editor + */ + if ( !g_qeglobals.d_savedinfo.show_names ) + CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED ); + if ( !g_qeglobals.d_savedinfo.show_coordinates ) + CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED ); + + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS ) + CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED ); + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT ) + CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED ); + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS ) + CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED ); + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER ) + CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED ); + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD ) + CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED ); + if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP ) + CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED ); + } + + ShowWindow (g_qeglobals.d_hwndMain, SW_SHOWDEFAULT); +} + + +/* +============================================================= + +REGISTRY INFO + +============================================================= +*/ + +BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize) +{ + LONG lres; + DWORD dwDisp; + HKEY hKeyId; + + lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\id\\QuakeEd4", 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp); + + if (lres != ERROR_SUCCESS) + return FALSE; + + lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, pvBuf, lSize); + + RegCloseKey(hKeyId); + + if (lres != ERROR_SUCCESS) + return FALSE; + + return TRUE; +} + +BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize) +{ + HKEY hKey; + long lres, lType, lSize; + + if (plSize == NULL) + plSize = &lSize; + + lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\id\\QuakeEd4", 0, KEY_READ, &hKey); + + if (lres != ERROR_SUCCESS) + return FALSE; + + lres = RegQueryValueEx(hKey, pszName, NULL, &lType, pvBuf, plSize); + + RegCloseKey(hKey); + + if (lres != ERROR_SUCCESS) + return FALSE; + + return TRUE; +} + +BOOL SaveWindowState(HWND hWnd, const char *pszName) +{ + RECT rc; + + GetWindowRect(hWnd, &rc); + if (hWnd != g_qeglobals.d_hwndMain) + MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2); + return SaveRegistryInfo(pszName, &rc, sizeof(rc)); +} + + +BOOL LoadWindowState(HWND hWnd, const char *pszName) +{ + RECT rc; + LONG lSize = sizeof(rc); + + if (LoadRegistryInfo(pszName, &rc, &lSize)) + { + if (rc.left < 0) + rc.left = 0; + if (rc.top < 0) + rc.top = 0; + if (rc.right < rc.left + 16) + rc.right = rc.left + 16; + if (rc.bottom < rc.top + 16) + rc.bottom = rc.top + 16; + + MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, + rc.bottom - rc.top, FALSE); + return TRUE; + } + + return FALSE; +} + +/* +=============================================================== + + STATUS WINDOW + +=============================================================== +*/ + +void Sys_UpdateStatusBar( void ) +{ + extern int g_numbrushes, g_numentities; + + char numbrushbuffer[100]=""; + + sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities ); + + Sys_Status( numbrushbuffer, 2 ); +} + +void Sys_Status(const char *psz, int part ) +{ + SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz); +} + +static HWND CreateMyStatusWindow(HINSTANCE hInst) +{ + HWND hWnd; + int partsize[3] = { 300, 1100, -1 }; + + hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles + STATUSCLASSNAME, // status bar + "", // no text + WS_CHILD | WS_BORDER | WS_VISIBLE, // styles + -100, -100, 10, 10, // x, y, cx, cy + g_qeglobals.d_hwndMain, // parent window + (HMENU)100, // window ID + hInst, // instance + NULL); // window data + + SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize ); + + return hWnd; +} + +//============================================================== + +#define NUMBUTTONS 15 +HWND CreateToolBar(HINSTANCE hinst) +{ + HWND hwndTB; + TBADDBITMAP tbab; + TBBUTTON tbb[NUMBUTTONS]; + + // Ensure that the common control DLL is loaded. + + InitCommonControls(); + + // Create a toolbar that the user can customize and that has a + // tooltip associated with it. + + hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL, + WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER, + 0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL); + + // Send the TB_BUTTONSTRUCTSIZE message, which is required for + // backward compatibility. + + SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); + + // Add the bitmap containing button images to the toolbar. + + tbab.hInst = hinst; + tbab.nID = IDR_TOOLBAR1; + SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab); + + // Fill the TBBUTTON array with button information, and add the + // buttons to the toolbar. + + tbb[0].iBitmap = 0; + tbb[0].idCommand = ID_BRUSH_FLIPX; + tbb[0].fsState = TBSTATE_ENABLED; + tbb[0].fsStyle = TBSTYLE_BUTTON; + tbb[0].dwData = 0; + tbb[0].iString = 0; + + tbb[1].iBitmap = 2; + tbb[1].idCommand = ID_BRUSH_FLIPY; + tbb[1].fsState = TBSTATE_ENABLED; + tbb[1].fsStyle = TBSTYLE_BUTTON; + tbb[1].dwData = 0; + tbb[1].iString = 0; + + tbb[2].iBitmap = 4; + tbb[2].idCommand = ID_BRUSH_FLIPZ; + tbb[2].fsState = TBSTATE_ENABLED; + tbb[2].fsStyle = TBSTYLE_BUTTON; + tbb[2].dwData = 0; + tbb[2].iString = 0; + + tbb[3].iBitmap = 1; + tbb[3].idCommand = ID_BRUSH_ROTATEX; + tbb[3].fsState = TBSTATE_ENABLED; + tbb[3].fsStyle = TBSTYLE_BUTTON; + tbb[3].dwData = 0; + tbb[3].iString = 0; + + tbb[4].iBitmap = 3; + tbb[4].idCommand = ID_BRUSH_ROTATEY; + tbb[4].fsState = TBSTATE_ENABLED; + tbb[4].fsStyle = TBSTYLE_BUTTON; + tbb[4].dwData = 0; + tbb[4].iString = 0; + + tbb[5].iBitmap = 5; + tbb[5].idCommand = ID_BRUSH_ROTATEZ; + tbb[5].fsState = TBSTATE_ENABLED; + tbb[5].fsStyle = TBSTYLE_BUTTON; + tbb[5].dwData = 0; + tbb[5].iString = 0; + + tbb[6].iBitmap = 6; + tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL; + tbb[6].fsState = TBSTATE_ENABLED; + tbb[6].fsStyle = TBSTYLE_BUTTON; + tbb[6].dwData = 0; + tbb[6].iString = 0; + + tbb[7].iBitmap = 7; + tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING; + tbb[7].fsState = TBSTATE_ENABLED; + tbb[7].fsStyle = TBSTYLE_BUTTON; + tbb[7].dwData = 0; + tbb[7].iString = 0; + + tbb[8].iBitmap = 8; + tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL; + tbb[8].fsState = TBSTATE_ENABLED; + tbb[8].fsStyle = TBSTYLE_BUTTON; + tbb[8].dwData = 0; + tbb[8].iString = 0; + + + tbb[9].iBitmap = 9; + tbb[9].idCommand = ID_SELECTION_SELECTINSIDE; + tbb[9].fsState = TBSTATE_ENABLED; + tbb[9].fsStyle = TBSTYLE_BUTTON; + tbb[9].dwData = 0; + tbb[9].iString = 0; + + tbb[10].iBitmap = 10; + tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT; + tbb[10].fsState = TBSTATE_ENABLED; + tbb[10].fsStyle = TBSTYLE_BUTTON; + tbb[10].dwData = 0; + tbb[10].iString = 0; + + + tbb[11].iBitmap = 11; + tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW; + tbb[11].fsState = TBSTATE_ENABLED; + tbb[11].fsStyle = TBSTYLE_BUTTON; + tbb[11].dwData = 0; + tbb[11].iString = 0; + + tbb[12].iBitmap = 12; + tbb[12].idCommand = ID_TEXTURES_WIREFRAME; + tbb[12].fsState = TBSTATE_ENABLED; + tbb[12].fsStyle = TBSTYLE_BUTTON; + tbb[12].dwData = 0; + tbb[12].iString = 0; + + tbb[13].iBitmap = 13; + tbb[13].idCommand = ID_TEXTURES_FLATSHADE; + tbb[13].fsState = TBSTATE_ENABLED; + tbb[13].fsStyle = TBSTYLE_BUTTON; + tbb[13].dwData = 0; + tbb[13].iString = 0; + + tbb[14].iBitmap = 14; + tbb[14].idCommand = ID_VIEW_TRILINEAR; + tbb[14].fsState = TBSTATE_ENABLED; + tbb[14].fsStyle = TBSTYLE_BUTTON; + tbb[14].dwData = 0; + tbb[14].iString = 0; + + SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS, + (LPARAM) (LPTBBUTTON) &tbb); + + ShowWindow(hwndTB, SW_SHOW); + + return hwndTB; +} + diff --git a/tools/quake2/extra/qe4/win_qe3.aps b/tools/quake2/extra/qe4/win_qe3.aps new file mode 100644 index 0000000000000000000000000000000000000000..9be3e7d4015343730c7c75a7b43042f0422584cf GIT binary patch literal 78688 zcmeIb37lnDRWH0N1F2MpFm$8A0SeHV2nluXtr1ZA)~#FJx4Wut<=$I8(M@$o(xD+^ zCm|gMQwdLLm8U%4d+Mj97Ah#HL?%IGCdXgu6l=x5Zz;OuEN=474owy33$Vxhs{nuerF`1Yz1eK?#&U z+gs`H2XV$dk;Kkwr`26TNa|zmNs8)q2M7r$HTPtt^gDCyJ_vQUTM5nC?#cj!hTB8J z?CNZ1u-IItm?`%Z?`Wkr-)vFNjQcW@T0Rz5Tir!OE8LI4YhSLcL(PR1V8@{JDy1B3 zGa8}usfpu-PM_P1LHnK<=H_f>{eCuz!kwIMY~ns!e! zq;ZmF+|vzd0;I+mvo1p+;wMR}Ipm^(G(}R~J=2h;Nou%f8PW_%M{2m3-q+>46t4oV$EG|fsB^%ntQGRt{_j2jo00n#WAixs~KEvnn4+FxVi;020?2W zU<2g<#Bn!nfs9wsCJa#IO}I$|LoNqw!c7@ieM*RvZrTDF|KpQx#sKHKhnGm5a?i6! zrV41!SK1tEhe2C2@A$NPfpz$V;50~7B~x&;f9U`@J30~7B~xg`seU`@HMfr)pg-Li#A zu%_J&N@E=@@@HJnq9jx^4$TRpQY*&Q+3peecyi1Q3i2@}tXQ`UDnN&n)^9Zz+QDfJ z?OTw@N^Y{|j##G*K4?dk)?Ss$adp1aUYH}N?v7bBV*#`mSsH^p*>J~$1Yc`Tj=K{U z#uNhW#Q_#;=E(`SYLKW9fShnAEsZfYIq7Z;uG#+dNt<#nu{b6PXg39%)-jXQ?q-W( zihy=Yfs*=Qa>kvqD5eN#w+56}Lny&7wJ63tXr~L56!EE=dznQsnn8PcKuKLXRd=^p z5Mvj#+XF}{(y4~K!-5#ypxqfjjIF70cbCO5u0gvyV6+;Wns8?f3Pl;H33pFGN$oi` z>F%{4Mm%Wu1(2_prl#C0ER69E+WnTsSe}}8XDy9!IyK`S2;!QktfVV3h9r2UMKWGN zdsRT9vJ1$Xd$mO}Zl`PRH36yJBNFTGn=Fv=3)+JL*hlAMg}G?D;npmWaSYl+mc}@p z9(NBL8j2if6YjN^#t569bpOH97(3Hb?wc)*u`@mGzQxiQJJU1nbxP~+@5~Q;IYxdt zr_}vI1`wogRnnn?RCC{^B&|OV5mtBK?&Yyw5K_av-jL8m8=Dz-|Iw4ERZtV|JCvj< z(Y+g+nQ-4}VB&Jpy+KLp4S`L${}h~3DP2yx@3JI;&A9&@oGPp~Hs=0|C9zM54)K3g zTIepK*W|uiN&8k=p%T?_-(ykYvf;j0X-w))YgO7xv~2GGQZjp~tD&0;^7kcZ-%&)9 z;l5uPZAu8WBWee?ZsdgiIC8lA0WU~7tKNt2NvYr@S7VwR>%mIqrT$nWnQp?tV0NfN?;3iQ-Tg zYUuL3iEIQD%}DzQVt0IO3^D%ZNbNTdwVQpRkGmfe`k_wy@M;Tj0KLRdxF3)7mF4+` zE<+U^~hHVBfA?^6VL_M;_w!|DXKAG`5r9F>FQn{2cOOP5j1O@>tZx4=0-ojYnqZvc%9Lkz-zaqTo)y3w)_Wtg|LRZ3qfx)k40EI3$dxK7M zVc??-!-9`h;?U7r<~X4MPP<>rfUW+%{>tp2*KA3iM92T*8A4SKx+|^youz#YEppQ* z1SFYosom_gF5Sf$i zHzPa9H2f*|TanKUw$xnI@-;E-{(EE{>vk7AOCoZ{{dP*{`~$*;*8X=QgR)wv(&jo# zn8A<|i*EEMBjA`Xm*_74uAxRn=rjLb#t53m-R}!0=84uqcS*87I>w*Mc$hGeY%ZRh zbbnA{Gxdcz<^E8Zvnzu^cZp$=;)&l+3%w|chdaIYd=F7YXXuiiPucSe%|U;Eb57X} z_eZ(PUUT1}c5l#b`N|BP(Lb)hwCDC|)SK>svz@8br|mU;vI zoIeu?dWi>6=vPt6wwrSd06I5+p0HZ`F`*%zM~CJwge9e1XR+vF%6&%2lDV1Is2D`l zwEN4HvD_T&7tW0PtCS;kJaYzf!e>)n3vHWlYVNO7&S7LHmKXMM{w8B}dl;3G)o_0+ zEb+BZwb^Ft;J#jWg}InroWB!9V6x(3N9J=vl`cnr^~lj#rBAxg3tie8opB?4%Kg2N zB^EGu*Y8RL#O};LL`G3(vRCszBHgQ|VzkKrC=9Q7v3Wpx1MKtsQ^M#hc}BzivoK5< z=q@cGVMX4!`xoJghZnj{jv|=q!klnl5T?XVoQR}9Cf)yxtR?h&kVg*om%Hk4%6&0% zmwRYWx-0zzG41|U5ZXg&F!M=@pc(%+!x%3ZXvV)}7!#3Eb6bWn85wnl>0z|Fs$(iL z8g9rirXyqAU1S(Dkul*e7DkN3W)JhHy=L#I^orPnM6{r-zr+YAFj3HyyHo(u89>ub zN7L?ck%pl?X*2G!OySBBGv#v3BurWNTeQ2Tt0cotu~kY ztIVya)cW0(UdzwZxEdn!D$D1rN)uxm9lB6J!#y`|RR*S8TYN&g^#+({o#R8VJ?NpA_hQyV`g=pPe;)>OuBu%UFu>UbwBUW z5~340?GEsP*#PsV2Zgb!gFJW5b+v2V4Hv^Qo4`oN%VW+2=X?Q9~kAEHCi=3`LGj zFJS6c74&9yPA6#RPBSj9r$*88eJ^Ckb#ZCV>-Yj9XP^)T=X3px|pUPpr<^ zVMoTmv4BZor7d+Oi)w%nNld51o+sJXh9-K;=O^#4Bi;eCki{3F_wW$>qaLsM%DNDW z2Ek<6YcUzD-u0QyI#E*M270f>TrtWia==`t#TS{FP+%EsPoYnAW5#Nsnp0j4v%0CX zr4^PlIIClFH)Zu(Jw_;a4NUW&z{*G1lle(bE)e4YNoEmo?X7 zcP>TLF>h2L3fZge#o6{81{%!o(9*!vQGw#<4jFKj;~Hg;W2&fNcV`c%2Td7-hzZOJ zF<8=lTEd_ig4s)bOQd$uWGlIbS(yT?)vv(on3XB$oDouZ1Cufdc@;B7;$R%pG6iQD z@q%a_VAfff6PTHaOg8zJJBitul&h|$FgKIZSLZNxK}S%8PGgEDV@tO#gm?y1H3ffV zd5$lm#bFb(H3frV!<*#gqeVz&F=-Rom~LBLWXC|9wlHr~@D_V3h~yqd#^j+J{GOb* z(5?mEd&@k$%cQ#+=4>*V3+;yT>X^GJ@y3WeVnCc-*d!iUSNd3bl4XX(vePe${M9Sj_P-||{bybQ(sfbi;=IWh7EoZgn6f^Zv{ILW!v zArS63W=;&Zzr28Hap6p0?t~mx*E%2}8U6adD9AF0F4P*P6$qB$3xd@?B0|v1|I0{c zqGAd_95gVgP&ioW`!=A48O6^E9fNWXUPPd}n81WWaG{h*Ocszb*Pd^p_hztDm?R)a zh8Ac>G@>xG_xD0(Rk<3;H4OTRp6~V+(G#49YEgiRv40W>|I+ z6p_^L>BumkyUe(k%cx09L_k3v$~s#ycMnmT#(@xlA__JBP&Q` zr$}9nyP3$&%M+YWxaURw$`ZS)+Wl1LlkWME%`u~p(eHU-ATO^jbywTH9)=LjL+ETZ zXQkIY&lhF00fbqSF8Ylt%gdNyfP(gsR(qN6e?%M_+EzpsQz;n;>y#pBvAu}s&gC>* zJ3{bIildrD(YTwB04dqsC3;D`fwrL&xtQ1YmC8I{EFFlP!QpP?)ZM|z5sBpKs0a=l zZo#tUO&9^lH5}ytG42*E0{v^>9%zvTV!|y|BUHeo>t<||bMW?QIpbn9SHwJ4o!yYJ z2i+n|;(b#uaxr8<|6Nv{;(Z)Pee+xhawsCC9btX0JS=gFJiNl{96~pq6H=aEcSj;$ zr~X492$CD_Xyi6m2JDl7JnoJ~GN#m4q)!CKgnLnB%=fy-WS9iTq&prNC|5GLVnYPp zlsgf5GMwOIU*%1^)yUH^h%UJmmox5U{qR#*FR9DF!p^UJ^0vix^(Z-4uDE z99@i6#=H0VoVz&!7BTQdD0AN38kxFs*YdH3<)x7?T?3uo zG%{vt?sUY+SU3?;cQ1=<>G@Jldv0)aS!)rz{<$q8R+bJf;Wc37PPp46w>OwigipFV zB2#)=)@M`h&dBX7VbT??XKSU01sE-@7qRT+?lOeq%t1#6?DJzYGw#gx5G=FQ%4??S z?g_AEbhA_$Q^ODa=Q)6XMTE?wl0+3a=&rJ9Se@%iMZh`T`>Q~bw+c|*osA&0R}@18 zQ_q>mb{6y^jPI zqw)V-f@psX{bjso7C8;~U$z4s?x9vy)VTYvB^07oJ2z3-g!}I8VMg4f`<{sN3*EF4 z6?JGkzc2EARG~OyuqCfk>2WNd{QihRhX$=DlDaRISPg3?*CThfiGhW0Tx)1Pe;~4= zaCE~u^WOD@`@t%RmR|MZr2C-=@zqT+9S84CxsAw=S}bJRy|D_y_iA|OC;i(R)>i&- z6^P9~Qqdxt?nkPSafAwA&AK0rn0;-GdTr-ZL)LO{iWp3HR$=Dcn}j@| zZo40gfEawg&{Yy}-u-w9f<-c&RlXb-ub{2{i3ka0MKE(dlcTBq$q4a^1kuMFr%I{2 zpE3|u>Pw;CYmT``G9J39?Vh~cnXff#?x!<0BWxZ^7F2e#?%tjOnAwVA+HAOYWPCO# z=$##vHcmX)9Cz=`K)#sHwU;_NnyED>+`BSRh>*}Ltu-gzyE9A=qXA9@OAD{{b#u!7 zOoqY)bgVa;)9yVPpJD2^+nj?#q|CVYX8ip~_tlQ{Lu<{Z``L_*g*U9M)%C1g$-S{6u6!b_?%=3>)j{A{(pII);a}bb+_L+P`5T)aKIJVG!!5(tkUJ=(G;& zAoO7mGn0h~t)qtjofO<&Tpk>S)P!v#`+KhrS5kdnshX{ay-@*UMP0h!0>6@!mOD{BH+U`$Ml+QRRYTo^6 zib7D)Icp-<_=>uYrsU634B~gyk6p{&L$mVdDO{rGP#wv3!wO#4N%ddH3ckNcVbHwX z?RPkhfRT*Kmx5QHX}Hg%Sk`-zvnt{TBf!5*(Gno6#96{i>7ahX{Z$HLpyt~lKhI3M z&!+s&66Q(yvT>E+kvPV}!M{#HK34QwJ)0XaH2j+s>Q_QAQ)7~^DjYNJZ&N2){E}w0 zj*;TurKs6%_aGN9XVYWq<5~B)ozNIwVy4ZfP|JNjV&|IZvo7t!0$+??kVqK)9>cN> zoouV4k@)8nJBOF%v#6v+EgFe`N!fnhhhg#Wp6BamD!!1SkS3@|Q4Vx6t&XAo>CWPU8X<0W^>y)be)v8wOq$eMP0Ba5B0S+=5W(Kh3nktYL1xIljgtNpYDp>rYg zxaO4{5tv+$2n~TQXrxqpzK&IZ>K@;|>#I#!;@7~6>?zlY%*E!uB@QsjkhOrp6*?db zm|>z%g(-^z19QK;x7E0w!MJ!K3OtmsYHl&Imb!Czuh{DKnM5<_DlJ7GznM6=q_HxC z!EiTcwfl#~)wo;ES>i#=Cu6B%@Suo0%qX5gcc+&z#t%0o#260uBa1_lf-~&~fisKl z7~+Vl_;tb;LeUT&j(pi&z?bV)bV>=BaL2X*fJMNhdr<)NiZ`ROQ-!dn+=~OdgI9c5 z7&E7Sa1E?oXt*0wu6|@d*0_5~V6~*9%bbG`2QjJn(v-nUfnRN+Rymz=`h%kj%EF{@ z#=`4Canx`xkDNZ{y$-fzg9&_!<8F%_bamQ2lm&jfhL0v@yEo^}%3c;+?|)y;I@*?R zh~RF*y&`9#0HLOrk0dAE{W-UF6tm87IOWdftbILXLa?UY1361RcnJI%_sX0>%yPaaXNz*yQ2v|9Z^{AG9z%^8&IhXyKIHfaaxG(Pe&odF zLy^-zipix#NqG5oa>_j%nRFp77^Wd>?wbvx!xiAj2yFPiCDMHb3v$D~E|Ocaj0n_m zcP>ydEduF$#m7M!)+ILZdHR(5jtagEILV%N-&w(4_MRbP#=RjRW>?WYZp&+uM!kXe zVc!)v7y$>>{$&c9#Q8RY_`MOLWq~iPxf)gY`06(2qs>0tMZa`eR|iALg!{f6bQn9y z@Y@#cIkxdO;QK2ep)b}(rd`kZeA}kW9H3&_{Xi8z3Yc*}m;>asV!II0bU&0M@EsUm zJx0u|+sHABh>BY7jX5NUiJ&?6!#T)nlEvg2w{7<$IVecd1-uHIcR!lL5W89lGmTI# z-;@KeycQoLBIq*m!eT`C<{UCRSd#sBL`2>FSOuS-i%HiEN*eCRD-cD9Q8eFD!QYRC z_)^FvC@7$B%|V#klCesZH0gdK2W4WW+)r+ch;pXgPel|aidWFZP;bn*w?)ouSC(!d zh)wrMBzG`RpmU(@+N}HO$ROS_Tkh?VsqIYk!<>6ZWFn|oQjf|<-rIyJrFO0D-nkt} zs|iV>dH1gEP@y&;4lhsM9dVw6j-a1TZ=<98GbtaP;8j~E@T251B1|N<`F(Pkt*?nC zdik+(84zAWD+J#zmm$(EmN4Km=E&AsX?a;@Puu9>zQ2OEYE~|^v7qq-5yOaHEu1&q z2g|I~^{o3)g!mYY0$OgflAFqyb3b1~X-g57p3h@Fn)`(a(jqUtp;a!h1;6G#T+Qbi zTkz}dBazS7JG!p|d04OV%NdUiK(Wvch?@IoKrCZ^R9ZKD^Mk5i$E|I2jXze22(KsF zXkmV>gy7I9ye@8|tNig2f>U++qC&!fUh^j+1``uHNh>D*k%~2yLCgOt{~+7)&d0D8_C@w}<6Fv-)bQjkguQV{roN4vIOuHeOVG(gM7o zFc;g#i;Ca1dqzh^OX7{IpLoo+F;(8l|U-?s=O1uIYb18qZ^v+h$C z1;6OzD+0C;pVLYrwA>$9jD2yz_pN_unS}rwBW?HT3=?8b70kQymXEx~H%Y{(FENAl zM;4%=&8Cgon8^BLi$b};G&r+EeBac@Jl3CB5CelL7l~c*45qRE)B^a)oEkchD6e`b;K`<*h(_ z79T}dpnN596f0G*-yYL+7T-wk0OU&Uqs3bs^rYNpEgBQ$2x_sougU4#u!^QVJL~>> z2e7JdxxcZPrFL6(A3{xbG}k@n{?E5vu*cx7K1myJNR$jeQpP^_z!QB zK5sE00+R%8)!g4(kWXNKP(ItmOC6Igt-AY%3aD-3TMhR=EX2>s#SGUPcmHSstkt;? zh*_Vc_QJ8<5MeX{O!x8ZBD8{HXvjCwup zZg+P9ub2mcxjUg=3C>wiPvbMQJF)W?-RQk@zxb3~H+JU8baM-*8ou5R+j(OD&>L3p zWpMrY3O+dKH;&)X9zTvH#j7{88`t+**dY>AmyAqVGVlHP}yy|{9p~y0WA4y0u+~~U>O^CWd!!FlbY#;J)PM3W{UQ4QO zMW7op?N13uT_+_Ra|a?J?7eg_CmnSQIq8^NBq;{6*oUCltKfqv!0eQBN6N7~+T5M8 zRDQB6&RtcAVzZkwRb0FK&Ye{NOx|-D`+CYlnUO_T??}n%CJDcgGVR6!AFE)YQ4c!` z{2JMQ!=~fKechcX?y&=7agUY9#XY9AP8JUs4Qv(#}5>YxW~}_ zq{&Vcaf_$Zr1{`tgOs=MQAUn_$CS4kg6?GUh^5FDCT}N2@)K2f-K)r*eytY#;~xM5}RUtq@ZZN)+$)X`X45b%i8=NRWCQs=+MCRZ7C)0x%2vz zp^d@qDX}Q1?h|Ba9pSe`c~7MHy-?m8DSi`_pN$m1`^ozv#czA^bCKfrJ9&Sk_>E3J z5Gh5Cp*xp+h#dLWPQT3irS-2t^UjpTtNVo&6wjJ8;5ijLu;9q4je?53DKQPkt+<(( zKBsW2@Ex1_PrwDX#Nc)xem{(hcq{F2%{}W9>Z9Zdk?h;j3km(CiqIuG*IXjudcpcR_hhxW{|1>-;@;G`&9DW8c!}`g^SJ81uK>gVf)Sxw^mOexeP3kMFm~{Vkhv zHz5!5YN_TfiVt;naeQdFOX9=0yEHybxW~nZNq1R%z%J+U0ehRr2W)B{A25Zv%RJTG z73Qh#9xqRAnZoY7XZxqHx#*04)|FiD`SR$O)N=30WlPX;%?;j3+!(UwDZ)n%;a0j= z7pXffsjHR3g%bD4c&}ZRWBjI<-9qS$2#qz%g#>@qHi9W3Y#`s4Uot?i^+rz!VU=4sk}wRxIxPm52OCV#qls<~0~RCmuXPYw4>^E8h3ndvTJ zM{BCJkUmZNx<{X;P}fJ~wEH^qG~={|79^(CwSCs7n)~{Q#D)OcG%2s)TW@_D_wBbn zg%(_&CVd;OPuQ`;$i%MJ=4r;a=7Pj0|Jt7G6BaNWypF7O307Gy_Z?bZ+yTbvIw=gw_ zeOrfMKFe>3IdmDGF2%{~FwV6#Ht*lkTf2x3aIM-05B>*cFqGWzp>n@59PeyZl=q;ROd@cL2!0fHiBv0gaoN z=6j1Gic1YDTUilyC3sb)&cu;_dEw_sxERsPDjEgm1d;Ouk;9DYD><3F5!R)`3PLca zA=Jl-r;OP%qmggq;C@QgVXCz-dnQgVD|G3InZ-mH!(fDJh?SBMcMIANI9Pgwdbv<_ z$jK5U#1SFtAd|&Nh`T^c&7leTNh-jYL=*BACLxNgPjm`{yU5}Q$yZ*yZ}NdM{cA#5 z+{iVIWq@70U*?*{`-aKYH5$WQ^_wyD^^UCi%{X?|Z_bLVehr6j!Of~)!^u|t8cw$A z7aVr-HSZMjZ72&qC$_={yZjKr$3Gp20TSA3z+nW)2XvoA?#y++Q z%E5(&y96w)uCItSk4gBL6o?NCMP;V6%oByBy9CVifkO^M4T1bCXPSZxS+lB^QZl28~T8!=d*Ran1EG&22Q5if@_ zC>Tg5P$nN~(Q_h|e#R&}fim$(%b@fxtllM1CLL)Rlz9!7?<^FBTWJ|of`CLa*%E~v z&?Mo+uM&hb)lm2W1uc^*K`4?;;uVzvph@y@O@iq1slX;W%(_Tulho0+Gnl%QMvQQf zy_G!i1Y6V~gVBHq2J1Oa1qKmCVT6dIg!+`UA{ae^u4SXbYMv-yPa-I0Ou-b0QLItG zXn`dVLvQQ59FTn~S}{!BKo82p+a7RC7se|_#S`hKxsZW0Eb1kS+4%N}_sM58qn?TM zpt-QFmj@RW4bW-Iu4=smi+UwAQ#R0pY^@&gQmTYz8U}iS4p#R{XeJjd?+HDi@qPl5!3TH=nA3g1ieE`O(+F#ijROr8(*rAxb2_R9(36-KJjy%hNoi3! zV-ug_mEgi9R=P2t+Icq`OBlXkz*6a?_yW&6u(k!o0mpa2HmkQUSScuc#)i+hyeOTM zj`jz|nbth!4J*9n^W<X0J|y_#xD~~u8pC_O6U2PiOti8il;A;f2)s?f!+A|WA8=28k*7Iia3$+E6=Fjr?uPb}+3y0xqusi|e%NS9tqw5+QP zNzVA?1mZ7D*2bu3pOg&WWsHo%!mi4aM8v?2SR}k;7olPDh%_{=k%qZR(vZ$VODych zd?92-`ks(z7c#Bw$?UA=KcuvfgSFjE2wGplZ5aH^klgC7dMII9tGiKd0V!GDRS|K? zfDYz-w~^jJU?kWP!e%7`I9DowY*{wkhM7@`2(z-8EI-P#EM4SGrY(!!9hmx-hJ4@m z5y#PA<~2D%NUx-DMWEi&dgxD!gKyJ-Iesg&P+Ikd0{FRxJM;3lRZ9JK`@vm=re_ zf1`@XFFxC$|7-+Wh_U<|Wt6S|YH=%ybX)`i*_;jwUX&)KfW_}O2s2?7nDIu1HQ?x* z6lX00M@%fS@e2j&tPZx9Xe|S$A;1WuY#~_VAh7%^Y$)L*NUV*lh2ZEvNmu3@RAS6j zVcH|+7c%7oGjdD$kzD_+8BBJDS&-DVu^3#T*jf#)VjIiBkuCMBPfpok#aItcvV^x1 zY%56_PA3+Gqg-iM^<_1KgOV!|D6xc2yRjl1-3YU21B$VKj05jaL@#Crbml>r-Xqqc zaFiOD#;R~+#+(<{z)^NyA|){PQ%ZttOh_zpY9zEK+#)Dy5q7eqjsi^6AT@)aO6%r` zG;M+)wa1rO9xigX0VEcPs{n~5;wnIDkvLQVMnz(oxJp7|p|}c=SSn5dF>#7-dZZVM zZ<&|{*mo+rJ{lzjPQU#j$hH~MKSCFXblX@69j{bKw*@nLApJNGIKCAxluODfShKHA zG!bT74WGdJ(H5Du%{8AWk!2fIc8xI7O)VNn?ZP(S>(aT6nxe9fALkKbBc`aljP2q) z)5XZJ3qUE!bVMX;WXOK}HWBFX7F-H$tkerPOoZ@4JC=Objt{Il~= zxz%GtVVHfXu+mwK^ZKyjS+de;xJ;M|E1d>`X(Ml7vt*^ypxD#Pt#leTW#!gN_uPK8|VMhup8LFI-UD&(yGlx3Fl}*Rc zd&V0naXw+C>iQtV^|Qy`DeZcyE19AQfm2thRjfRg7d--00PsrzL7v= zmOG7H?rNV{?lioT<<1h%SnjOg)y1D-Hd%wOGL7ZV3U}k`&c8WG-4&KQE8G>9J1cnj z4gl$_bFd-Kf?o>DofYn8)SaK0PyK>MScE1C5riVx!b}pQVEU+;wJB9F8|t!E$@Gx} zL)Ech6fO(PomI@ja%aX2rtE69c`sCJTx+>gokV&xXzAY-#H|#>^O!8KPB745WMFZZ zp|ZoE=(gHaoUfFV|!aY5++?nt)%bf|YWVy4<Rt zjf!OX^gyT~rKPDx+C|HqiWWK(RrX_on2_4SNGx}%13!BmtQWyWNN~CkzhlBdu~n8k zmBWsuG0_?P&Z^RogXeW`m|#YrUBlp4#Z+7Fj66wpo%ly=`1dlXNeZi;2u+A`|8^$f zmMwQ?viZ`d*iZ}#LaI>#1ZS2z;aK0S6dTYMjT|j^mf4x*&I$nHk#SDTon$GBa9$GCK;n_0J^e z#ajE!L}(HR+nE_P8mrBW8h}(oshLs3#l}DEw@cb!7Ts_%Goywh66s1S6EQQIuqFBl zK&~mwj3x+l_seERw?U}ik{m8RFgXWP>bYaHStlpZb9QQG)Nu9fv+RscbC;qVE7uG{ z8a*~X%1a_mcHqs;j2gE(e;7J!umGA=KGw{rag>@FHH_5Es9~U7Nv~WsEaXBo!;`U( zH8W~>-Y7}rn%DJOkTLW#W z4R*?`IYdr4S3s;uMb0|!0KsbR!pvv^+uqEmfkbn3Y#OYY(MphHp29+?sRYpnFPj;y z6j3%aYGK?;4;_!x%%}zIWM;GyS7Bz<;84R=ni(|^F3@gbrh!pa7$P;v!I#|dHl`xf z+B8aaG&5@Cl+BEmn28Eg>aZ(sZf4ZDRUURDRa=)jX`#i{IJ7oIlZ1=TEyUD#K?r68 zb2Fo5U%-%CZf3LuvSvn0OlxMe#I$9Clj|jbEm!=0&j5TXg%TKRCw|hmJx<>Hpu5CR z{K_b91slx;>eNAqdatm;%xGDT2N}DdrjuFZuu3zdWnl%(h%*f{OwM7^b*JTRys(1i z;{LLnvYAnXsW3BYxY*J+F*9mdK3X6gn~NGVqm_`<%&37>ni)0xsHK=*L@1LS6Cs?; zwq`~vOHNJ+uyK|m3KZ)JDb2hRG8dPt+t_CxsIe?k1D5luEJLj`O;pWhV zWwILf?#@BJ1jcQjX=XGBg$M~_D4H3~G1X>9b5w3-H0Lu+*34+m&&-VG?99w)&d$t? z=4`uLcMZFB=X_&k)UZlsMsuD`XKcKkv$>ykuxUv%qdC81W;6$s%#7v$L~5A)6EmX~ z{KU*?1wS=2S^zF!X4K&P8GBaw}B{QQ1Z+kPN z8ARuBSO=kjESVY2z}uP`&2T%K8O^X&W=1o}&Spk4Fbw@wn;9+RXm%{KTADN%G`Jb# z$7WZW8O`KXnHkL>+nE{7U^|)_&9FP08O^}km>JDb+n5>6P?cszGYsN)M>C@td^4DY_{^5nb90lX=XGBp{|}y%#7xMqz_exnb90jWo9(T zP)LQDQ3K0N6FAJb5(_*DC z1xcxCu@WpdEmi`QO^cNvnQ5^qerj5*3Q>euKYRAGVk2WeG*0h*m zYd$G#gC)sY@KVEGNoBzPdbA9d)B=H(x=xbY$6yqYlz+obWh51VM^%^>Gr_DhEw&B6 zFfC^I@-m-qRwRaXu|>!(!b?^Hh-tCH^|q$Psu9+-SQ)`_k~J+>MzDLXlM~`seEx4R zJDL_taJgx*lvy?{mhh`hizN`O9jG)dRt3sUizOIzB{(a=Z*OzcVhK(_*5(vUizNUr z$eI>Q_!LlKS}eg-nifkCMhf0G8Pj433VzW6S87@;!Pv=7}AX|Y7Wwx-1r)OM!D5)cD}ZWc4|QSnULb;Zv2+nW|k1Q7>8#k^VD z_FR`&Q2>^(`#=X=z$FiBvT7E3@r-L^3;Rt5D< zh^jO#Fr!4?<+po@X|Y7c_NK)W*!HHy64(x=#en1f3HlDhU58L#ijNP5vAwx&#CZue z;=CMt>up@&+$h$OZ*5(I^A;{CcXt0*K0nc2?dD-2>^7%-_eWQ|CEVXnrW?Xj7xu<( zfh92>7vs4PTV${B=(+XqGzvL4x_e-4jDI{<)~|NUut9bjZtr!cjE;A%FMxidyBWT_ z8q&|;>1B|36L8M0x!LtL=x5=A&-7s%SbZ9DzYMu8xVXzb0QWC}>-(Vhr9eL9J}Nrt zk9#36bV2bXoD?9bOrHK@F_z_ztJ~Q z!jkayr!78a9MV^3kT!I6voPnuTR~VxkqWm#&z-_wM(o@w8p-3a54bsS?}y9nuz@cQ zdqVINauXY{Cy&M{Dk&x1#JYHRa>>|GI1(q)Ek?=5; z^cZ%pM2>i=_>)qX5RTh{xkuQ)Zg{g2+MC?Vg*WV8V|XpN)R374qBKmnX)XA%%S&4Zl=G# zE#V&m?+n~iil)uwC>=Z=LdY10lzR(Y--Eck5h%@Z4?_y2Mjx=W+yg$3*GegfVZ0nE zK)1|AR?7Z$mZp$ON5pL>p&b?4frNHUXb0DO@Eg;Iz8^*T;jxfW)%{{dRS6$lZzAk3 zfqte7EjO}mU@fOoW1QZxz6k!yMbFi+3CVhfF{8Eb-Kc+H^+n>lk92#9m#6ilb9W(6 z#dsQ(T9MWvnRe>;t5K8PC^8v_GZ}t>bi5OCZ$c?xIlGl0cV~uTEzU47FHqKKB6Gcj z*8FrD`9o9m9ljQ2YSZVVxQ042YUlIQ>&hC@47Tr7`h>w|=qo!D% zqO9A2Tywu>kZc#&UeF(`^%)**VP+)<5zm9AU?2Dl1&`zF;i-lkd$l*ab)ulwg^Ew& zaJ;ynjtdnZ7Ng!;EvPX41PSAUJy}p|Zc^y-wJxmJ1$_;tvhh(I{Pyz&9Xlcj9$&(V zZwH8j*p_L1`x2y0sEe5@EVnCCwl2q&$FHC~F=w4Y`>bVfRB{4KlctuoM}0x-&pEg` z3>4eUQxb=);dy*3I4pN8Iit|?Qrv}Ha4&f5S1>2Bd~2I=c0Hxhhl`MX7izZ~@yp{r zxMW?;{6p6~UIE%HXe{HF{=oVyB&77wlEnMb@?Q-}DbA)n{SfM$)1r&{kL85^IwQH1 zd4&A~me(^t^LPueX-bS1HPo#@F*k>n|E)z@ZjX7yU|3VUOmxwwZ%;Uk1^R-=8{vn2 zz}_x?CFNbH<%nQ^%l4O?d$+_t^UWy2!T5c-q}*MQ#x|biL|Yb?6X$+reHqWUp#R4@ zjQy?)xzjZK2>e8s^aXWk|0DF47@iLUk=AChZD;KnWBPJ;5I$k-_u!LT#V6WAy&N*S z$djkUueW)LK_7{)m)eSySTi#AV;|DF+YQEY)?g-(KBQ}2*|uvLxkX|&Vwt}~tzsp= zXT1Tp_rS+26*njG+Ymp$cYS1*znkYY{bQ06Sw54&(O)C2SY zj^MY08l;7~U*yUenryEy*HsA9LW1C`&AV%!@2p zn(K$$&@v^AxTm4zxDo^6t*teb3YHl?lt1tJv^2ejSfw=f!L*z+{T}jiM!>le=A*W@ z9`X`Cd5H~^)_gV&sguw(MDLvY9t!nX<#My}6zH4+{U%ZTL;E|8d*$RsUt%@>T!vwtUr33p>nP z_CWZTU*q+Uc>Xg`7C2X-J=%y?tomhFfnAg~<233<_G|5-c=~Mw)IbW^}SzQE2wwvLn8%eYs1I>sT&-fJ&q+4{JYt!IlnQ}zTpw0s)*jUn&GLB%s(H!hhJyvr>3Z+-||$ z;Bki#mfH|tw`5S(ZP!5N>rk)tDs(D;xA3nv{P#o7C{C@*Um;Sf>OC@0ulqXvL9|#r zY@h5=*LtYGhn7d&HAq|5<(js(HW$&rG(CnbT6K*M2AB-n(~w59Fz3@XVLJ}tqvDqB zl#V}l3ftp=buNT0wpX@)`RGH5S_Wab6uI)k;Z)3{3Fk7xc|F3}H{ld-`*>JJo+DrL z)kDIHKNlh1pWt4A`esXxhm)3T6!jZR;!BXb(i}|*bo(^)Wun{IJ1o0gNa9{=0~`0D zk09~s-iMsTqY1qio@02l{e_2M%xS0o!b9#V;a{k~@HDi~*C4O1nEnFegFe0#Wq8=f z$-@|}@?d`C^=TOU)7{rpx_hc|r|}crJyqO&ZKb>GjJsD-jXRHX6sMM9rB%f>vJ8&* zAxHACaUExLLSL3Wp#QJqxsJTa_!?A%oBf+77xCQp;|=Yny%c$W6#mulzY2HN{n5*X z^W>r5l56ahkGdO>?{&_KbAT5LdFYS+?l$@BN{40v$7T5IyXQ$+dlf4&oa=X){d z#`f|S_Z-kV(07x6k3qkwA1_7AbNNtR{J}o8z8Bet`h8SJw|pm|vz}o#njzD?KZ1GN z*T82-kX{dCCY19DH$(Fog!yv(9Y%ZIMGbQZXOGV02ySl{w?_-NoNv%sM0H(*Uu9o# zxC(CW5I4uf4M)n)jS=zZZ%7YHW;`hY>H!mGRP+St)7{KGuBr zhR54{_>hFQsvI71Zy37Sof~?$ATB&t^=R|srSAKs{A@QqI_>!vs_#}%Z#@g;Z5HvQ zpH! zw4X+fy^yxN<9Tay5D%~9vcLyuo9TRs8mF|v-yTwX(r^Ve;rMuJOu3PEuthoEP zi({S&VPL(#jC!BtI^;L@=^2X~ka#WX{fod`L(ezVedI;V9>H8Jn0o}p_a`alX@a@L zV_xn@C{e~W!oO7bT5sMZ609DK!Qq$335NMX=PMc*Z>PFmAh^pi+$841Q{24Zh6Q&D z{^nZ}&L`fQ;g$t=x!^b}db8-(9BP`Ny3(6 zG%r3S30scQy!d6Ae-stt`!`UpFwcH@=BF}F^Ws&Rzsfkxi%-q`R>o;w{ECwQ6dB`8 z^W;~S{Fmc2Z+=zDe>qO`=vSBgm*XBrTR99v^h|RtE6mUOr@15g@%3o+hGC|jSS>dJ zsZwoxf45*qEBsl;ZV2`n6@JaJR}E=B_)Nj->W%OwFZlDSA^?tkiE^$LKF1%dbGbI=Mvao9&b8c^E_pUek%ju`}-gAu~%9!sFJ!8fnWy~7|Q!{?aF$a8J zsSAd6*^Q{p*hjtz_k0tX=I;Z@H=KiP2>y2Iujy)|)J2Hz1IRzbj|=`L_jCt&ICu8Q~g@^y-@JXNjLj3S1$K^q%PYlI4wil)sY8=-YD3n zV6`8SW5YP?yP@VD_lO^dg|X5oMiBJNt>Ebq@K<7>67jm$jq67A9c}7rqnI~%BILs% zjxiT)$!}c5H*JS7nqKu|*gi(lUA(bdmG^e@xaaYKOaAUlGD5;ANu}uZg~E0268tIM z6L9$w2t$y}6wn?Y=NtLSdfMKIQf*#Ifb3Fj{-vxif6+Cx?!yfIV7(Wkq9UFxaFZI-9USZ7q>UbUV z(9pwhFy_zT$}wD6H|JcCKkuFd+yXGS3Zgv2;VNf6-h$BSjEDB8r%_)FAuV)fgt19| z!QXt+mPz$q4}E8GI=9z75$^a7pFL__K@)wsT|AB!{(qjtPwGC8rS0Nq4*G|Xt2jRs zd>T`pHtsoFHvm`17|iW9jV{0Br!P4N#3;_Kt;=!h$kxs`>_RHOXPxhy$K8A7I^lj+ zu9NP4a-G6^bMmM0cAVE4yaVTT4r}{(J?P#c*9EMq;PayUm|VM9Ma$=9te)Vt?=F_- z>)nI$d>vNlIrr^&!##`Z)rCJl4}a>L9_!B`qyy*o_OBmY@2oGZA6Q>pzia)>`km|R z>vyl;v3_p-Ti5T0oV!rSHN2d`D9gD9dOnBq2{?x&{xEX_H`T|QbNF{_YkI*iZgH-; z&CN|P@VXcOP^1_9@(nPi&D}X3!}1${c6weT%mDl|)Zrj6KLl{@>^Z%jE3Uu|XV{&d z#d%Z!Wk3%P3mHFaR1eykT)ZLca7JbpU)u<&z%#!yg3JjB3sDf z{&nZhy^dr#hR->H!O30X=p0g+96B2w7QN!>3q3Yd@DdLe^ic6yF_5zq8E zFVJ6v_kQ-G?jNQc9Egx%#3b%8>ns7rSegOOve^ZnMS;c^vrX>_F-)j^Nwg=|qNKf|Od1AgMu+GPmvFs>sAFlcbYBV7HX4-)8%OY;3yfI%-A z3@>~l-l2F+-?K$LOIYa(26&iP1Q=I`TOQ#$EKh~r+#iWv2S?BgF!TZ>Hs|DHvG|cR2Bf8@9!ppW1Yv z`_(r?*JCaB>aj2F^{K z=cx?mD9*h&PvTs|xq)*N=Xp*-;~d4g7w1WwYdAM>ZsI)8g%LPMaqh)=66YGu4V;@e z&pU^IcYYM-UYsX!uHoFkxry_<+w0&>H;R*gCvmRf+`zes^SlOabQIUUI8WkS!?}TT z6X$si_TEuk_u@Q>a}DPP&P|->HA+s7;<^{-Nt|mqH*jv^Jg?EUHj3+BoF{Rv;oQKv ziSxWh<;EzkdvTt`xrTEC=O)hc8qJ%dxbDSy66YGu4V;@e&r1^QJwJ-;UYsX!uHoFk zxry_a}DPP&P|->-6q1n=|*wx#d#9v z8qN)z{5!8%YjhOXy*N+eT*JA6a}(!z&31c7aovmaB+fOQ8#p&{p4TjSaunCSI8WkS z!?}TT6X$u&u4|*X?!|c$=NirpoSQh$YgXPE#dR;vlQ`FKZs6R+d0w;m<|wXvah}Av zhI7Mx?u%RQM}b>|Jn2kt)1L-&hoiFtk7G3cSARc%$8ZU&AK>1+6PogmRL6xayLUxYR2sfg@RvJoHd@ln5C=JO*|0EQ+j4 zY6{B4XR1_upxJ^1q(Bf?dEJ>SPWqynan64^aNz?FJj+EM{Ew2z?2Nz*>c+>NUc4NN z+3xV1jyq07p@;XvqICVI2lQU_7uvmVf*=u5C=Ar?)JOV=LZKpfL;ORfa*(Wwg~U8h zfS{Ewcm>B_?>Z9fok&o^n^}}84@*o$ba1E|Ky+ArLf;XB{6^IsCs(RhDJml*g`rj6 zT1Th6BhdgfrF%ZFqC#&Fa;b@kAYGy4@rcg!x$4*I4g3K=DZnA}2+%NDsOTkKGzYcv zEHrViKfyPKw9_rL4EhBigsULnh61Ty)r$|pk9a@;xdT4i09d}g7vF07s~jeAa4G`4 zUa4h7AC=QbJeUeY;c#uet zA_uMFLB+84qc=Q~7yqE7ieK{SxL^%-`TSo{3hhv1HWffV6cXVlVBYBLEeBjT4A`6OF>Chhe zv*qzV;g7hH{_a#i_@YRD<(}PLQ7ylui>K%@@j=v(J$eQu28>o0z$pQN--QS(~(zChA5_fXA_}Hau8VN z1rAlY6Np-g{sPCKi66-3oewtay22~H9wQ&V5oY1`QQSZ%WhRG)Ux><41j9`nl@yv; z9uRg$1g^QHMC_w^NLo+PCF&?$lxiN6-{=QThYsT)>M*yFxbq#H95^uI`k?`4IQ5j^ zvY^XN7-h(F4=oTppkA^bDCr`+^6(5^4xsRd?8gv?*cQEv10H-R2xuRDx(hE;5+C(0 zJcq0Ik9mZCW6T5IdK`xc^R}Oim9z=o91K^53$k!k}2K}nEzk6^1 z+L`^`$gYFCNF5nD-X9z|E&&fQK=~SKT(r@FYC>2I@OTWW0i_ncaql1Kqv4Y$&<6dH z1Mq=ELiBeXho>kv{EHU-5zp|J02~?%kHH75Y8hbqLOsJ6*xm257kV7z!HK>*AyEJw zfJi#%FT(4Cj2rsICy`hGC?bM7eH6G|eb)UFAMi_O*T`VciIEo%cI_D%jO>&8`qeR+cd{6s80p`NxZq+bl`RqB zf2i3U>7l_6$zBkv$+o6HnEF!1mDb0l`NHxg$Cv z6`$&ll@{;mCDd^02a>%XNuigbm*3NW@vc)ZMlLuJ!YWtfI{%FBCp{#|kA8@>KjOTQ zQQT0G9PGk7jP*rVAmS?FPou=WXV-gbt<`kHsU%h!nlUEDh=x4))|w z7=J;^;{;^n|5Jk#d-h;|jd)1EPlg`M2sqgZK7d1I`rm3FAj`A4k*QVyBZxWTfQ^5N zZRh&PE2jphP8C^@K9TBQyuqkoTpZ{j10?$6L!`?Pj~O){;U4D*P2^FoRHI+Ka z14s)NLMDR1D}D;bi_pQ!>YV@|899N*kb*R&L6@Mx6OXvTQ}zs2eDG22GUUR=57J*^ zjo=_FzXlGpBlA%(T_-4{at}PTx58GQ;BdQZ;Lu5uTF5sx;v7Fx3G#uJUn z?Up`;7jGcY(C0Ei$>)sv5J29$5$vXiTmyZf*h%J>9DtmIIKZu~e~jdK3-vEL?n|Ea z>mKI3{;ob!0EO^Ph)%i@ANZJ-xshEGa|o;);A_5<)HuNA=Ykm!HOz_No$X@FdQ5as zk3&O@wg@~QEqX<`1;QUjK#*O1Mc8(qh*O9As*q3@aG^ z6gL7u0EKYE?b^jQgU>j`lej`DeSrE88M88MQ4PC00uh0cUcQR}-ibQC9oPfEQJJWf zE2s^HW2rk4m+1W6uyB+M8yznA0(_)Yl-^&B8~=_ z82I=4)GLS#Uo+eE&jp|pH5j2J9ugpbn_TokfJ)cj$0|HO9Lk6QJR zD}IEcM0o;t57LjGBNn=G_=}c67K&VD@;q|lI2xCVLqv&64R|Jo3duNe;>1Bw>wiFG z&eMZ!@&&@*IaT!fq9-IYc!U)G%75T;K;`{H_N~Z&yi%dy{f&B0@<4D|dBt!tEq;RX z3Md56UZKB`RQ$`Bfhutz)YK4Q(7u<0S}LJ@#2)=uiFD^stJA{gmEvKx1z zr?^T)U^FJz!u2*<*n^WJXbCum&NGmiI%; zeiP=_Q#u@r9tkENcmzr0;Hl#VyCjyC%VMH1!AlLqen4@U+k%FhECWPVz*DHc(hD9? z4D|07jY1aHX!^;Md;IVw%B#NXk7x_nxxw=3G-ON>BcYRQ;Dti)n`CUxFsdf6R`iP> zQvX`{<{mX5WYM3gUnx}%5i48`l9VY1tgk(HPBK^zut-9^{0A9EU+H$c5&#VpEWhdp zc~A-&OgRm_szW9XwXQ}A$V6Y@Q2kXvy7qz5fXFj%iDuJJ#iAS(@uNIS7fe`Hs_8a4 zDsrG=9WNg<+yVukEw@v=Mbw$clP$=Fkc&=(S~-d!p>f6Cecx{;Wazy}Gc z0eLUx#mJ|A0q}>eeRSlSws|gQfkJQtPQ`^MUfJoCLwv{|Y9`IAR<@GFCko&BHysLi z4T%#`$2SGkL{3l{JRsfxkyoOgkonPRxD-H)JK-*yBzC(T~RGuI% z!jC#CK`)@+SF0w_MmawjFAfc)_l#HOov9bVl7G5LgcKrnx?w!B8Qb(u-uLKS_fK&0 z;NHux1)WD5C;iHU7~L@x`-lP)=)}(n;@^*drBDtvi@R|t*rqeTDI|X{&hU-@8r)PLYtG>xA0X)kzqrM>Nt^%9 zZ;~MM{~Z5Y$AIpSjNgC7hJ|1F!q(P5{2LzZ3EI|&x3<1CL=es|;WOB~F8kLn{NoqD z@cGYg{qy`FN2%2JGxOH+VCKm z+(&kFLj>9&)4sg}&!2%CZM(QTP|BzMiuZpa@b4+{-w(>Welzf2QQ~v2^f&xg;FtGG z=YHN-{C41%_wzmviD!Q&@XLEpbC2e;Xl%FJqnUf>y5A4{hf4n2fcu~R4Efc2HJyWt zyFN>P^8um0AZeVF54KlJbF!?5j}dk%N+ Qt#12RCoG_NY*#1zKl-IdC;$Ke literal 0 HcmV?d00001 diff --git a/tools/quake2/extra/qe4/win_qe3.c b/tools/quake2/extra/qe4/win_qe3.c new file mode 100644 index 00000000..297a58d9 --- /dev/null +++ b/tools/quake2/extra/qe4/win_qe3.c @@ -0,0 +1,605 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" +#include "mru.h" + +int screen_width; +int screen_height; +qboolean have_quit; + +int update_bits; + +HANDLE bsp_process; + +//=========================================== + +void Sys_SetTitle (char *text) +{ + SetWindowText (g_qeglobals.d_hwndMain, text); +} + +HCURSOR waitcursor; + +void Sys_BeginWait (void) +{ + waitcursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); +} + +void Sys_EndWait (void) +{ + if (waitcursor) + { + SetCursor (waitcursor); + waitcursor = NULL; + } +} + + +void Sys_GetCursorPos (int *x, int *y) +{ + POINT lpPoint; + + GetCursorPos (&lpPoint); + *x = lpPoint.x; + *y = lpPoint.y; +} + +void Sys_SetCursorPos (int x, int y) +{ + SetCursorPos (x, y); +} + +void Sys_UpdateWindows (int bits) +{ +// Sys_Printf("updating 0x%X\n", bits); + update_bits |= bits; +//update_bits = -1; +} + + +void Sys_Beep (void) +{ + MessageBeep (MB_ICONASTERISK); +} + +char *TranslateString (char *buf) +{ + static char buf2[32768]; + int i, l; + char *out; + + l = strlen(buf); + out = buf2; + for (i=0 ; iepairs ; ep ; ep=ep->next) + { + if (ep->key[0] == 'b' && ep->key[1] == 's' && ep->key[2] == 'p') + { + bsp_commands[i] = ep->key; + AppendMenu (hmenu, MF_ENABLED|MF_STRING, + CMD_BSPCOMMAND+i, (LPCTSTR)ep->key); + i++; + } + } + count = i; +} + +//============================================== + +/* +=============== +CheckBspProcess + +See if the BSP is done yet +=============== +*/ +void CheckBspProcess (void) +{ + char outputpath[1024]; + char temppath[512]; + DWORD exitcode; + char *out; + BOOL ret; + + if (!bsp_process) + return; + + ret = GetExitCodeProcess (bsp_process, &exitcode); + if (!ret) + Error ("GetExitCodeProcess failed"); + if (exitcode == STILL_ACTIVE) + return; + + bsp_process = 0; + + GetTempPath(512, temppath); + sprintf (outputpath, "%sjunk.txt", temppath); + + LoadFile (outputpath, (void *)&out); + Sys_Printf ("%s", out); + Sys_Printf ("\ncompleted.\n"); + free (out); + Sys_Beep (); + + Pointfile_Check (); +} + +extern int cambuttonstate; + +/* +================== +WinMain + +================== +*/ +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance + ,LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + double time, oldtime, delta; + HACCEL accelerators; + + g_qeglobals.d_hInstance = hInstance; + + InitCommonControls (); + + screen_width = GetSystemMetrics (SM_CXFULLSCREEN); + screen_height = GetSystemMetrics (SM_CYFULLSCREEN); + + // hack for broken NT 4.0 dual screen + if (screen_width > 2*screen_height) + screen_width /= 2; + + accelerators = LoadAccelerators (hInstance + , MAKEINTRESOURCE(IDR_ACCELERATOR1)); + if (!accelerators) + Error ("LoadAccelerators failed"); + + Main_Create (hInstance); + + WCam_Create (hInstance); + WXY_Create (hInstance); + WZ_Create (hInstance); + CreateEntityWindow(hInstance); + + // the project file can be specified on the command line, + // or implicitly found in the scripts directory + if (lpCmdLine && strlen(lpCmdLine)) + { + ParseCommandLine (lpCmdLine); + if (!QE_LoadProject(argv[1])) + Error ("Couldn't load %s project file", argv[1]); + } + else if (!QE_LoadProject("scripts/quake.qe4")) + Error ("Couldn't load scripts/quake.qe4 project file"); + + QE_Init (); + + Sys_Printf ("Entering message loop\n"); + + oldtime = Sys_DoubleTime (); + + while (!have_quit) + { + Sys_EndWait (); // remove wait cursor if active + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + if (!TranslateAccelerator(g_qeglobals.d_hwndMain, accelerators, &msg) ) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + if (msg.message == WM_QUIT) + have_quit = true; + } + + + CheckBspProcess (); + + time = Sys_DoubleTime (); + delta = time - oldtime; + oldtime = time; + if (delta > 0.2) + delta = 0.2; + + // run time dependant behavior + Cam_MouseControl (delta); + + // update any windows now + if (update_bits & W_CAMERA) + { + InvalidateRect(g_qeglobals.d_hwndCamera, NULL, false); + UpdateWindow (g_qeglobals.d_hwndCamera); + } + if (update_bits & (W_Z | W_Z_OVERLAY) ) + { + InvalidateRect(g_qeglobals.d_hwndZ, NULL, false); + UpdateWindow (g_qeglobals.d_hwndZ); + } + + if ( update_bits & W_TEXTURE ) + { + InvalidateRect(g_qeglobals.d_hwndTexture, NULL, false); + UpdateWindow (g_qeglobals.d_hwndEntity); + } + + if (update_bits & (W_XY | W_XY_OVERLAY)) + { + InvalidateRect(g_qeglobals.d_hwndXY, NULL, false); + UpdateWindow (g_qeglobals.d_hwndXY); + } + + update_bits = 0; + + if (!cambuttonstate && !have_quit) + { // if not driving in the camera view, block + WaitMessage (); + } + + } + + /* return success of application */ + return TRUE; + +} + diff --git a/tools/quake2/extra/qe4/win_qe3.rc b/tools/quake2/extra/qe4/win_qe3.rc new file mode 100644 index 00000000..06dab11e --- /dev/null +++ b/tools/quake2/extra/qe4/win_qe3.rc @@ -0,0 +1,693 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New", ID_FILE_NEW + MENUITEM "&Open", ID_FILE_OPEN + MENUITEM "&Save", ID_FILE_SAVE + MENUITEM "Save &as...", ID_FILE_SAVEAS + MENUITEM "&Pointfile", ID_FILE_POINTFILE + MENUITEM "Load &project", ID_FILE_LOADPROJECT + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Copy brush", ID_EDIT_COPYBRUSH, GRAYED + MENUITEM "&Paste brush", ID_EDIT_PASTEBRUSH, GRAYED + END + POPUP "&View" + BEGIN + MENUITEM "Texture View\tT", ID_VIEW_TEXTURE + MENUITEM "Console View\tO", ID_VIEW_CONSOLE + MENUITEM "Entity View\tN", ID_VIEW_ENTITY + MENUITEM SEPARATOR + MENUITEM "&Center\tEnd", ID_VIEW_CENTER + MENUITEM "&Up Floor\tPage Up", ID_VIEW_UPFLOOR + MENUITEM "&Down Floor\tPage Down", ID_VIEW_DOWNFLOOR + MENUITEM SEPARATOR + MENUITEM "&XY 100%", ID_VIEW_100 + MENUITEM "XY Zoom &In\tDelete", ID_VIEW_ZOOMIN + MENUITEM "XY Zoom &Out\tInsert", ID_VIEW_ZOOMOUT + MENUITEM SEPARATOR + MENUITEM "Show &Names", ID_VIEW_SHOWNAMES, CHECKED + MENUITEM "Show Blocks", ID_VIEW_SHOWBLOCKS + MENUITEM "Show C&oordinates", ID_VIEW_SHOWCOORDINATES + , CHECKED + MENUITEM "Show &Entities", ID_VIEW_SHOWENT, CHECKED + MENUITEM "Show &Path", ID_VIEW_SHOWPATH, CHECKED + MENUITEM "Show &Lights", ID_VIEW_SHOWLIGHTS, CHECKED + MENUITEM "Show &Water", ID_VIEW_SHOWWATER, CHECKED + MENUITEM "Show Clip &Brush", ID_VIEW_SHOWCLIP, CHECKED + MENUITEM "Show Wor&ld", ID_VIEW_SHOWWORLD, CHECKED + MENUITEM "Show Detail\tctrl-D", ID_VIEW_SHOWDETAIL, CHECKED + MENUITEM SEPARATOR + MENUITEM "&Z 100%", ID_VIEW_Z100 + MENUITEM "Z Zoo&m In\tctrl-Delete", ID_VIEW_ZZOOMIN + MENUITEM "Z Zoom O&ut\tctrl-Insert", ID_VIEW_ZZOOMOUT + END + POPUP "&Selection" + BEGIN + MENUITEM "Drag &Edges\tE", ID_SELECTION_DRAGEDGES + MENUITEM "Drag &Vertecies\tV", ID_SELECTION_DRAGVERTECIES + MENUITEM "&Clone\tspace", ID_SELECTION_CLONE + MENUITEM "Deselect\tEsc", ID_SELECTION_DESELECT + MENUITEM "&Delete\tBackspace", ID_SELECTION_DELETE + MENUITEM "Flip &X", ID_BRUSH_FLIPX + MENUITEM "Flip &Y", ID_BRUSH_FLIPY + MENUITEM "Flip &Z", ID_BRUSH_FLIPZ + MENUITEM "Rotate X", ID_BRUSH_ROTATEX + MENUITEM "Rotate Y", ID_BRUSH_ROTATEY + MENUITEM "Rotate Z", ID_BRUSH_ROTATEZ + MENUITEM "Arbitrary rotation", ID_SELECTION_ARBITRARYROTATION + + MENUITEM "Make &Hollow", ID_SELECTION_MAKEHOLLOW + MENUITEM "CSG &Subtract", ID_SELECTION_CSGSUBTRACT + MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL + + MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING + MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL + + MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE + MENUITEM "Connect entities\tCtrl-k", ID_SELECTION_CONNECT + MENUITEM "Ungroup entity", ID_SELECTION_UNGROUPENTITY + MENUITEM "Make detail\tCtrl-m", ID_SELECTION_MAKE_DETAIL + MENUITEM "Make structural", ID_SELECTION_MAKE_STRUCTURAL + END + POPUP "&Bsp" + BEGIN + MENUITEM SEPARATOR + END + POPUP "&Grid" + BEGIN + MENUITEM "Grid1\t&1", ID_GRID_1 + MENUITEM "Grid2\t&2", ID_GRID_2 + MENUITEM "Grid4\t&3", ID_GRID_4 + MENUITEM "Grid8\t&4", ID_GRID_8, CHECKED + MENUITEM "Grid16\t&5", ID_GRID_16 + MENUITEM "Grid32\t&6", ID_GRID_32 + MENUITEM "Grid64\t&7", ID_GRID_64 + END + POPUP "&Textures" + BEGIN + MENUITEM "Show In &Use\tU", ID_TEXTURES_SHOWINUSE + MENUITEM "&Surface inspector\tS", ID_TEXTURES_INSPECTOR + MENUITEM SEPARATOR + MENUITEM "&Wireframe", ID_TEXTURES_WIREFRAME + MENUITEM "&Flat shade", ID_TEXTURES_FLATSHADE + MENUITEM "&Nearest", ID_VIEW_NEAREST + MENUITEM "Nearest &Mipmap", ID_VIEW_NEARESTMIPMAP + MENUITEM "&Linear", ID_VIEW_LINEAR + MENUITEM "&Bilinear", ID_VIEW_BILINEAR + MENUITEM "B&ilinear Mipmap", ID_VIEW_BILINEARMIPMAP + MENUITEM "T&rilinear", ID_VIEW_TRILINEAR + MENUITEM SEPARATOR + END + POPUP "&Misc" + BEGIN + MENUITEM "&Benchmark", ID_MISC_BENCHMARK + POPUP "&Colors" + BEGIN + MENUITEM "&Texture Background", ID_TEXTUREBK + MENUITEM "Grid Background", ID_COLORS_XYBK + MENUITEM "Grid Major", ID_COLORS_MAJOR + MENUITEM "Grid Minor", ID_COLORS_MINOR + END + MENUITEM "&Gamma", ID_MISC_GAMMA + MENUITEM "Find brush", ID_MISC_FINDBRUSH + MENUITEM "Next leak spot\tctrl-l", ID_MISC_NEXTLEAKSPOT + MENUITEM "Previous leak spot\tctrl-p", ID_MISC_PREVIOUSLEAKSPOT + MENUITEM "&Print XY View", ID_MISC_PRINTXY + MENUITEM "&Select Entity Color\tK", ID_MISC_SELECTENTITYCOLOR + END + POPUP "&Region" + BEGIN + MENUITEM "&Off", ID_REGION_OFF + MENUITEM "&Set XY", ID_REGION_SETXY + MENUITEM "Set &Tall Brush", ID_REGION_SETTALLBRUSH + MENUITEM "Set &Brush", ID_REGION_SETBRUSH + MENUITEM "Set Se&lected Brushes", ID_REGION_SETSELECTION + END + POPUP "&Brush" + BEGIN + MENUITEM "3 sided\tctrl-3", ID_BRUSH_3SIDED + MENUITEM "4 sided\tctrl-4", ID_BRUSH_4SIDED + MENUITEM "5 sided\tctrl-5", ID_BRUSH_5SIDED + MENUITEM "6 sided\tctrl-6", ID_BRUSH_6SIDED + MENUITEM "7 sided\tctrl-7", ID_BRUSH_7SIDED + MENUITEM "8 sided\tctrl-8", ID_BRUSH_8SIDED + MENUITEM "9 sided\tctrl-9", ID_BRUSH_9SIDED + MENUITEM "Arbitrary sided", ID_BRUSH_ARBITRARYSIDED + END + POPUP "&Help" + BEGIN + MENUITEM "&About", ID_HELP_ABOUT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_FINDTEXTURE DIALOG DISCARDABLE 0, 0, 129, 53 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Find Texture" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,10,30,50,14 + PUSHBUTTON "Cancel",IDCANCEL,70,30,50,14 + EDITTEXT IDC_EDIT1,10,10,110,14,ES_AUTOHSCROLL +END + +IDD_ENTITY DIALOGEX 0, 0, 234, 389 +STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | + WS_CAPTION | WS_THICKFRAME +EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE +CAPTION "Entity" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LISTBOX IDC_E_LIST,5,5,180,99,LBS_SORT | LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP, + WS_EX_CLIENTEDGE + EDITTEXT IDC_E_COMMENT,5,106,180,50,ES_MULTILINE | ES_READONLY | + WS_VSCROLL,WS_EX_CLIENTEDGE + PUSHBUTTON "135",IDC_E_135,5,290,15,15 + PUSHBUTTON "180",IDC_E_180,5,305,15,15 + PUSHBUTTON "225",IDC_E_225,5,320,15,15 + PUSHBUTTON "270",IDC_E_270,21,320,15,15 + PUSHBUTTON "90",IDC_E_90,21,290,15,15 + PUSHBUTTON "45",IDC_E_45,35,290,15,15 + PUSHBUTTON "0",IDC_E_0,35,305,15,15 + PUSHBUTTON "315",IDC_E_315,35,320,15,15 + PUSHBUTTON "Up",IDC_E_UP,60,295,15,15 + PUSHBUTTON "Dn",IDC_E_DOWN,60,310,15,15 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,5,160,50,8 + CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,5,170,50,8 + CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,5,180,50,8 + CONTROL "",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,5,190,50,8 + CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,65,160,50,8 + CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,65,170,50,8 + CONTROL "",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,65,180,50,8 + CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,65,190,50,8 + CONTROL "!Easy",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 125,160,50,8 + CONTROL "!Medium",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,125,170,50,8 + CONTROL "!Hard",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,125,180,50,10 + CONTROL "!DeathMatch",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,125,190,55,10 + LISTBOX IDC_E_PROPS,5,205,180,50,LBS_SORT | LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | + WS_VSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE + PUSHBUTTON "Del Key/Pair",IDC_E_DELPROP,105,295,45,15 + EDITTEXT IDC_E_STATUS,83,312,95,30,ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL + LTEXT "Key",IDC_STATIC_KEY,5,260,25,10 + LTEXT "Value",IDC_STATIC_VALUE,5,275,25,10 + EDITTEXT IDC_E_KEY_FIELD,40,260,135,14,ES_AUTOHSCROLL + EDITTEXT IDC_E_VALUE_FIELD,40,275,135,14,ES_AUTOHSCROLL +END + +IDD_GAMMA DIALOGEX 0, 0, 127, 76 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Gamma" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,10,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,65,40,50,14 + EDITTEXT IDC_G_EDIT,30,15,66,13,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE +END + +IDD_FINDBRUSH DIALOGEX 0, 0, 127, 76 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Find brush" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,5,55,50,14 + PUSHBUTTON "Cancel",IDCANCEL,65,55,50,14 + EDITTEXT IDC_FIND_ENTITY,80,15,46,13,ES_AUTOHSCROLL, + WS_EX_CLIENTEDGE + EDITTEXT IDC_FIND_BRUSH,80,30,46,13,ES_AUTOHSCROLL, + WS_EX_CLIENTEDGE + LTEXT "Entity number",IDC_STATIC,10,15,60,8 + LTEXT "Brush number",IDC_STATIC,10,30,65,8 +END + +IDD_ROTATE DIALOG DISCARDABLE 0, 0, 186, 71 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Arbitrary rotation" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + EDITTEXT IDC_ROTX,30,5,40,14,ES_AUTOHSCROLL + LTEXT "x",IDC_STATIC,5,10,8,8 + EDITTEXT IDC_ROTZ,30,45,40,14,ES_AUTOHSCROLL + LTEXT "y",IDC_STATIC,5,25,8,8 + EDITTEXT IDC_ROTY,30,25,40,14,ES_AUTOHSCROLL + LTEXT "z",IDC_STATIC,5,45,8,8 +END + +IDD_SIDES DIALOG DISCARDABLE 0, 0, 186, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Arbitrrary sides" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + EDITTEXT IDC_SIDES,50,15,40,14,ES_AUTOHSCROLL + LTEXT "Sides",IDC_STATIC,15,15,18,8 +END + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 274, 212 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About QuakeEd" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,217,7,50,14 + CONTROL 127,IDC_STATIC,"Static",SS_BITMAP,7,7,83,58 + CONTROL "QuakeEd 4.0(beta)\nCopyright (C) 1997 id Software, Inc.", + IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,100,10, + 110,23 + GROUPBOX "OpenGL Properties",IDC_STATIC,5,75,265,50 + LTEXT "Vendor:\t\tWHOEVER",IDC_ABOUT_GLVENDOR,10,90,125,10 + LTEXT "Version:\t\t1.1",IDC_ABOUT_GLVERSION,10,100,125,10 + LTEXT "Renderer:\tWHATEVER",IDC_ABOUT_GLRENDERER,10,110,125,10 + LTEXT "WHATEVER",IDC_ABOUT_GLEXTENSIONS,10,140,255,60 + GROUPBOX "OpenGL Extensions",IDC_STATIC,5,130,265,80 +END + +IDD_SURFACE DIALOG DISCARDABLE 400, 100, 392, 181 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Surface inspector" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,5,155,40,14 + PUSHBUTTON "Cancel",IDCANCEL,105,155,40,14 + EDITTEXT IDC_HSHIFT,85,45,35,15,ES_AUTOHSCROLL + SCROLLBAR IDC_HSHIFTA,120,45,10,15,SBS_VERT + LTEXT "Horizontal shift",IDC_STATIC,10,45,65,8 + LTEXT "Vertical shift",IDC_STATIC,10,60,65,8 + LTEXT "Horizontal stretch",IDC_STATIC,10,75,65,8 + LTEXT "Vertical stretch",IDC_STATIC,10,90,65,8 + LTEXT "Rotate",IDC_STATIC,10,105,65,8 + LTEXT "value",IDC_STATIC,10,120,65,8 + EDITTEXT IDC_VSHIFT,85,60,35,15,ES_AUTOHSCROLL + SCROLLBAR IDC_VSHIFTA,120,60,10,15,SBS_VERT + EDITTEXT IDC_HSCALE,85,75,35,15,ES_AUTOHSCROLL + SCROLLBAR IDC_HSCALEA,120,75,10,15,SBS_VERT + EDITTEXT IDC_VSCALE,85,90,35,15,ES_AUTOHSCROLL + SCROLLBAR IDC_VSCALEA,120,90,10,15,SBS_VERT + EDITTEXT IDC_ROTATE,85,105,35,15,ES_AUTOHSCROLL + SCROLLBAR IDC_ROTATEA,120,105,10,15,SBS_VERT + EDITTEXT IDC_VALUE,85,120,35,15,ES_AUTOHSCROLL + EDITTEXT IDC_TEXTURE,50,15,80,14,ES_AUTOHSCROLL + CONTROL "light",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,10,41,8 + CONTROL "slick",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,20,41,8 + CONTROL "sky",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,30,41,8 + CONTROL "warp",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,40,41,8 + CONTROL "trans33",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,160,50,41,8 + CONTROL "trans66",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,160,60,41,8 + CONTROL "flowing",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,160,70,41,8 + CONTROL "nodraw",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,160,80,41,8 + CONTROL "100",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,90,41,8 + CONTROL "200",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,100,41,8 + CONTROL "400",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,110,41,8 + CONTROL "800",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,120,41,8 + CONTROL "1000",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,130,41,8 + CONTROL "2000",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,140,41,8 + CONTROL "4000",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,150,41,8 + CONTROL "8000",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 160,160,41,8 + LTEXT "Texture",IDC_STATIC,10,18,30,8 + PUSHBUTTON "Apply",IDAPPLY,55,155,40,14 + CONTROL "10000",IDC_CHECK17,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,10,41,8 + CONTROL "20000",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,20,41,8 + CONTROL "40000",IDC_CHECK19,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,30,41,8 + CONTROL "80000",IDC_CHECK20,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,40,41,8 + CONTROL "100000",IDC_CHECK21,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,50,41,8 + CONTROL "200000",IDC_CHECK22,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,60,41,8 + CONTROL "400000",IDC_CHECK23,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,70,41,8 + CONTROL "800000",IDC_CHECK24,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,80,41,8 + CONTROL "1000000",IDC_CHECK25,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,90,41,8 + CONTROL "2000000",IDC_CHECK26,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,100,41,8 + CONTROL "4000000",IDC_CHECK27,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,110,41,8 + CONTROL "8000000",IDC_CHECK28,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,120,41,8 + CONTROL "10000000",IDC_CHECK29,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,130,40,8 + CONTROL "20000000",IDC_CHECK30,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,140,45,8 + CONTROL "40000000",IDC_CHECK31,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,150,45,8 + CONTROL "80000000",IDC_CHECK32,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,210,160,45,8 + CONTROL "solid",IDC_CHECK33,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,280,10,41,8 + CONTROL "window",IDC_CHECK34,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,280,20,41,8 + CONTROL "aux",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,31,41,8 + CONTROL "lava",IDC_CHECK36,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,41,41,8 + CONTROL "slime",IDC_CHECK37,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,280,50,41,8 + CONTROL "water",IDC_CHECK38,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,280,60,41,8 + CONTROL "mist",IDC_CHECK39,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,71,41,8 + CONTROL "80",IDC_CHECK40,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,81,41,8 + CONTROL "100",IDC_CHECK41,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,90,41,8 + CONTROL "200",IDC_CHECK42,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,100,41,8 + CONTROL "400",IDC_CHECK43,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,111,41,8 + CONTROL "800",IDC_CHECK44,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,121,41,8 + CONTROL "1000",IDC_CHECK45,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,130,41,8 + CONTROL "2000",IDC_CHECK46,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,140,41,8 + CONTROL "4000",IDC_CHECK47,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,151,41,8 + CONTROL "8000",IDC_CHECK48,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 280,161,41,8 + CONTROL "playerclip",IDC_CHECK49,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,10,41,8 + CONTROL "monsterclip",IDC_CHECK50,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,20,50,8 + CONTROL "current_0",IDC_CHECK51,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,31,50,8 + CONTROL "current_90",IDC_CHECK52,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,41,50,8 + CONTROL "current_180",IDC_CHECK53,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,50,50,8 + CONTROL "current_270",IDC_CHECK54,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,60,50,8 + CONTROL "current_up",IDC_CHECK55,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,71,50,8 + CONTROL "current_dn",IDC_CHECK56,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,81,50,8 + CONTROL "origin",IDC_CHECK57,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,90,41,8 + CONTROL "monster",IDC_CHECK58,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,100,41,8 + CONTROL "corpse",IDC_CHECK59,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,111,41,8 + CONTROL "detail",IDC_CHECK60,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,121,41,8 + CONTROL "translucent",IDC_CHECK61,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,130,50,8 + CONTROL "ladder",IDC_CHECK62,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,140,45,8 + CONTROL "40000000",IDC_CHECK63,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,151,45,8 + CONTROL "80000000",IDC_CHECK64,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,330,161,45,8 + GROUPBOX "Surf flags",IDC_STATIC,150,0,115,175 + GROUPBOX "Content flags",IDC_STATIC,270,0,115,175 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Id Software\0" + VALUE "FileDescription", "qe3\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "qe3\0" + VALUE "LegalCopyright", "Copyright © 1996\0" + VALUE "OriginalFilename", "qe3.exe\0" + VALUE "ProductName", "Id Software qe3\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE +BEGIN + "3", ID_BRUSH_3SIDED, VIRTKEY, CONTROL, NOINVERT + "4", ID_BRUSH_4SIDED, VIRTKEY, CONTROL, NOINVERT + "5", ID_BRUSH_5SIDED, VIRTKEY, CONTROL, NOINVERT + "6", ID_BRUSH_6SIDED, VIRTKEY, CONTROL, NOINVERT + "7", ID_BRUSH_7SIDED, VIRTKEY, CONTROL, NOINVERT + "8", ID_BRUSH_8SIDED, VIRTKEY, CONTROL, NOINVERT + "9", ID_BRUSH_9SIDED, VIRTKEY, CONTROL, NOINVERT + "D", ID_VIEW_SHOWDETAIL, VIRTKEY, CONTROL, NOINVERT + "K", ID_SELECTION_CONNECT, VIRTKEY, CONTROL, NOINVERT + "L", ID_MISC_NEXTLEAKSPOT, VIRTKEY, CONTROL, NOINVERT + "M", ID_SELECTION_MAKE_DETAIL, VIRTKEY, CONTROL, NOINVERT + "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT + "P", ID_MISC_PREVIOUSLEAKSPOT, VIRTKEY, CONTROL, NOINVERT + "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT + VK_DELETE, ID_VIEW_ZZOOMIN, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ID_VIEW_ZZOOMOUT, VIRTKEY, CONTROL, NOINVERT + "X", ID_FILE_EXIT, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15 +BEGIN + BUTTON ID_BRUSH_FLIPX + BUTTON ID_BRUSH_ROTATEX + BUTTON ID_BRUSH_FLIPY + BUTTON ID_BRUSH_ROTATEY + BUTTON ID_BRUSH_FLIPZ + BUTTON ID_BRUSH_ROTATEZ + BUTTON ID_SELECTION_SELECTCOMPLETETALL + BUTTON ID_SELECTION_SELECTTOUCHING + BUTTON ID_SELECTION_SELECTPARTIALTALL + BUTTON ID_SELECTION_SELECTINSIDE + BUTTON ID_SELECTION_CSGSUBTRACT + BUTTON ID_SELECTION_MAKEHOLLOW + BUTTON ID_TEXTURES_WIREFRAME + BUTTON ID_TEXTURES_FLATSHADE + BUTTON ID_VIEW_TRILINEAR +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_TOOLBAR1 BITMAP DISCARDABLE "toolbar1.bmp" +IDB_BITMAP1 BITMAP DISCARDABLE "q.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ENTITY, DIALOG + BEGIN + RIGHTMARGIN, 227 + BOTTOMMARGIN, 387 + END + + IDD_GAMMA, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 120 + TOPMARGIN, 7 + BOTTOMMARGIN, 68 + END + + IDD_FINDBRUSH, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 120 + TOPMARGIN, 7 + BOTTOMMARGIN, 68 + END + + IDD_ROTATE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 64 + END + + IDD_SIDES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 267 + TOPMARGIN, 7 + BOTTOMMARGIN, 205 + END + + IDD_SURFACE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 385 + TOPMARGIN, 7 + BOTTOMMARGIN, 174 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tools/quake2/extra/qe4/win_xy.c b/tools/quake2/extra/qe4/win_xy.c new file mode 100644 index 00000000..75a03444 --- /dev/null +++ b/tools/quake2/extra/qe4/win_xy.c @@ -0,0 +1,306 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// win_xy.c -- windows specific xy view code + +#include "qe3.h" + +static HDC s_hdcXY; +static HGLRC s_hglrcXY; + +static unsigned s_stipple[32] = +{ + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, + 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, +}; + +/* +============ +WXY_WndProc +============ +*/ +LONG WINAPI WXY_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + int fwKeys, xPos, yPos; + RECT rect; + + + GetClientRect(hWnd, &rect); + + switch (uMsg) + { + case WM_CREATE: + + s_hdcXY = GetDC(hWnd); + + QEW_SetupPixelFormat(s_hdcXY, false); + + if ( ( s_hglrcXY = wglCreateContext( s_hdcXY ) ) == 0 ) + Error( "wglCreateContext in WXY_WndProc failed" ); + + if (!wglMakeCurrent( s_hdcXY, s_hglrcXY )) + Error ("wglMakeCurrent failed"); + + if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcXY ) ) + Error( "wglShareLists in WXY_WndProc failed" ); + + glPolygonStipple ((char *)s_stipple); + glLineStipple (3, 0xaaaa); + + return 0; + + case WM_DESTROY: + QEW_StopGL( hWnd, s_hglrcXY, s_hdcXY ); + return 0; + + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + + if (!wglMakeCurrent( s_hdcXY, s_hglrcXY )) + Error ("wglMakeCurrent failed"); + + QE_CheckOpenGLForErrors(); + XY_Draw (); + QE_CheckOpenGLForErrors(); + + SwapBuffers(s_hdcXY); + + EndPaint(hWnd, &ps); + } + return 0; + + case WM_KEYDOWN: + return QE_KeyDown (wParam); + + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONDOWN: + if ( GetTopWindow( g_qeglobals.d_hwndMain ) != hWnd) + BringWindowToTop(hWnd); + SetFocus( g_qeglobals.d_hwndXY ); + SetCapture( g_qeglobals.d_hwndXY ); + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + XY_MouseDown (xPos, yPos, fwKeys); + return 0; + + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONUP: + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + XY_MouseUp (xPos, yPos, fwKeys); + if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) + ReleaseCapture (); + return 0; + + case WM_MOUSEMOVE: + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + XY_MouseMoved (xPos, yPos, fwKeys); + return 0; + + case WM_SIZE: + g_qeglobals.d_xy.width = rect.right; + g_qeglobals.d_xy.height = rect.bottom; + InvalidateRect( g_qeglobals.d_hwndXY, NULL, false); + return 0; + + case WM_NCCALCSIZE:// don't let windows copy pixels + DefWindowProc (hWnd, uMsg, wParam, lParam); + return WVR_REDRAW; + + case WM_KILLFOCUS: + case WM_SETFOCUS: + SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 ); + return 0; + + case WM_CLOSE: + DestroyWindow (hWnd); + return 0; + } + + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + + +/* +============== +WXY_Create +============== +*/ +void WXY_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WXY_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; //(HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = NULL; + wc.lpszClassName = XY_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Error ("RegisterClass: failed"); + + g_qeglobals.d_hwndXY = CreateWindow (XY_WINDOW_CLASS , + "XY View", + QE3_STYLE , + ZWIN_WIDTH, + (int)(screen_height*CWIN_SIZE)-20, + screen_width-ZWIN_WIDTH, + (int)(screen_height*(1.0-CWIN_SIZE)-38), // size + + g_qeglobals.d_hwndMain, // parent + 0, // no menu + hInstance, + NULL); + + if (!g_qeglobals.d_hwndXY ) + Error ("Couldn't create XY View"); + + LoadWindowState(g_qeglobals.d_hwndXY, "xywindow"); + ShowWindow(g_qeglobals.d_hwndXY, SW_SHOWDEFAULT); +} + +static void WXY_InitPixelFormat( PIXELFORMATDESCRIPTOR *pPFD ) +{ + memset( pPFD, 0, sizeof( *pPFD ) ); + + pPFD->nSize = sizeof( PIXELFORMATDESCRIPTOR ); + pPFD->nVersion = 1; + pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pPFD->iPixelType = PFD_TYPE_RGBA; + pPFD->cColorBits = 24; + pPFD->cDepthBits = 32; + pPFD->iLayerType = PFD_MAIN_PLANE; + +} + +void WXY_Print( void ) +{ + DOCINFO di; + + PRINTDLG pd; + + /* + ** initialize the PRINTDLG struct and execute it + */ + memset( &pd, 0, sizeof( pd ) ); + pd.lStructSize = sizeof( pd ); + pd.hwndOwner = g_qeglobals.d_hwndXY; + pd.Flags = PD_RETURNDC; + pd.hInstance = 0; + if ( !PrintDlg( &pd ) || !pd.hDC ) + { + MessageBox( g_qeglobals.d_hwndMain, "Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR ); + return; + } + + /* + ** StartDoc + */ + memset( &di, 0, sizeof( di ) ); + di.cbSize = sizeof( di ); + di.lpszDocName = "QE4"; + if ( StartDoc( pd.hDC, &di ) <= 0 ) + { + MessageBox( g_qeglobals.d_hwndMain, "Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR ); + return; + } + + /* + ** StartPage + */ + if ( StartPage( pd.hDC ) <= 0 ) + { + MessageBox( g_qeglobals.d_hwndMain, "Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR ); + return; + } + + /* + ** read pixels from the XY window + */ + { + int bmwidth = 320, bmheight = 320; + int pwidth, pheight; + + RECT r; + + GetWindowRect( g_qeglobals.d_hwndXY, &r ); + + bmwidth = r.right - r.left; + bmheight = r.bottom - r.top; + + pwidth = GetDeviceCaps( pd.hDC, PHYSICALWIDTH ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETX ); + pheight = GetDeviceCaps( pd.hDC, PHYSICALHEIGHT ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETY ); + + StretchBlt( pd.hDC, + 0, 0, + pwidth, pheight, + s_hdcXY, + 0, 0, + bmwidth, bmheight, + SRCCOPY ); + } + + /* + ** EndPage and EndDoc + */ + if ( EndPage( pd.hDC ) <= 0 ) + { + MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR ); + return; + } + + if ( EndDoc( pd.hDC ) <= 0 ) + { + MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR ); + return; + } +} diff --git a/tools/quake2/extra/qe4/win_z.c b/tools/quake2/extra/qe4/win_z.c new file mode 100644 index 00000000..a7233c8c --- /dev/null +++ b/tools/quake2/extra/qe4/win_z.c @@ -0,0 +1,195 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// win_cam.c -- windows specific camera view code + +#include "qe3.h" + +static HDC s_hdcZ; +static HGLRC s_hglrcZ; + +/* +============ +WZ_WndProc +============ +*/ +LONG WINAPI WZ_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + int fwKeys, xPos, yPos; + RECT rect; + + GetClientRect(hWnd, &rect); + + switch (uMsg) + { + + case WM_DESTROY: + QEW_StopGL( hWnd, s_hglrcZ, s_hdcZ ); + return 0; + + case WM_CREATE: + s_hdcZ = GetDC(hWnd); + QEW_SetupPixelFormat( s_hdcZ, false); + if ( ( s_hglrcZ = wglCreateContext( s_hdcZ ) ) == 0 ) + Error( "wglCreateContext in WZ_WndProc failed" ); + + if (!wglMakeCurrent( s_hdcZ, s_hglrcZ )) + Error ("wglMakeCurrent in WZ_WndProc failed"); + + if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcZ ) ) + Error( "wglShareLists in WZ_WndProc failed" ); + return 0; + + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + + if ( !wglMakeCurrent( s_hdcZ, s_hglrcZ ) ) + Error ("wglMakeCurrent failed"); + QE_CheckOpenGLForErrors(); + + Z_Draw (); + SwapBuffers(s_hdcZ); + + EndPaint(hWnd, &ps); + } + return 0; + + + case WM_KEYDOWN: + QE_KeyDown (wParam); + return 0; + + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONDOWN: + if (GetTopWindow(g_qeglobals.d_hwndMain) != hWnd) + BringWindowToTop(hWnd); + + SetFocus( g_qeglobals.d_hwndZ ); + SetCapture( g_qeglobals.d_hwndZ ); + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + Z_MouseDown (xPos, yPos, fwKeys); + return 0; + + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONUP: + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + Z_MouseUp (xPos, yPos, fwKeys); + if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) + ReleaseCapture (); + return 0; + + case WM_GETMINMAXINFO: + { + MINMAXINFO *pmmi = (LPMINMAXINFO) lParam; + + pmmi->ptMinTrackSize.x = ZWIN_WIDTH; + return 0; + } + + case WM_MOUSEMOVE: + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + Z_MouseMoved (xPos, yPos, fwKeys); + return 0; + + case WM_SIZE: + z.width = rect.right; + z.height = rect.bottom; + InvalidateRect( g_qeglobals.d_hwndZ, NULL, false); + return 0; + + case WM_NCCALCSIZE:// don't let windows copy pixels + DefWindowProc (hWnd, uMsg, wParam, lParam); + return WVR_REDRAW; + + case WM_KILLFOCUS: + case WM_SETFOCUS: + SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 ); + return 0; + + case WM_CLOSE: + /* call destroy window to cleanup and go away */ + DestroyWindow (hWnd); + return 0; + } + + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + + +/* +============== +WZ_Create +============== +*/ +void WZ_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WZ_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = Z_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Error ("WCam_Register: failed"); + + g_qeglobals.d_hwndZ = CreateWindow (Z_WINDOW_CLASS , + "Z", + QE3_STYLE, + 0,20,ZWIN_WIDTH,screen_height-38, // size + g_qeglobals.d_hwndMain, // parent + 0, // no menu + hInstance, + NULL); + if (!g_qeglobals.d_hwndZ) + Error ("Couldn't create zwindow"); + + LoadWindowState(g_qeglobals.d_hwndZ, "zwindow"); + ShowWindow (g_qeglobals.d_hwndZ, SW_SHOWDEFAULT); +} diff --git a/tools/quake2/extra/qe4/xy.c b/tools/quake2/extra/qe4/xy.c new file mode 100644 index 00000000..5c8303e6 --- /dev/null +++ b/tools/quake2/extra/qe4/xy.c @@ -0,0 +1,973 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "qe3.h" + +#define PAGEFLIPS 2 + +/* +============ +XY_Init +============ +*/ +void XY_Init (void) +{ + g_qeglobals.d_xy.origin[0] = 0; + g_qeglobals.d_xy.origin[1] = 20; + g_qeglobals.d_xy.origin[2] = 46; + + g_qeglobals.d_xy.scale = 1; +} + + +/* +============================================================================ + + MOUSE ACTIONS + +============================================================================ +*/ + +static int cursorx, cursory; +static int buttonstate; +static int pressx, pressy; +static vec3_t pressdelta; +static qboolean press_selection; + +void XY_ToPoint (int x, int y, vec3_t point) +{ + point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale; + point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale; + point[2] = 0; +} + +void XY_ToGridPoint (int x, int y, vec3_t point) +{ + point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale; + point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale; + point[2] = 0; + point[0] = floor(point[0]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; + point[1] = floor(point[1]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; +} + +/* +============== +XY_MouseDown +============== +*/ +void XY_MouseDown (int x, int y, int buttons) +{ + vec3_t point; + vec3_t origin, dir, right, up; + + buttonstate = buttons; + pressx = x; + pressy = y; + VectorCopy (vec3_origin, pressdelta); + + XY_ToPoint (x, y, point); + + VectorCopy (point, origin); + origin[2] = 8192; + + dir[0] = 0; dir[1] = 0; dir[2] = -1; + right[0] = 1/g_qeglobals.d_xy.scale; right[1] = 0; right[2] = 0; + up[0] = 0; up[1] = 1/g_qeglobals.d_xy.scale; up[2] = 0; + + press_selection = (selected_brushes.next != &selected_brushes); + + Sys_GetCursorPos (&cursorx, &cursory); + + // lbutton = manipulate selection + // shift-LBUTTON = select + if ( (buttons == MK_LBUTTON) + || (buttons == (MK_LBUTTON | MK_SHIFT)) + || (buttons == (MK_LBUTTON | MK_CONTROL)) + || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ) + { + Drag_Begin (x, y, buttons, + right, up, + origin, dir); + return; + } + + // control mbutton = move camera + if (buttonstate == (MK_CONTROL|MK_MBUTTON) ) + { + camera.origin[0] = point[0]; + camera.origin[1] = point[1]; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + } + + // mbutton = angle camera + if (buttonstate == MK_MBUTTON) + { + VectorSubtract (point, camera.origin, point); + if (point[1] || point[0]) + { + camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]); + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); + } + } + + // shift mbutton = move z checker + if (buttonstate == (MK_SHIFT|MK_MBUTTON) ) + { + XY_ToPoint (x, y, point); + z.origin[0] = point[0]; + z.origin[1] = point[1]; + Sys_UpdateWindows (W_XY_OVERLAY|W_Z); + return; + } + +} + +/* +============== +XY_MouseUp +============== +*/ +void XY_MouseUp (int x, int y, int buttons) +{ + Drag_MouseUp (); + + if (!press_selection) + Sys_UpdateWindows (W_ALL); + + buttonstate = 0; +} + +qboolean DragDelta (int x, int y, vec3_t move) +{ + vec3_t xvec, yvec, delta; + int i; + + xvec[0] = 1/g_qeglobals.d_xy.scale; + xvec[1] = xvec[2] = 0; + yvec[1] = 1/g_qeglobals.d_xy.scale; + yvec[0] = yvec[2] = 0; + + for (i=0 ; i<3 ; i++) + { + delta[i] = xvec[i]*(x - pressx) + yvec[i]*(y - pressy); + delta[i] = floor(delta[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; + } + VectorSubtract (delta, pressdelta, move); + VectorCopy (delta, pressdelta); + + if (move[0] || move[1] || move[2]) + return true; + return false; +} + +/* +============== +NewBrushDrag +============== +*/ +void NewBrushDrag (int x, int y) +{ + vec3_t mins, maxs, junk; + int i; + float temp; + brush_t *n; + + if (!DragDelta (x,y, junk)) + return; + // delete the current selection + if (selected_brushes.next != &selected_brushes) + Brush_Free (selected_brushes.next); + XY_ToGridPoint (pressx, pressy, mins); + mins[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize)); + XY_ToGridPoint (x, y, maxs); + maxs[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize)); + if (maxs[2] <= mins[2]) + maxs[2] = mins[2] + g_qeglobals.d_gridsize; + + for (i=0 ; i<3 ; i++) + { + if (mins[i] == maxs[i]) + return; // don't create a degenerate brush + if (mins[i] > maxs[i]) + { + temp = mins[i]; + mins[i] = maxs[i]; + maxs[i] = temp; + } + } + + n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef); + if (!n) + return; + + Brush_AddToList (n, &selected_brushes); + + Entity_LinkBrush (world_entity, n); + + Brush_Build( n ); + +// Sys_UpdateWindows (W_ALL); + Sys_UpdateWindows (W_XY| W_CAMERA); +} + +/* +============== +XY_MouseMoved +============== +*/ +void XY_MouseMoved (int x, int y, int buttons) +{ + vec3_t point; + + if (!buttonstate) + return; + + // lbutton without selection = drag new brush + if (buttonstate == MK_LBUTTON && !press_selection) + { + NewBrushDrag (x, y); + return; + } + + // lbutton (possibly with control and or shift) + // with selection = drag selection + if (buttonstate & MK_LBUTTON) + { + Drag_MouseMoved (x, y, buttons); + Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA); + return; + } + + // control mbutton = move camera + if (buttonstate == (MK_CONTROL|MK_MBUTTON) ) + { + XY_ToPoint (x, y, point); + camera.origin[0] = point[0]; + camera.origin[1] = point[1]; + Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA); + return; + } + + // shift mbutton = move z checker + if (buttonstate == (MK_SHIFT|MK_MBUTTON) ) + { + XY_ToPoint (x, y, point); + z.origin[0] = point[0]; + z.origin[1] = point[1]; + Sys_UpdateWindows (W_XY_OVERLAY|W_Z); + return; + } + + // mbutton = angle camera + if (buttonstate == MK_MBUTTON ) + { + XY_ToPoint (x, y, point); + VectorSubtract (point, camera.origin, point); + if (point[1] || point[0]) + { + camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]); + Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA); + } + return; + } + + // rbutton = drag xy origin + if (buttonstate == MK_RBUTTON) + { + Sys_GetCursorPos (&x, &y); + if (x != cursorx || y != cursory) + { + g_qeglobals.d_xy.origin[0] -= (x-cursorx)/g_qeglobals.d_xy.scale; + g_qeglobals.d_xy.origin[1] += (y-cursory)/g_qeglobals.d_xy.scale; + Sys_SetCursorPos (cursorx, cursory); + Sys_UpdateWindows (W_XY | W_XY_OVERLAY); + } + return; + } +} + + +/* +============================================================================ + +DRAWING + +============================================================================ +*/ + + +/* +============== +XY_DrawGrid +============== +*/ +void XY_DrawGrid (void) +{ + float x, y, xb, xe, yb, ye; + int w, h; + char text[32]; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_1D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale; + h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale; + + xb = g_qeglobals.d_xy.origin[0] - w; + if (xb < region_mins[0]) + xb = region_mins[0]; + xb = 64 * floor (xb/64); + + xe = g_qeglobals.d_xy.origin[0] + w; + if (xe > region_maxs[0]) + xe = region_maxs[0]; + xe = 64 * ceil (xe/64); + + yb = g_qeglobals.d_xy.origin[1] - h; + if (yb < region_mins[1]) + yb = region_mins[1]; + yb = 64 * floor (yb/64); + + ye = g_qeglobals.d_xy.origin[1] + h; + if (ye > region_maxs[1]) + ye = region_maxs[1]; + ye = 64 * ceil (ye/64); + + // draw major blocks + + glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]); + + if ( g_qeglobals.d_showgrid ) + { + + glBegin (GL_LINES); + + for (x=xb ; x<=xe ; x+=64) + { + glVertex2f (x, yb); + glVertex2f (x, ye); + } + for (y=yb ; y<=ye ; y+=64) + { + glVertex2f (xb, y); + glVertex2f (xe, y); + } + + glEnd (); + + } + + // draw minor blocks + if ( g_qeglobals.d_showgrid && g_qeglobals.d_gridsize*g_qeglobals.d_xy.scale >= 4) + { + glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]); + + glBegin (GL_LINES); + for (x=xb ; x region_maxs[0]) + xe = region_maxs[0]; + xe = 1024 * ceil (xe/1024); + + yb = g_qeglobals.d_xy.origin[1] - h; + if (yb < region_mins[1]) + yb = region_mins[1]; + yb = 1024 * floor (yb/1024); + + ye = g_qeglobals.d_xy.origin[1] + h; + if (ye > region_maxs[1]) + ye = region_maxs[1]; + ye = 1024 * ceil (ye/1024); + + // draw major blocks + + glColor3f(0,0,1); + glLineWidth (2); + + glBegin (GL_LINES); + + for (x=xb ; x<=xe ; x+=1024) + { + glVertex2f (x, yb); + glVertex2f (x, ye); + } + for (y=yb ; y<=ye ; y+=1024) + { + glVertex2f (xb, y); + glVertex2f (xe, y); + } + + glEnd (); + glLineWidth (1); + + // draw coordinate text if needed + + for (x=xb ; xowner) + return FALSE; // during construction + + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP) + { + if (!strncmp(pb->brush_faces->texdef.name, "clip", 4)) + return TRUE; + } + + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER) + { + if (pb->brush_faces->texdef.name[0] == '*') + return TRUE; + } + + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL) + { + if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL) + return TRUE; + } + + if (pb->owner == world_entity) + { + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD) + return TRUE; + return FALSE; + } + else if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT) + return TRUE; + + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS) + { + if (!strncmp(pb->owner->eclass->name, "light", 5)) + return TRUE; + } + + if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) + { + if (!strncmp(pb->owner->eclass->name, "path", 4)) + return TRUE; + } + + return FALSE; +} + +/* +============================================================= + + PATH LINES + +============================================================= +*/ + +/* +================== +DrawPathLines + +Draws connections between entities. +Needs to consider all entities, not just ones on screen, +because the lines can be visible when neither end is. +Called for both camera view and xy view. +================== +*/ +void DrawPathLines (void) +{ + int i, j, k; + vec3_t mid, mid1; + entity_t *se, *te; + brush_t *sb, *tb; + char *psz; + vec3_t dir, s1, s2; + vec_t len, f; + int arrows; + int num_entities; + char *ent_target[MAX_MAP_ENTITIES]; + entity_t *ent_entity[MAX_MAP_ENTITIES]; + + + num_entities = 0; + for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next) + { + ent_target[num_entities] = ValueForKey (te, "target"); + if (ent_target[num_entities][0]) + { + ent_entity[num_entities] = te; + num_entities++; + } + } + + for (se = entities.next ; se != &entities ; se = se->next) + { + psz = ValueForKey(se, "targetname"); + + if (psz == NULL || psz[0] == '\0') + continue; + + sb = se->brushes.onext; + if (sb == &se->brushes) + continue; + + for (k=0 ; kbrushes.onext; + if (tb == &te->brushes) + continue; + + for (i=0 ; i<3 ; i++) + mid[i] = (sb->mins[i] + sb->maxs[i])*0.5; + + for (i=0 ; i<3 ; i++) + mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5; + + VectorSubtract (mid1, mid, dir); + len = VectorNormalize (dir); + s1[0] = -dir[1]*8 + dir[0]*8; + s2[0] = dir[1]*8 + dir[0]*8; + s1[1] = dir[0]*8 + dir[1]*8; + s2[1] = -dir[0]*8 + dir[1]*8; + + glColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]); + + glBegin(GL_LINES); + glVertex3fv(mid); + glVertex3fv(mid1); + + arrows = (int)(len / 256) + 1; + + for (i=0 ; inext) + { + if (brush->mins[0] > maxs[0] + || brush->mins[1] > maxs[1] + || brush->maxs[0] < mins[0] + || brush->maxs[1] < mins[1] ) + { + culled++; + continue; // off screen + } + + if (FilterBrush (brush)) + continue; + drawn++; + if (brush->owner != e) + { + e = brush->owner; + glColor3fv(e->eclass->color); + } + Brush_DrawXY( brush ); + } + + DrawPathLines (); + + // + // draw pointfile + // + if ( g_qeglobals.d_pointfile_display_list) + glCallList (g_qeglobals.d_pointfile_display_list); + + // + // draw block grid + // + if ( g_qeglobals.show_blocks) + XY_DrawBlockGrid (); + + // + // now draw selected brushes + // + glTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]); + + glColor3f(1.0, 0.0, 0.0); + glEnable (GL_LINE_STIPPLE); + glLineStipple (3, 0xaaaa); + glLineWidth (2); + + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + { + drawn++; + Brush_DrawXY( brush ); + } + + glDisable (GL_LINE_STIPPLE); + glLineWidth (1); + + // edge / vertex flags + + if (g_qeglobals.d_select_mode == sel_vertex) + { + glPointSize (4); + glColor3f (0,1,0); + glBegin (GL_POINTS); + for (i=0 ; imins[0] + b->maxs[0])/2; + } + + dir[0] = 0; dir[1] = 1; dir[2] = 0; + + vright[0] = 0; vright[1] = 0; vright[2] = 0; + + // LBUTTON = manipulate selection + // shift-LBUTTON = select + // middle button = grab texture + // ctrl-middle button = set entire brush to texture + // ctrl-shift-middle button = set single face to texture + if ( (buttons == MK_LBUTTON) + || (buttons == (MK_LBUTTON | MK_SHIFT)) + || (buttons == MK_MBUTTON) +// || (buttons == (MK_MBUTTON|MK_CONTROL)) + || (buttons == (MK_MBUTTON|MK_SHIFT|MK_CONTROL)) ) + { + Drag_Begin (x, y, buttons, + vright, vup, + org, dir); + return; + } + + // control mbutton = move camera + if ((buttons == (MK_CONTROL|MK_MBUTTON) ) || (buttons == (MK_CONTROL|MK_LBUTTON))) + { + camera.origin[2] = org[2] ; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z); + } + + +} + +/* +============== +Z_MouseUp +============== +*/ +void Z_MouseUp (int x, int y, int buttons) +{ + Drag_MouseUp (); +} + +/* +============== +Z_MouseMoved +============== +*/ +void Z_MouseMoved (int x, int y, int buttons) +{ + if (!buttons) + return; + if (buttons == MK_LBUTTON) + { + Drag_MouseMoved (x, y, buttons); + Sys_UpdateWindows (W_Z|W_CAMERA); + return; + } + // rbutton = drag z origin + if (buttons == MK_RBUTTON) + { + Sys_GetCursorPos (&x, &y); + if ( y != cursory) + { + z.origin[2] += y-cursory; + Sys_SetCursorPos (cursorx, cursory); + Sys_UpdateWindows (W_Z); + } + return; + } + // control mbutton = move camera + if ((buttons == (MK_CONTROL|MK_MBUTTON) ) || (buttons == (MK_CONTROL|MK_LBUTTON))) + { + camera.origin[2] = (y - (z.height/2))/z.scale; + Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z); + } + +} + + +/* +============================================================================ + +DRAWING + +============================================================================ +*/ + + +/* +============== +Z_DrawGrid +============== +*/ +void Z_DrawGrid (void) +{ + float zz, zb, ze; + int w, h; + char text[32]; + + w = z.width/2 / z.scale; + h = z.height/2 / z.scale; + + zb = z.origin[2] - h; + if (zb < region_mins[2]) + zb = region_mins[2]; + zb = 64 * floor (zb/64); + + ze = z.origin[2] + h; + if (ze > region_maxs[2]) + ze = region_maxs[2]; + ze = 64 * ceil (ze/64); + + // draw major blocks + + glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]); + + glBegin (GL_LINES); + + glVertex2f (0, zb); + glVertex2f (0, ze); + + for (zz=zb ; zz= 4) + { + glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]); + + glBegin (GL_LINES); + for (zz=zb ; zznext) + { + if (brush->mins[0] >= z.origin[0] + || brush->maxs[0] <= z.origin[0] + || brush->mins[1] >= z.origin[1] + || brush->maxs[1] <= z.origin[1]) + continue; + + if (!Brush_Ray (org_top, dir_down, brush, &top)) + continue; + top = org_top[2] - top; + if (!Brush_Ray (org_bottom, dir_up, brush, &bottom)) + continue; + bottom = org_bottom[2] + bottom; + + q = Texture_ForName (brush->brush_faces->texdef.name); + glColor3f (q->color[0], q->color[1], q->color[2]); + glBegin (GL_QUADS); + glVertex2f (-xCam, bottom); + glVertex2f (xCam, bottom); + glVertex2f (xCam, top); + glVertex2f (-xCam, top); + glEnd (); + + glColor3f (1,1,1); + glBegin (GL_LINE_LOOP); + glVertex2f (-xCam, bottom); + glVertex2f (xCam, bottom); + glVertex2f (xCam, top); + glVertex2f (-xCam, top); + glEnd (); + } + + // + // now draw selected brushes + // + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + { + if ( !(brush->mins[0] >= z.origin[0] + || brush->maxs[0] <= z.origin[0] + || brush->mins[1] >= z.origin[1] + || brush->maxs[1] <= z.origin[1]) ) + { + if (Brush_Ray (org_top, dir_down, brush, &top)) + { + top = org_top[2] - top; + if (Brush_Ray (org_bottom, dir_up, brush, &bottom)) + { + bottom = org_bottom[2] + bottom; + + q = Texture_ForName (brush->brush_faces->texdef.name); + glColor3f (q->color[0], q->color[1], q->color[2]); + glBegin (GL_QUADS); + glVertex2f (-xCam, bottom); + glVertex2f (xCam, bottom); + glVertex2f (xCam, top); + glVertex2f (-xCam, top); + glEnd (); + } + } + } + + glColor3f (1,0,0); + glBegin (GL_LINE_LOOP); + glVertex2f (-xCam, brush->mins[2]); + glVertex2f (xCam, brush->mins[2]); + glVertex2f (xCam, brush->maxs[2]); + glVertex2f (-xCam, brush->maxs[2]); + glEnd (); + } + + + ZDrawCameraIcon (); + + glFinish(); + QE_CheckOpenGLForErrors(); + + if (z.timing) + { + end = Sys_DoubleTime (); + Sys_Printf ("z: %i ms\n", (int)(1000*(end-start))); + } +} + diff --git a/tools/quake2/extra/qe4/z.h b/tools/quake2/extra/qe4/z.h new file mode 100644 index 00000000..5e3545a6 --- /dev/null +++ b/tools/quake2/extra/qe4/z.h @@ -0,0 +1,42 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// window system independent camera view code + +typedef struct +{ + int width, height; + + qboolean timing; + + vec3_t origin; // at center of window + float scale; +} z_t; + +extern z_t z; + +void Z_Init (void); +void Z_MouseDown (int x, int y, int buttons); +void Z_MouseUp (int x, int y, int buttons); +void Z_MouseMoved (int x, int y, int buttons); +void Z_Draw (void); + diff --git a/tools/quake2/extra/texpaint/docs.txt b/tools/quake2/extra/texpaint/docs.txt new file mode 100644 index 00000000..f50759e9 --- /dev/null +++ b/tools/quake2/extra/texpaint/docs.txt @@ -0,0 +1,38 @@ + +Texpaint works with three data types: + +Skin textures +Model frames +S/T mappings + + +Skin textures can be either lbm or pcx files, and they will allways be +saved out the same size as loaded in, even if it is larger than the +active texture area. + +Model frames are alias .tri files. Adding support for 3ds would not +be difficult, but it is likely that there would be coordinate problems +unless the entire model was done completely in 3ds. + +S/T mappings allow a skin to be mapped onto any model frame. A mapping is +generated from a base frame and a texture size. If a coords.txt file is +not present, texpaint will generate a default mapping that is compatable +with the output of the old texmake. New skin or remap to skin will +generate a new coords.txt file. + + +Usage +----- +A three button mouse is required. + +The left button paints with the current color in either the skin window +or the camera window, or selects colors in the palette view. Ctrl-left +click picks up the color clicked on in any view, making it current. + +Right button dragging slides the object or skin around. Ctrl-right drag +to move in or out on the object. + +Middle button dragging rotates the object in the camera view. Ctrl-middle +drag to change the roll angle. + + diff --git a/tools/quake2/extra/texpaint/resource.h b/tools/quake2/extra/texpaint/resource.h new file mode 100644 index 00000000..7c26da1d --- /dev/null +++ b/tools/quake2/extra/texpaint/resource.h @@ -0,0 +1,58 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by texmake.rc +// +#define IDR_MENU1 101 +#define IDR_MENU2 102 +#define IDR_ACCELERATOR1 104 +#define IDD_NEWSKIN 105 +#define IDC_WIDTH 1000 +#define IDC_HEIGHT 1001 +#define ID_FILE_SAVEAS 4003 +#define ID_VIEW_MODELLINES 4006 +#define ID_VIEW_MODELLIGHTING 4008 +#define ID_FILE_OPENSKIN 4009 +#define ID_FILE_SAVESKIN 4010 +#define ID_FILE_SAVESKINAS 4011 +#define ID_FILE_EXIT 4012 +#define ID_FILE_OPENMODEL 4013 +#define ID_FILE_RELOADSKIN 4014 +#define ID_FILE_NEWSKIN 4016 +#define ID_FILE_OPENFRAME 4017 +#define ID_VIEW_SKINLINES 4018 +#define ID_VIEW_MODELINES 4019 +#define ID_VIEW_TEXTURELINES 4020 +#define ID_FILE_RESAMPLESKIN 4024 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 106 +#define _APS_NEXT_COMMAND_VALUE 4025 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/tools/quake2/extra/texpaint/texmake.aps b/tools/quake2/extra/texpaint/texmake.aps new file mode 100644 index 0000000000000000000000000000000000000000..5a63f6cc81037601ec654473af83084e5fb92dea GIT binary patch literal 33472 zcmb__3%F!gRp#n8h=>>l;tVsNXmFTFgv2_hs_wmoQ8;z#)V)Pl)v45@Z{Mc1CND@2 zoka40@U+9{YsMMJahw@Z5fMd5LP#J;c*#@EHwwN%UV#Y8Q}8jPI1hXNwf5O(uf5N% z8|Rz3-`9O_?f>7;v(MgZueH}IBBBfN@7y`_4}W?;7vs|t@o$gzsgK|1&K;@nN1Rvv zK|gqwX!oh7o_os`&$%W&b<54C&)n2Lb@Mg1e*YDxufLi9xDLRjH(tg32QCZCyPuP( zMXtOjNXirF#%pf6;g%b(y5`br36+ip^Yx^dt`bUG2|dguq)15VYfVCy=f${~XUlTV z#11{2)7Qh%xL7Z;<3+ZhPOH_Xuao5CqhfzODF?-PJen2)ZP6nd(C*%HG~MNlJM{Ig zymD4d7sp0Z272^J2XI9dkhJIP3JpgUX06Z zU@Pg+qa8FY_HFtW{Uevog$?J~q~OA~=`n)H2r%6aK(a%Rb%<164NcOc3mmd6PApew zMFplU`X*P^yjWzD+1L(3+M$0;w9aOW^%U9GfXmf9FV@Gi@v6XM>e4rBJTE7cY&xjm zPAl!w<9&R(oR{M|d#gp?qVdJSq_DYpvV1F%ol{pl>sCxFnNdfcK+ivYz4>&MjvQaC zj~DaBsGP1x(_u*oM(D_BP#(iy{iFCR&!(7Llv2*0vVJ*VQkw?+VO}if2h^d0Ka6&# z<-DLS4f)dnrqveh@}JX^wrP+5%E#rRpdES!f7mO=GwRVX0oIFUwjAa3q)U>E>GGp! zBj)~*ygy&8voT6ukBi}wTDK;xR%?tBG_)*dKvF?^9x@+c3IoGLMXslMSif8@%L%|8 z0l&)wv*`hlp&*x42s%C}=C&a%v}8=*<71{JEi`3JPxB$$lor}DrlG`rO$IH=dfmXKAlraq|U^qVLbK6^J#h8jZwak|5$qIP{>i`@2wX_F< z>;T!VkiF5Mz@(Usv%CHO5lPorn1VGjmPNh5Ix{4?N^vgTiqMitZF`0?K)9q z;3=f}b?+;>?fyZ5AVoWJ~F)09xd89#CLyx;nth<8uRb=$ZhU7d+>Xt4q%c zpkvuIGuReATd+kj%VcN7ZhM-JWWy8d(E#hpY_?vGmSdjU1s)o`++m}^xR?}+MYda^ z3H_`?dFA3A!egZL3dg9+UKf*oF&OYRDz&ufm5zn=eufFS#yeD1)1g;6xa>c}G*G>R zXlR#SE!~p69h)8(jKzpv=TdpgGsy|v?vl;&EA*7^aOu2n8+x1W^pn@vvL!=@Uhj|@ z#$~-ImMdO(QF)i{Qs8`q*I1!j^o9U6xwh%9-lI1< zd^HI@y~zRGw{>354(gut>0SjF*l#DJ6`RF|nuo{_+-Wvg{q3P56B49N(IlVsuR)aI3Uyp#*=oIuD5wIGb zA^oNgjx+m&hjhO{#bC5t=i?%i^(TRh_gg_agc37j(u96nVVGw!CTU6^P{}JZh0->C z(4`Kst{QTOe#a%x&>S<7A^!btkiLf8dCX+mqTdU_#jMCjS=F#@`hADbi&>FXjo6_- z@PKM}FOsxJf9Q|}&J+34bu^H?X(#kCjpf-Q&jw~F+9`cpV@p2Qh@`+Xu-&FlG*A%;1ntlR8ePoBIC2Qm zrB4dN%QXbs>M?a%^w~OD&L>RnB=k8+<<+0}#Nvb$(n;y_E}b80VWv%|Okwh=Q>-4^|oB=b_a zcF76-wImPA`2>>S5LHVBTP^w<0ZI($Xu5!~V;>fzSo*sflXrq=pX>)IP8a{f$Iu%) zz^0ixA^z}zr>XH*Gi}`)C4B=!zk8%i~msX2)4JP!B0%HHfImHcD57{20 z5xd;=@CYBP0iHG%zWRj4?#D z-|hjU>1a~tO6f@+n4M5yn=aNMH`uH%rp69^hlaV?8t&4QHC)e^A%^@Z8o@Cg!mjBC z^b(h7Y?&>NjYnp~7(z91sRJjFlJ`bqS<{EfkXjBJKqJ5!n#H2Td6|c2kWuPzQBhz? z1H@-e>N<$!7nbx4l+c!gum=HI%5sBjDQ!D!H5Jj88w03KI}WlXvQT8;4)q)yzE8;B zrKdW4HDz(tsFqCjE&478^O;eSq2_s-O`ff%<+_;9afHZ@L)gmtRfn*(_ALoYk`i*` zYBqz00TmP{@?y4xUP6k)Mw>fktw{+;DGeNHQcN)1VL5Fo9A$+CFC=tm=m;|wX3Hrz zNt%JZVdT(qilc=rD#I4`hi5osxnDXYrDG0}5*ah6B4ljSSi>UXG6A!OPdQ+8XrdWt zQneqLR~C#eP2&txz!sGOtY%JUn`Qxu(_B6BogKP7fR|-GB|ANuI}}G278+PzIa(Hc z>Kj6(LB}0K_7Pss4VKWp!?JuiIu0?O6;c(R(g}y>W)rDoAe7vu1BYg-CCem8?$Ak> z42{}KWFi1vdZq)0^YWw|lK^bdDF@)a62&QRM8LM`dmSdn3GSZ3c4+M|a|V&l8?;CN z(xH+wTPQfAD+0JWrzlRJu5=uhMHH6PRSuKNA!4j~+^d!k=xRrp6w8dC8uoq`0Za=E zdX{4hM%ZK(IHYGgus>Q(vYEzvExOj>A{rR&rYfVC&}qk!v#?i0O8?5iBKdMT#b9|b zGpk6iLuVXgH9a;h_ooi+(sd4?TXekxMbgqO+ol^FI+{Wyi%mCQ&F955H|t_= zho0M{@Hulik^}p&)$7rXn<)#(Uoy_UjBc_tmK{xH{4}bg|Bw&x&vTR^7D+6D%W}lE`D=vl^+>``+!3!Mf>dEIgAV8sKYwFMo6^-W&WRdka zo15j1&-^b^gu1|Vp*bjd=1d(xV4?tj~^dljIvujG5el(;kme`|q*OlajVmkD%L(V)K zjLLO?1(mnV$Rz2~zX?hG137r2gf0595M0%r+@^mUg8H3EU`hFRAwj=atT6a-N2s1s z{ZiBm5TCpM!$#gLTkgrYLNNHr25T_Fv>&dFvNpkK{697*MjnGrCKDkk!QuR;Hj(z{ zSXE7J9r{lV7KYXcH?FWQ{pZazRooW+7soR;khR%Fr8?}LKjZLfsPH=D7&SGDvSG3V z-K66{puz5mN4=0mEZIrv=N#J4aImO0*96<=D;(qshZr^*R=KzD;&|^oubPZ~J(Pnwin7V@!8KMXUPsOOCT! z;MA*yPt&uUe%W!L(2Q{g^cu&hdXL$cXLB>Hb_)6xM{wOY>#eD0NUv>Bu-T5*Z0i&X z_S!of#l9=T8B~)TTkV~WQdK031$3OIl$2htD7>go?Yft>=nVk|5w)0$ac7uh3EdsQ zJYd5Tnjk4VOX;3~z>}?hO|v$=F~E64fpm5tdz>kxLvIR5)oVH^rXw*Xp($OuHz3&o zu~KQ0ZPA+p&K#!!Rt3urZ`SK_X7jckYB65!mYMNzO04lU`?eF46Q=e{0^ z9GYYqy)}Rrz>OXVx%>3C0LBgllQf$O0O$1f0OnP#Uequ%-VxwMiBl(ME$E#N%I4T- z>*w5W(YpdnKj(fz?+##I)XM4DEC~IS-V@-MUFEPI`F@+;8xUleE|W3YV~Qu zq~E3YH}M>53z2G*{ucdu6JO+e#f0rXC}5j@!x9$jGKaPz&&I`SI$AE)GuR}@rl7n< z_d8ytPpK4R!xWmz4>+_kw_?7Vtv-da@`DaW**WY%3Qp;F91P{pNMUXIU5m}ui_6D$ zH5XxryO3f@|Bz2HY8_sKAj9tSB(npWVuk;(PcA02-*wttX=ejs>}Fsws|8AMv@P@wnK9EW&m#)5b1+)TfAf8MhzS^Ku{Nwc!vulzC@U z9I!s-lc5l(UPUb4tg8buY`Mk;~GZj6Ug8 z%0WMurB@z^?LnVD<q9o-btotz%@xr-^xqkC8|8@o)pGoU~5$-MGouad(Gu3ngd zDd^KatC~1IYe=8*S?DT+vkbGQTBuWOC4cI3Fuv>R?AmM|wv|8g=`uXWQ#`iIS1{L^ z2iHsKvpx+q&&tJ!)d)DrnDXVtOM7kloX_QTPi9tRd~gE%yw8>nE$28t;KWi@-=#13 zB<|F(u=BaMMPKys(G-&ovu3&G{>T{jw&_bgsTvjBlPYjFGJC3_?$Dq6)aoV#PiiRn zV*TjRm;Ef}_4BsT6eq>6_^f_e9-CzIV}W|iG^0;{aTpuNOK94vA<|N&KzP9l&Vb$09A&Vw3o)4_A60?n`BR9;VnT{?2FNnP4Hs zdtj7lDfWuL_Zip;xE8sH#0z1+L+5;kS=ClkPmh>l)1afZWq)tEbf*1bI)J)A0C@$d zbZ6-R`u+gsU7n|RA&Op<0HuFGf!Mj{zXAiO{sR(T&i-fs*+qtJ0NsB;@E`sFy8nPs ziSu&2FokT>BLfZ>GU97z&`a4DVz5KsU};#)um|+Z6S#5KqQ|;qqfbL>LKnDHIlHqW zKy(vq>G>xiC=@=RLk+^lp2sx^c*GUjrhnQ%EA406>d-&q>tB2qV~l$cC0hw$fJx}_ zlDt1U+0SwowvgDSZ?TD$sRD@|`c|6=)7xml+ZU3%bfK$sne}-+<*RcBZP61fI$&!T z>yrlKU23E1{%)VrY%P>wzTRf$7qKxbEp}4v4%0$rSDc) zWk_RSi@wJJq93z1UPia+X%1z@s8v_nsK5DRC0-bD-PVvjP1$w3i0An)L|pSc?Y z;X?Gd$|T1ODAygs^uXL_F66_xcCg~^uE)M3jx=GN4VN)OUe z8A8QkUn=X+EQF+i&?n=nqHUlQx6eb|gSayffX;p zt486ALa`C&N2k0Z~(zPC`g;0 z1p5lM?LIC;;NmN?(Q`v= ze~*MgXKF9~6(oL4ArIIOBK4GCPk>oqi-KM-S7J%?`dYyg}2$coL|9I`loa%mzD99XCo9Vixrr( zKNsR`Z8O&#P{j_tB8IyHdi3)lLClIpT|`E&3>l+o!0FR3gdD?g73K7*kYbB*qyhb6 zNUCa*%j9Nk3wm`(vL%@dyoNTUUkYg$U9$-DGs1iM%OL^RYs)bUD01?`T|IhDNa-)9 zL;D2rZvILHht>+0xTF<$IbR!L)IG+l`ML`q%rYTQc}VweV%gPzc`%;5+3_j_f?%aiFCggt zs*ghmUh6dhR+G0h8CH>4K-|5r2^%x93@;?!w>AmZ3~eY~dRvoHT@phdw&?8+HmlNX zChE}w67D-9*jn9OC~%?iosPo;y{@xo^lMGX&)uhYIZ8Exu7I509Yy^z2K1f=%j^{P z>iG~C*66*CWL|lZhSq$+7I;GMi{pI97I;eUcQ~7O)_fQc4EI%jGr)KQs4v@dIGVDQn%nu`mF${%PjSXJkgDg~tG4>}GM z6Gr7YgrbKv6HwxcCAEO5;`cNUGV~l?C1!zwq2l*F5aywwF#*efz)tZ88Xt^~kJ$OC ze{iyxi{8F~sp1bc1tMlSG;gch?6MC1QG|rOPI0>QALUXj?g6*vjXs|9ok4QnE3^;b=%u^iF zr!(mYo{b}trowA4a z<*V#ik)B$?Yhckng~DbTZnN+o69AXabNHu13CY94>Ok=#zWaQe!YimGy{=ADUdVUV zi9E8xySY@ zbAcS=S-UIWTPKTuvk2sDZhr0gJjgu^Tt@~@G(y&y{2w%a2le>bQSiDP^i4On@-csH z*fe%amu~!jeJUHqL`K&Qrygt`8UBa)btV4!F#*04{`v6Xf3)-A-#l8%tAFs+QTABU_Rx-^wZ}H4jr;X`_uFVa>mG&IF_BjgG|18~w-; z_=JBgKGh!Sb&B;$7qazAmk+g9x_mNT>GG#|rORK|D_uT_%DRV&$m(^q@kA&(9s@dS zdCHmsn)CV(z4DR8#&j?t98lR2I!_Y4H;-RO!5#+84LU!Bqh=^vCG~}PvthGhP&KV- z(oy|0V6}NvMw?U*Kt<3doo04r(orCvxp*hU%z;W306UNDj|PwvC8g?z9YUrn4ROWa zE5wZ-8IoqlE5nY9i6Fa%E>J6$gQoGF$x5-TkU+7lkU+7lkU+7l5OZu*isc5T6w3{) zRxCFVt8Rt5v4J_oas$$e^rz@cKfL1-wJqYS554q-F7S+T5;reaxvoWm)WHJ}yCDqSm|2f!73r2ZePu)V^ zJfxL)q!EgUJrWZJxy{mOddIa(S4>$}8;K`nNji$sZuM@Rly-xHE>qs`WMoi}llTE{!&OIb%I#+~<>0F@=)49ex)42j7rgMd| zyr)g)3gRhSy?|_1SAxO7+_5&MbCqL*>0B`)rt=z&na&mHo6Z%`G@UCjG@UCbG@UD` zVLDe>XgY5|&UD^@tm!-iYSVcL)CTfxEC%(I4@~DZvcYt&@VM!G6QMSp*Mzv~yoRHu z^8nSR^BUS<7L4IyG%#kt7;Lo!#w=Jf8fL*7i9|zDSR@*XLRn(wMLCFuq8RL6FY4}Q zG!(^(MMF_A-m7>t6mabBXTuCwS<~$rP;|gRCIW;d*ABp}FHnW>4rb^gSy?(K*D*vo zI)fN;p=5H=P*iC~cvh%L3bs%|O=U8j zXm85#z~ic%!u@C{KA@waD5Mz;MS-H1lWOn?J;74OK@>{@;~{!*GdhYXwMq}7qj*>l z9mT^M(NUTxOlGYAN9+{4lvQ0M3c(90j?CQ=qM`PkB*`M zFFJ}z=Yu_DXX_z~D(nOh6^&GCU*K4D6jKTdv?>frrGt>WZz|a~-ss=0t45I^I*KVK z9v#JD@|=wbiH7lwp#Vc~?2z-lp%86GM+q2}IYC87aRjmW)`6-xItnl&qt}=G>dlU$ zqcq_lI!c6qapd`eyS0(*HbO{SDrJi=g;uj@KRQYrSJ6>Gz|zZ?#2Yc`LP*D? z3o#RYL1NN{kd8?gVk#zG2*C=(Tzmj`R&^*B9}Ggdcp$e<$7)gYgqy-` z)Ub@OYiT{XIh2c6E)Lc@l#7Rjpw#Bc_6ca#0WqUwoc4kUSsT z2V89cQr*qr8?Y){7|KOKwnQDuMZuMTScgWEP%a9Og>q4_4&_oO9~R1`CI!AKVT2X0 z>$T>(5z0jsw<(m1qQpbFD1t0Qekd1(2BBOO5`=P5h?E$Fa`E73C>M_bJ7hDI%Lazb zn~pcbr3Gr{Ae2j(SzU-~A(Tr9`=MMEYV;U#`&@@|Q4HDic=M5l!Dmrna?3Fc<)Uz- z1F-@eqO5p}j}GOcGWnrg6yS$)Q2^d6IRnb25Dw*{FgXk9P%a9q9KRf@6hByy%u!H< zViCFCzRUv0Lb<34Sa4GLMY^~7rE(7G;DvHgne81q_61d;Toj`j%0+?EP%a7=IVKj$ zMR8)GTof!~JD1~!a#4&(C>Mn`L%AqW#6s0|`0Xjw`hx3_6Y$80QFPb}4&@Rl#Zq)A zmzuUYl#8M`mw(tDg;JSt%%0&}g zQ<|Y%qP$2b7sbO07Y*g2C|0-4qfiHXQIDe@pI9gtRZcUMO9S+(P;VV>K8B%OR9=JO z##bH6r2(RwI!=rC;9Pc1Q7fLU-CXhVLb)_5iiL7%kaQ@Q2B<^1G(bDyc}?d~E)9Zy zuPSYaS-9$_WZyvdio*Rt7gWu5%d2BV;7+otu43_ZI~S4xmy(;5Dn4kDpP&INW92dA$ zD3>V359OjL(NHc5ceT{&M#NR|W{jiw0a{}3Hd-4EE9P;wqGjf*PS*LQFqrTy73wULkGVkOcRdL%b2n zB_uRLxr77^s#X3;D3=KCg>s4Dekhlk@DQO~6fY9WMWK9E72lj;m3)ZwqQ+?f513{s z7nQpa%B99OhjIxhMu)>|5H`q0D3^e|F_cTdJ2aF_z>S4+2`Gn$atX)?rVtP1(&Vvg zcMuuI+b}q&i5nk1T{)CXP+lyQOF-Ea$|ay38p)0luJN6G?YugeTYyl0XrVbB_MI9yihIy9uMUbkg5}XG?Ys~{fC5d39@Vm z>!kj;yz?3mw+3FatYu{@53SiA6QwS=1?vH3(o`#sTay6U|=T*L%9SD z+>Atks=z0QL%Gzv#kv{FB?N;|E+Ndjd=Sbdq(noxge0uhekhla;K@)aLb-&5SSXi} z!-YgbxhNVNg5<)1cGWb>eycw+H%N9WA57xQqz4qMqz~v&l7gvZs39Yb`*C7 zs6~EZoa5JlYqqCqGhL~@r7Oo?#Bgm?({$f%P;4=-HA*fETI0EIZ!F1o-)_)C_w5Fu z>Au~d1n%20+;`uOG3p-U=41>H{I0z>w3=-Z_w7bWK{1iZQZrnOlzgzjo9wx7s~WWX zwo29>+TN^ax^JsoP4{gDLUiBYzP*toVMFgazfe)_ie>F)P39Ih3?xv*mU3a@VNW7N7>}Q9V3PA z+a3p^1ZyQ??%N(uNZPL#?%N)rDu^#l%E-Ze+rznli2Jt3iMnrl3{?uOP0D@SW1%hP zz~#GddmOE-U>&Om)&=2VHs-}b1cxQ6?-$9X9C?Ze2@KDcjt96NyC z1BUyyN2(t12KVh4wc0{VmEpYOubL_5p8K{}#%A|zkG9!;+oK)gz73xGlBY}1>m%@& z!8c74f7>(MMd3k;ua-T5|3~;j)ttt(!WYmMNVngUt$kvZ=PQ37@HEREegp3Y;oSw^9IP{R1HMT0 z>J8i*g?l@=3$UICe!T9Rgm=gJP1c3z#T96;Zs`@mzVCdl|0bZO2QR`rxgIGucqP10@;(J9 zw<$zl0Q4tN(s7i-=fVBaJ-tr2_kz0w?^d+w7W9C78s~GH z&%zmAmwb_MpH0^yH$U@ddo`Sq8cyK<3-RyVxkupNwUVai?<4Vr&UfHD%pZvvb&vcW zqZa-=K~MPi6!VLJmzY8Pdro)B?*-j1zn65c{63(kJV^9o_$uEgNK9XaX>yYzF&Sq^0R%GZj*A_DC0@^_qne*ckVWU&=EQ+ z*ai6J_6yLWbNG1~zD4;op7G5Xeg1Lz|AplLe4T$iu=yVg#O1#hwV%c_>D7yoL?YAHt^vi?0Bzxihu z|K22j5j_kXoBnY8&GUtS9*1@4iTJ&Te)jSE+&Q!MF=qd|7=I7&&vCeR{&6t}9=MF? zr;y?}_X|VE)!^70KmFaB(~P}wC32m3y5=;d-u|G`X`)Aar4edNrG z{_pk?-aGC*G>;iI{qFG&@YO@}H1`PJAHMm;oA(EPerH~~`F-d2@-u?R-%Fl@m!188 Hn}h!crfN(| literal 0 HcmV?d00001 diff --git a/tools/quake2/extra/texpaint/texmake.rc b/tools/quake2/extra/texpaint/texmake.rc new file mode 100644 index 00000000..21a1eb10 --- /dev/null +++ b/tools/quake2/extra/texpaint/texmake.rc @@ -0,0 +1,156 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU2 MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New skin\tCtrl-n", ID_FILE_NEWSKIN + MENUITEM "&Open skin\tCtrl-o", ID_FILE_OPENSKIN + MENUITEM "&Reload skin\tCtrl-r", ID_FILE_RELOADSKIN + MENUITEM "&Save skin\tCtrl-s", ID_FILE_SAVESKIN + MENUITEM "Save skin &as\tCtrl-a", ID_FILE_SAVESKINAS + MENUITEM "Resample skin", ID_FILE_RESAMPLESKIN + MENUITEM SEPARATOR + MENUITEM "Open &frame\tCtrl-f", ID_FILE_OPENFRAME + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl-z", ID_EDIT_UNDO + MENUITEM "&Redo\tCtrl-y", ID_EDIT_REDO + END + POPUP "&View" + BEGIN + MENUITEM "&Model lines\tCtrl-m", ID_VIEW_MODELLINES + MENUITEM "&Texture lines\tCtrl-t", ID_VIEW_TEXTURELINES + MENUITEM "Model &lighting\tCtrl-l", ID_VIEW_MODELLIGHTING + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE +BEGIN + "A", ID_FILE_SAVESKINAS, VIRTKEY, CONTROL, NOINVERT + "F", ID_FILE_OPENFRAME, VIRTKEY, CONTROL, NOINVERT + "L", ID_VIEW_MODELLIGHTING, VIRTKEY, CONTROL, NOINVERT + "M", ID_VIEW_MODELLINES, VIRTKEY, CONTROL, NOINVERT + "N", ID_FILE_NEWSKIN, VIRTKEY, CONTROL, NOINVERT + "O", ID_FILE_OPENSKIN, VIRTKEY, CONTROL, NOINVERT + "R", ID_FILE_RELOADSKIN, VIRTKEY, CONTROL, NOINVERT + "S", ID_FILE_SAVESKIN, VIRTKEY, CONTROL, NOINVERT + "T", ID_VIEW_TEXTURELINES, VIRTKEY, CONTROL, NOINVERT + "Y", ID_EDIT_REDO, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NEWSKIN DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "New Skin" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + EDITTEXT IDC_WIDTH,51,14,40,14,ES_AUTOHSCROLL + LTEXT "Width",IDC_STATIC,20,17,20,8 + EDITTEXT IDC_HEIGHT,51,37,40,14,ES_AUTOHSCROLL + LTEXT "height",IDC_STATIC,19,40,20,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_NEWSKIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tools/quake2/extra/texpaint/texpaint.c b/tools/quake2/extra/texpaint/texpaint.c new file mode 100644 index 00000000..cad7028d --- /dev/null +++ b/tools/quake2/extra/texpaint/texpaint.c @@ -0,0 +1,311 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "texpaint.h" + +triangle_t *faces; +int numfaces; + +int skinwidth, skinheight; +int picwidth, picheight; +int width, height; +int iwidth, iheight; +int width2, height2; // padded to ^2 + +float tmcoords[10000][3][2]; + +byte pic[1024*512]; +unsigned rgb[1024*512]; + +float scale; +float s_scale, t_scale; + +char filename[1024]; +char picfilename[1024]; + + +/* +================ +BoundFaces +================ +*/ +vec3_t mins, maxs; + +void BoundFaces (void) +{ + int i,j,k; + triangle_t *pol; + float v; + + for (i=0 ; i<3 ; i++) + { + mins[i] = 9999; + maxs[i] = -9999; + } + + for (i=0 ; iverts[j][k]; + if (vmaxs[k]) + maxs[k] = v; + } + } + + for (i=0 ; i<3 ; i++) + { + mins[i] = floor(mins[i]); + maxs[i] = ceil(maxs[i]); + } + + width = maxs[0] - mins[0]; + height = maxs[2] - mins[2]; + + printf ("width: %i height: %i\n",width, height); + + if (!skinwidth) + { // old way + scale = 8; + if (width*scale >= 150) + scale = 150.0 / width; + if (height*scale >= 190) + scale = 190.0 / height; + s_scale = t_scale = scale; + iwidth = ceil(width*scale) + 4; + iheight = ceil(height*scale) + 4; + } + else + { // new way + s_scale = (skinwidth/2-4)/(float)width; + t_scale = (skinheight-4)/(float)height; + iwidth = skinwidth/2; + iheight = skinheight; + } + + printf ("scale: %f\n",scale); + printf ("iwidth: %i iheight: %i\n",iwidth, iheight); +} + + + +/* +============ +AddFace +============ +*/ +void AddFace (int facenum, triangle_t *f) +{ + vec3_t v1, v2, normal; + int basex, basey; + int i, j; + int coords[3][2]; + +// +// determine which side to map the teture to +// + VectorSubtract (f->verts[0], f->verts[1], v1); + VectorSubtract (f->verts[2], f->verts[1], v2); + CrossProduct (v1, v2, normal); + + if (normal[1] > 0) + basex = iwidth + 2; + else + basex = 2; + basey = 2; + + for (i=0 ; i<3 ; i++) + { + coords[i][0] = Q_rint((f->verts[i][0] - mins[0])*s_scale + basex); + coords[i][1] = Q_rint( (maxs[2] - f->verts[i][2])*t_scale + basey); +tmcoords[facenum][i][0] = coords[i][0]/(float)width2; +tmcoords[facenum][i][1] = coords[i][1]/(float)height2; + } + +} + + +void CalcTmCoords (void) +{ + int j; + + BoundFaces (); + + for (j=0 ; j 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + argv[argc] = lpCmdLine; + argc++; + + while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + *lpCmdLine = 0; + lpCmdLine++; + } + + } + } +} + +/* +================= +LoadTriFile +================= +*/ +void LoadTriFile (char *name) +{ + strcpy (tri_filename, name); + SetWindowText (camerawindow, tri_filename); + + LoadTriangleList (tri_filename, &faces, &numfaces); + InvalidateRect (camerawindow, NULL, false); +} + +/* +================== +TimerProc + +================== +*/ +int CALLBACK TimerProc( + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime // current system time + ) +{ + static int counter; + char name[1024]; + + if (!skin_filename[0]) + return 0; + + if (!modified_past_autosave) + { + counter = 0; + return 0; + } + + counter++; + + if (counter < 3*5) + return 0; // save every five minutes + + strcpy (name, skin_filename); + StripExtension (name); + strcat (name, "_autosave.lbm"); + Skin_SaveFile (name); + + modified_past_autosave = false; + counter = 0; + + return 0; +} + +/* +================== +WinMain + +================== +*/ +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance + ,LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + HACCEL accelerators; + + main_instance = hInstance; + + ParseCommandLine (lpCmdLine); + + screen_width = GetSystemMetrics (SM_CXFULLSCREEN); + screen_height = GetSystemMetrics (SM_CYFULLSCREEN); + + // hack for broken NT 4.0 dual screen + if (screen_width > 2*screen_height) + screen_width /= 2; + + accelerators = LoadAccelerators (hInstance + , MAKEINTRESOURCE(IDR_ACCELERATOR1)); + if (!accelerators) + Sys_Error ("LoadAccelerators failed"); + + Main_Create (hInstance); + WCam_Create (hInstance); + WPal_Create (hInstance); + WSkin_Create (hInstance); + + if (argc == 2) + Skin_LoadFile (argv[1]); + + SetTimer ( mainwindow, 1, 1000*20, TimerProc ); + + while (1) + { + if (!GetMessage (&msg, mainwindow, 0, 0)) + break; + if (!TranslateAccelerator(mainwindow, accelerators, &msg) ) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + + /* return success of application */ + return TRUE; +} + diff --git a/tools/quake2/extra/texpaint/texpaint.h b/tools/quake2/extra/texpaint/texpaint.h new file mode 100644 index 00000000..15eaf9ed --- /dev/null +++ b/tools/quake2/extra/texpaint/texpaint.h @@ -0,0 +1,88 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "lbmlib.h" +#include "trilib.h" +#include "l3dslib.h" + +#include +#include +#include +#include +#include "resource.h" +#include "afxres.h" + +extern HINSTANCE main_instance; + +extern HGLRC baseRC; + +extern HWND mainwindow; +extern HWND camerawindow; +extern HWND palettewindow; +extern HWND skinwindow; + +extern int screen_width, screen_height; + +#define QE3_STYLE (WS_OVERLAPPED| WS_CAPTION | WS_THICKFRAME | \ + /* WS_MINIMIZEBOX | */ WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | \ + WS_CLIPCHILDREN | WS_CHILD) + +extern byte pic[1024*512]; +extern unsigned rgb[1024*512]; +extern unsigned index_texture[1024*512]; +extern byte palette[768]; + +extern triangle_t *faces; +extern int numfaces; +extern float tmcoords[10000][3][2]; + +extern int skinwidth, skinheight; +extern int picwidth, picheight; +extern int width, height; +extern int iwidth, iheight; +extern int width2, height2; // padded to ^2 + +extern char tri_filename[1024]; +extern char skin_filename[1024]; + +extern int selected_index; +extern unsigned selected_rgb; + +extern qboolean model_lines; +extern qboolean skin_lines; + +extern qboolean modified; +extern qboolean modified_past_autosave; + +#define TEXTURE_SKIN 1 +#define TEXTURE_INDEX 2 + +#define MENU_VIEW 2 + +#define MODEL_DISPLAYLIST 1 + +typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint); + +extern BINDTEXFUNCPTR BindTextureEXT; + diff --git a/tools/quake2/extra/texpaint/texpaint.mak b/tools/quake2/extra/texpaint/texpaint.mak new file mode 100644 index 00000000..1a836604 --- /dev/null +++ b/tools/quake2/extra/texpaint/texpaint.mak @@ -0,0 +1,468 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=texpaint - Win32 Debug +!MESSAGE No configuration specified. Defaulting to texpaint - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "texpaint - Win32 Release" && "$(CFG)" !=\ + "texpaint - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "texpaint.mak" CFG="texpaint - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "texpaint - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "texpaint - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "texpaint - Win32 Debug" +MTL=mktyplib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "texpaint - 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 "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\texpaint.exe" + +CLEAN : + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\l3dslib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\texmake.res" + -@erase "$(INTDIR)\texpaint.obj" + -@erase "$(INTDIR)\trilib.obj" + -@erase "$(INTDIR)\win_cam.obj" + -@erase "$(INTDIR)\win_main.obj" + -@erase "$(INTDIR)\win_pal.obj" + -@erase "$(INTDIR)\win_skin.obj" + -@erase "$(OUTDIR)\texpaint.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /ML /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)/texpaint.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/texmake.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/texpaint.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 opengl32.lib glu32.lib glaux.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:windows /machine:I386 +LINK32_FLAGS=opengl32.lib glu32.lib glaux.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:windows /incremental:no\ + /pdb:"$(OUTDIR)/texpaint.pdb" /machine:I386 /out:"$(OUTDIR)/texpaint.exe" +LINK32_OBJS= \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\l3dslib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\texmake.res" \ + "$(INTDIR)\texpaint.obj" \ + "$(INTDIR)\trilib.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_pal.obj" \ + "$(INTDIR)\win_skin.obj" + +"$(OUTDIR)\texpaint.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "texpaint - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "texpaint" +# PROP BASE Intermediate_Dir "texpaint" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\texpaint.exe" + +CLEAN : + -@erase "$(INTDIR)\cmdlib.obj" + -@erase "$(INTDIR)\l3dslib.obj" + -@erase "$(INTDIR)\lbmlib.obj" + -@erase "$(INTDIR)\mathlib.obj" + -@erase "$(INTDIR)\scriplib.obj" + -@erase "$(INTDIR)\texmake.res" + -@erase "$(INTDIR)\texpaint.obj" + -@erase "$(INTDIR)\trilib.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\win_cam.obj" + -@erase "$(INTDIR)\win_main.obj" + -@erase "$(INTDIR)\win_pal.obj" + -@erase "$(INTDIR)\win_skin.obj" + -@erase "$(OUTDIR)\texpaint.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "WIN_ERROR" /YX /c +CPP_PROJ=/nologo /MLd /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D\ + "_WINDOWS" /D "WIN_ERROR" /Fp"$(INTDIR)/texpaint.pch" /YX /Fo"$(INTDIR)/"\ + /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/texmake.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/texpaint.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 opengl32.lib glu32.lib glaux.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:windows /pdb:none /debug /machine:I386 +LINK32_FLAGS=opengl32.lib glu32.lib glaux.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:windows /pdb:none /debug\ + /machine:I386 /out:"$(OUTDIR)/texpaint.exe" +LINK32_OBJS= \ + "$(INTDIR)\cmdlib.obj" \ + "$(INTDIR)\l3dslib.obj" \ + "$(INTDIR)\lbmlib.obj" \ + "$(INTDIR)\mathlib.obj" \ + "$(INTDIR)\scriplib.obj" \ + "$(INTDIR)\texmake.res" \ + "$(INTDIR)\texpaint.obj" \ + "$(INTDIR)\trilib.obj" \ + "$(INTDIR)\win_cam.obj" \ + "$(INTDIR)\win_main.obj" \ + "$(INTDIR)\win_pal.obj" \ + "$(INTDIR)\win_skin.obj" + +"$(OUTDIR)\texpaint.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "texpaint - Win32 Release" +# Name "texpaint - Win32 Debug" + +!IF "$(CFG)" == "texpaint - Win32 Release" + +!ELSEIF "$(CFG)" == "texpaint - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\texpaint.c +DEP_CPP_TEXPA=\ + "..\common\cmdlib.h"\ + "..\common\l3dslib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\trilib.h"\ + ".\texpaint.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\texpaint.obj" : $(SOURCE) $(DEP_CPP_TEXPA) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\mathlib.c +DEP_CPP_MATHL=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + "..\..\..\quake\utils2\common\mathlib.h"\ + + +"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\l3dslib.c +DEP_CPP_L3DSL=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + "..\..\..\quake\utils2\common\l3dslib.h"\ + "..\..\..\quake\utils2\common\mathlib.h"\ + "..\..\..\quake\utils2\common\trilib.h"\ + + +"$(INTDIR)\l3dslib.obj" : $(SOURCE) $(DEP_CPP_L3DSL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\lbmlib.c +DEP_CPP_LBMLI=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + "..\..\..\quake\utils2\common\lbmlib.h"\ + + +"$(INTDIR)\lbmlib.obj" : $(SOURCE) $(DEP_CPP_LBMLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\scriplib.c +DEP_CPP_SCRIP=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + "..\..\..\quake\utils2\common\scriplib.h"\ + + +"$(INTDIR)\scriplib.obj" : $(SOURCE) $(DEP_CPP_SCRIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\trilib.c +DEP_CPP_TRILI=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + "..\..\..\quake\utils2\common\mathlib.h"\ + "..\..\..\quake\utils2\common\trilib.h"\ + + +"$(INTDIR)\trilib.obj" : $(SOURCE) $(DEP_CPP_TRILI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_skin.c +DEP_CPP_WIN_S=\ + "..\common\cmdlib.h"\ + "..\common\l3dslib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\trilib.h"\ + ".\texpaint.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_skin.obj" : $(SOURCE) $(DEP_CPP_WIN_S) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_main.c +DEP_CPP_WIN_M=\ + "..\common\cmdlib.h"\ + "..\common\l3dslib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\trilib.h"\ + ".\texpaint.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_main.obj" : $(SOURCE) $(DEP_CPP_WIN_M) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_pal.c +DEP_CPP_WIN_P=\ + "..\common\cmdlib.h"\ + "..\common\l3dslib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\trilib.h"\ + ".\texpaint.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_pal.obj" : $(SOURCE) $(DEP_CPP_WIN_P) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\win_cam.c +DEP_CPP_WIN_C=\ + "..\common\cmdlib.h"\ + "..\common\l3dslib.h"\ + "..\common\lbmlib.h"\ + "..\common\mathlib.h"\ + "..\common\trilib.h"\ + ".\texpaint.h"\ + {$(INCLUDE)}"\gl\GL.H"\ + {$(INCLUDE)}"\gl\GLAUX.H"\ + {$(INCLUDE)}"\gl\GLU.H"\ + + +"$(INTDIR)\win_cam.obj" : $(SOURCE) $(DEP_CPP_WIN_C) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\texmake.rc + +"$(INTDIR)\texmake.res" : $(SOURCE) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\texpaint.h + +!IF "$(CFG)" == "texpaint - Win32 Release" + +!ELSEIF "$(CFG)" == "texpaint - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\lbmlib.h + +!IF "$(CFG)" == "texpaint - Win32 Release" + +!ELSEIF "$(CFG)" == "texpaint - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\cmdlib.h + +!IF "$(CFG)" == "texpaint - Win32 Release" + +!ELSEIF "$(CFG)" == "texpaint - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\quake\utils2\common\cmdlib.c +DEP_CPP_CMDLI=\ + "..\..\..\quake\utils2\common\cmdlib.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + + +"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/tools/quake2/extra/texpaint/win_cam.c b/tools/quake2/extra/texpaint/win_cam.c new file mode 100644 index 00000000..5e1986d7 --- /dev/null +++ b/tools/quake2/extra/texpaint/win_cam.c @@ -0,0 +1,414 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "texpaint.h" + +#define CAMERA_WINDOW_CLASS "TPCamera" + +HDC camdc; +HGLRC baseRC; + +float pitch, yaw, roll; +qboolean model_lines = false; + +float cam_x, cam_y=-64, cam_z=32; + +int cam_width, cam_height; + +BINDTEXFUNCPTR BindTextureEXT; + +void InitIndexTexture (void) +{ + int i; + + BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + for (i=0 ; i= width2*height2) + return; + + if (index == cam_last_index) + return; // in same pixel + cam_last_index = index; + if (shift) + { + Pal_SetIndex (pic[index]); + return; + } + + SetSkin (index, selected_rgb); + UpdateWindow (camerawindow); +} + + +void Cam_DrawSetup (void) +{ + glViewport (0,0,cam_width, cam_height); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective (90, (float)cam_width/cam_height, 2, 1024); + gluLookAt (cam_x, cam_y, cam_z, cam_x, cam_y+1, cam_z, 0, 0, 1); + + glRotated (-roll*0.3, 0, 1, 0); + glRotated (-pitch*0.3, 1, 0, 0); + glRotated (yaw*0.3, 0, 0, 1); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glEnable (GL_DEPTH_TEST); + glEnable (GL_CULL_FACE); + glEnable (GL_TEXTURE_2D); + glCullFace (GL_FRONT); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void Cam_Draw (void) +{ + if (!cam_width || !cam_height) + return; + + glClearColor (0.3,0.3,0.3,1); + Cam_DrawSetup (); + + BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN); + + DrawModel (); + + if (model_lines) + { + glDisable (GL_TEXTURE_2D); + glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + glDepthFunc (GL_LEQUAL); + glDepthRange (0, 0.999); // nudge depth to avoid dropouts + DrawModel (); + glDepthRange (0, 1); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glEnable (GL_TEXTURE_2D); + } + + SwapBuffers(camdc); + + // now fill the back buffer with the index texture + glClearColor (0,0,0,0); + glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX); + DrawModel (); + + BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN); +} + + + +/* +============ +CameraWndProc +============ +*/ +LONG WINAPI WCam_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 1; + int fwKeys, xPos, yPos; + RECT rect; + static int oldx, oldy; + POINT pt; + + GetClientRect(hWnd, &rect); + cam_width = rect.right-rect.left; + cam_height = rect.bottom-rect.top; + + switch (uMsg) + { + case WM_CREATE: + camdc = GetDC(hWnd); + bSetupPixelFormat(camdc); + + baseRC = wglCreateContext( camdc ); + if (!baseRC) + Sys_Error ("wglCreateContext failed"); + if (!wglMakeCurrent( camdc, baseRC )) + Sys_Error ("wglMakeCurrent failed"); + BindTextureEXT = (void *)wglGetProcAddress((LPCSTR) "glBindTextureEXT"); + if (!BindTextureEXT) + Sys_Error ("GetProcAddress for BindTextureEXT failed"); + + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + if (!wglMakeCurrent( camdc, baseRC )) + Sys_Error ("wglMakeCurrent failed"); + Cam_Draw (); + EndPaint(hWnd, &ps); + } + break; + + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + if (GetTopWindow(mainwindow) != hWnd) + BringWindowToTop(hWnd); + + SetFocus (camerawindow); + SetCapture (camerawindow); + GetCursorPos (&pt); + xPos = pt.x; + yPos = pt.y; + oldx = xPos; + oldy = yPos; + break; + + case WM_LBUTTONDOWN: + cam_last_index = -1; +draw: + if (GetTopWindow(mainwindow) != hWnd) + BringWindowToTop(hWnd); + + SetFocus (camerawindow); + SetCapture (camerawindow); + fwKeys = wParam; // key flags + xPos = (short)LOWORD(lParam); // horizontal position of cursor + yPos = (short)HIWORD(lParam); // vertical position of cursor + yPos = (int)rect.bottom - 1 - yPos; + if (!wglMakeCurrent( camdc, baseRC )) + Sys_Error ("wglMakeCurrent failed"); + + Cam_Click (xPos, yPos, !!(wParam&(MK_SHIFT|MK_CONTROL)) ); + +// Cam_MouseDown (xPos, yPos, fwKeys); + break; + + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONUP: + if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) + ReleaseCapture (); + break; + + case WM_MOUSEMOVE: + { + int dx, dy; + + if (wParam & MK_LBUTTON) + goto draw; + + GetCursorPos (&pt); + xPos = pt.x; + yPos = pt.y; + if (!(wParam & (MK_RBUTTON|MK_MBUTTON))) + { + oldx = xPos; + oldy = yPos; + break; + } + dx = xPos-oldx; + dy = oldy-yPos; + if (!dx && !dy) + break; + SetCursorPos (oldx, oldy); + + if (wParam == (MK_RBUTTON|MK_CONTROL) ) + { + if (abs(dx) > abs(dy)) + cam_y -= 0.1*dx; + else + cam_y -= 0.1*dy; + InvalidateRect (camerawindow, NULL, false); + } + if (wParam == MK_RBUTTON) + { + cam_x -= 0.1*dx; + cam_z -= 0.1*dy; + InvalidateRect (camerawindow, NULL, false); + } + if (wParam == (MK_MBUTTON|MK_CONTROL) ) + { + if (abs(dx) > abs(dy)) + roll -= dx; + else + roll -= dy; + InvalidateRect (camerawindow, NULL, false); + } + if (wParam == MK_MBUTTON) + { + yaw += dx; + pitch += dy; + InvalidateRect (camerawindow, NULL, false); + } + } + break; + + + + case WM_SIZE: +// camera.width = rect.right; +// camera.height = rect.bottom; + InvalidateRect(camerawindow, NULL, false); + break; + case WM_NCCALCSIZE:// don't let windows copy pixels + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + return WVR_REDRAW; + case WM_CLOSE: + /* call destroy window to cleanup and go away */ + DestroyWindow (hWnd); + break; + + case WM_DESTROY: + { + HGLRC hRC; + HDC hDC; + + /* release and free the device context and rendering context */ + hRC = wglGetCurrentContext(); + hDC = wglGetCurrentDC(); + + wglMakeCurrent(NULL, NULL); + + if (hRC) + wglDeleteContext(hRC); + if (hDC) + ReleaseDC(hWnd, hDC); + } + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 1 if handled message, 0 if not */ + return lRet; +} + + +/* +============== +WCam_Register +============== +*/ +void WCam_Register (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WCam_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = CAMERA_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Sys_Error ("WCam_Register: failed"); +} + + +void WCam_Create (HINSTANCE hInstance) +{ + WCam_Register (hInstance); + + camerawindow = CreateWindow (CAMERA_WINDOW_CLASS , + "Camera View", + QE3_STYLE, + 0, + 0, + (int)(screen_width*0.5), + (int)(screen_height-20), // size + + mainwindow, // parent window + 0, // no menu + hInstance, + 0); + if (!camerawindow) + Sys_Error ("Couldn't create camerawindow"); + + RestoreWindowState(camerawindow, "camerawindow"); + ShowWindow (camerawindow, SW_SHOWDEFAULT); +} diff --git a/tools/quake2/extra/texpaint/win_main.c b/tools/quake2/extra/texpaint/win_main.c new file mode 100644 index 00000000..d377d7ba --- /dev/null +++ b/tools/quake2/extra/texpaint/win_main.c @@ -0,0 +1,496 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "texpaint.h" + +HINSTANCE main_instance; + +int screen_width, screen_height; + +HWND mainwindow; +HWND camerawindow; +HWND palettewindow; +HWND skinwindow; + +/* +================= +Sys_Error + +For abnormal program terminations +================= +*/ +void Sys_Error (char *error, ...) +{ + va_list argptr; + char text[1024]; + char text2[1024]; + int err; + + err = GetLastError (); + + va_start (argptr,error); + vsprintf (text, error,argptr); + va_end (argptr); + + sprintf (text2, "%s\nGetLastError() = %i", text, err); + MessageBox(mainwindow, text2, "Error", 0 /* MB_OK */ ); + + exit (1); +} + + +/* +====================================================================== + +FILE DIALOGS + +====================================================================== +*/ + +qboolean modified; +qboolean modified_past_autosave; + +qboolean ConfirmModified (void) +{ + if (!modified) + return true; + + if (MessageBox (mainwindow, "This will lose changes to the skin" + , "warning", MB_OKCANCEL) == IDCANCEL) + return false; + return true; +} + +OPENFILENAME ofn; /* common dialog box structure */ +char szDirName[MAX_PATH]; /* directory string */ +char szFile[260]; /* filename string */ +char szFileTitle[260]; /* file title string */ +char szSkinFilter[260] = /* filter string */ + "Skin texture (*.lbm *.pcx)\0*.lbm;*.pcx\0\0"; +char szFrameFilter[260] = /* filter string */ + "Model frame (*.tri)\0*.tri\0\0"; +char chReplace; /* string separator for szFilter */ +int i, cbString; /* integer count variables */ +HANDLE hf; /* file handle */ + +void OpenSkinDialog (void) +{ +// strcpy (szDirName, ValueForKey (project_entity, "basepath") ); +// strcat (szDirName, "\\maps"); + + /* Place the terminating null character in the szFile. */ + + szFile[0] = '\0'; + + /* Set the members of the OPENFILENAME structure. */ + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = mainwindow; + ofn.lpstrFilter = szSkinFilter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof(szFileTitle); + ofn.lpstrInitialDir = szDirName; + ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | + OFN_FILEMUSTEXIST; + + /* Display the Open dialog box. */ + + if (!GetOpenFileName(&ofn)) + return; // canceled + + Skin_LoadFile (ofn.lpstrFile); +} + +void OpenFrameDialog (void) +{ +// strcpy (szDirName, ValueForKey (project_entity, "basepath") ); +// strcat (szDirName, "\\maps"); + + /* Place the terminating null character in the szFile. */ + + szFile[0] = '\0'; + + /* Set the members of the OPENFILENAME structure. */ + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = mainwindow; + ofn.lpstrFilter = szFrameFilter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof(szFileTitle); + ofn.lpstrInitialDir = szDirName; + ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | + OFN_FILEMUSTEXIST; + + /* Display the Open dialog box. */ + + if (!GetOpenFileName(&ofn)) + return; // canceled + + LoadTriFile (ofn.lpstrFile); +} + +void SaveSkinDialog (void) +{ +// strcpy (szDirName, ValueForKey (project_entity, "basepath") ); +// strcat (szDirName, "\\maps"); + + /* Place the terminating null character in the szFile. */ + + szFile[0] = '\0'; + + /* Set the members of the OPENFILENAME structure. */ + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = mainwindow; + ofn.lpstrFilter = szSkinFilter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFile; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof(szFileTitle); + ofn.lpstrInitialDir = szDirName; + ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | + OFN_FILEMUSTEXIST; + + /* Display the Open dialog box. */ + + if (!GetSaveFileName(&ofn)) + return; // canceled + + DefaultExtension (ofn.lpstrFile, ".lbm"); + Skin_SaveFile (ofn.lpstrFile); + strcpy (skin_filename, ofn.lpstrFile); +} + +//========================================================================== + +BOOL bSetupPixelFormat(HDC hDC) +{ + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 24, // 24-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + int pixelformat = 0; + PIXELFORMATDESCRIPTOR newp; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ) + { + printf("%d",GetLastError()); + Error ("ChoosePixelFormat failed"); + } + if (!SetPixelFormat(hDC, pixelformat, &pfd)) + Error ("SetPixelFormat failed"); + + return TRUE; +} + + +/* +============================================================================== + + MENU + +============================================================================== +*/ + + +/* handle all WM_COMMAND messages here */ +LONG WINAPI CommandHandler ( + HWND hWnd, + WPARAM wParam, + LPARAM lParam) +{ + unsigned short cmd; + + cmd = LOWORD(wParam); + + switch (cmd) + { + // + // file menu + // + case ID_FILE_RESAMPLESKIN: + ResampleSkin (); + break; + + case ID_FILE_NEWSKIN: + NewSkin (); + break; + + case ID_FILE_OPENFRAME: + OpenFrameDialog (); + break; + + case ID_FILE_OPENSKIN: + if (!ConfirmModified()) + break; + OpenSkinDialog (); + break; + + case ID_FILE_RELOADSKIN: + if (!ConfirmModified()) + break; + Skin_LoadFile (skin_filename); + break; + + case ID_FILE_SAVESKIN: + Skin_SaveFile (skin_filename); + break; + + case ID_FILE_SAVESKINAS: + SaveSkinDialog (); + break; + case ID_FILE_EXIT: + if (!ConfirmModified()) + break; + PostQuitMessage (0); + break; + + // + // edit menu + // + case ID_EDIT_UNDO: + Undo(); + break; + case ID_EDIT_REDO: + Redo(); + break; + + // + // view menu + // + case ID_VIEW_MODELLINES: + model_lines ^= 1; + CheckMenuItem ( GetSubMenu (GetMenu(mainwindow), MENU_VIEW) + , ID_VIEW_MODELLINES + , MF_BYCOMMAND | (model_lines ? MF_CHECKED : MF_UNCHECKED) ); + InvalidateRect (camerawindow, NULL, false); + break; + case ID_VIEW_TEXTURELINES: + skin_lines ^= 1; + CheckMenuItem ( GetSubMenu (GetMenu(mainwindow), MENU_VIEW) + , ID_VIEW_TEXTURELINES + , MF_BYCOMMAND | (skin_lines ? MF_CHECKED : MF_UNCHECKED) ); + InvalidateRect (skinwindow, NULL, false); + break; + default: + return FALSE; + } + + return TRUE; +} + +/* +============ +WMAIN_WndProc +============ +*/ +LONG WINAPI WMAIN_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 1; + RECT rect; + HDC maindc; + + GetClientRect(hWnd, &rect); + + switch (uMsg) + { + case WM_CREATE: + maindc = GetDC(hWnd); + bSetupPixelFormat(maindc); + break; + case WM_COMMAND: + lRet = CommandHandler (hWnd, wParam, lParam); + break; + + case WM_CLOSE: + if (!ConfirmModified()) + break; + PostQuitMessage (0); + break; + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 1 if handled message, 0 if not */ + return lRet; +} + + + + +/* +============== +Main_Create +============== +*/ +void Main_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)WMAIN_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU2); + wc.lpszClassName = "TEXPAINT_MAIN"; + + if (!RegisterClass (&wc) ) + Error ("WCam_Register: failed"); + + + mainwindow = CreateWindow ("TEXPAINT_MAIN" , + "Texpaint", + WS_OVERLAPPEDWINDOW | + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN, + 0,0,screen_width,screen_height, // size + 0, + NULL, // no menu + hInstance, + NULL); + if (!mainwindow) + Error ("Couldn't create main window"); + +// GetWindowInfo("mainwindow", &SavedInfo, NULL); + ShowWindow (mainwindow, SW_SHOWDEFAULT); +} + + + + +BOOL SaveWindowInfo(const char *pszName, void *pvBuf, long lSize) +{ + LONG lres; + DWORD dwDisp; + HKEY hKeyId; + + lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\id\\Texpaint", 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp); + + if (lres != ERROR_SUCCESS) + return FALSE; + + lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, pvBuf, lSize); + + RegCloseKey(hKeyId); + + if (lres != ERROR_SUCCESS) + return FALSE; + + return TRUE; +} + + +BOOL GetWindowInfo(const char *pszName, void *pvBuf, long *plSize) +{ + HKEY hKey; + long lres, lType, lSize; + + if (plSize == NULL) + plSize = &lSize; + + lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\id\\Texpaint", 0, KEY_READ, &hKey); + + if (lres != ERROR_SUCCESS) + return FALSE; + + lres = RegQueryValueEx(hKey, pszName, NULL, &lType, pvBuf, plSize); + + RegCloseKey(hKey); + + if (lres != ERROR_SUCCESS) + return FALSE; + + return TRUE; + +} + +BOOL SaveWindowState(HWND hWnd, const char *pszName) +{ + RECT rc; + + GetWindowRect(hWnd, &rc); + MapWindowPoints(NULL, mainwindow, (POINT *)&rc, 2); + return SaveWindowInfo(pszName, &rc, sizeof(rc)); +} + + +BOOL RestoreWindowState(HWND hWnd, const char *pszName) +{ + RECT rc; + LONG lSize = sizeof(rc); + + if (GetWindowInfo(pszName, &rc, &lSize)) + { + if (rc.left < 0) + rc.left = 0; + if (rc.top < 0) + rc.top = 0; + if (rc.right < rc.left + 16) + rc.right = rc.left + 16; + if (rc.bottom < rc.top + 16) + rc.bottom = rc.top + 16; + + MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, + rc.bottom - rc.top, FALSE); + return TRUE; + } + + return FALSE; +} + diff --git a/tools/quake2/extra/texpaint/win_pal.c b/tools/quake2/extra/texpaint/win_pal.c new file mode 100644 index 00000000..09ebe51f --- /dev/null +++ b/tools/quake2/extra/texpaint/win_pal.c @@ -0,0 +1,257 @@ +/* +=========================================================================== +Copyright (C) 1997-2006 Id Software, Inc. + +This file is part of Quake 2 Tools source code. + +Quake 2 Tools source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake 2 Tools source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake 2 Tools source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "texpaint.h" + +#define PALETTE_WINDOW_CLASS "TPPalette" + +HDC paldc; +int pal_width, pal_height; +int blocks_x, blocks_y; + +int selected_index; +unsigned selected_rgb; + +byte palette[768]; + +float SnapAspect (float aspect) +{ + if (aspect > 128) + return 256; + if (aspect > 32) + return 128; + if (aspect > 8) + return 64; + if (aspect > 2) + return 32; + return 16; +} + +void Pal_SetIndex (int index) +{ + selected_index = index; + selected_rgb = palette[index*3] + (palette[index*3+1]<<8) + (palette[index*3+2]<<16); + InvalidateRect (palettewindow, NULL, false); +} + +void Pal_Draw (void) +{ + int x, y; + float aspect; + float xs, ys; + int c; + + if (pal_width < 1 || pal_height < 1) + return; + + // + // determine the block arrangement + // + if (pal_width > pal_height) + { + aspect = SnapAspect (pal_width / pal_height); + blocks_x = aspect; + blocks_y = 256/blocks_x; + } + else + { + aspect = SnapAspect (pal_height / pal_width); + blocks_y = aspect; + blocks_x = 256/blocks_y; + } + + // + // draw it + // + glViewport (0,0,pal_width, pal_height); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glOrtho (0,1,0,1,-100,100); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glClear (GL_COLOR_BUFFER_BIT); + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + glDisable (GL_TEXTURE_2D); + + xs = 1.0/blocks_x; + ys = 1.0/blocks_y; + + for (x=0 ; xoffset = index; + m->oldvalue = pic[index]; + + modify_index = (++undo_index)&(MAX_MODIFY-1); + + // modify it + rgb[index] = selected_rgb; + pic[index] = selected_index; + UpdateTexture (index); + InvalidateRect (skinwindow, NULL, false); + InvalidateRect (camerawindow, NULL, false); +} + +void Undo (void) +{ + modify_t *m; + int temp; + + if (!undo_index) + return; + + if (!--undo_index) + { // back to unmodified state + modified = false; + SetWindowText (skinwindow, skin_filename); + } + m = &modify[undo_index]; + + // modify it + temp = pic[m->offset]; + pic[m->offset] = m->oldvalue; + rgb[m->offset] = palette[m->oldvalue*3] + + (palette[m->oldvalue*3+1]<<8) + (palette[m->oldvalue*3+2]<<16); + m->oldvalue = temp; + UpdateTexture (m->offset); + InvalidateRect (skinwindow, NULL, false); + InvalidateRect (camerawindow, NULL, false); + +} + +void Redo (void) +{ + modify_t *m; + int temp; + + if (undo_index == modify_index) + return; + + m = &modify[undo_index]; + + // modify it + temp = pic[m->offset]; + pic[m->offset] = m->oldvalue; + rgb[m->offset] = palette[m->oldvalue*3] + + (palette[m->oldvalue*3+1]<<8) + (palette[m->oldvalue*3+2]<<16); + m->oldvalue = temp; + UpdateTexture (m->offset); + InvalidateRect (skinwindow, NULL, false); + InvalidateRect (camerawindow, NULL, false); + + if (!undo_index++) + { // modified again + char text[1024]; + + modified = true; + sprintf (text, "%s *", skin_filename); + SetWindowText (skinwindow, text); + } +} + +//=================================================================== + +/* +============= +Skin_SaveFile + +Load a skin texture and the base.tri from the same directory +============= +*/ +void Skin_SaveFile (char *name) +{ + byte *data; + int i, j; + char backup[1024]; + + // back up the current file if it exists + sprintf (backup, "%s.bak", name); + remove (backup); + rename (name, backup); + + modified = false; + modified_past_autosave = false; + modify_index = undo_index = 0; + SetWindowText (skinwindow, skin_filename); + + data = malloc(skin_width*skin_height); + for (i=0 ; i 1024 || skin_height > 512) + Sys_Error ("Skin file is too large"); + + width2 = 1; + height2 = 1; + for (i=0 ; i<12 ; i++) + { + if (width2 < skin_width) + width2<<=1; + if (height2 < skin_height) + height2<<=1; + } + + // compatability shit for auto sizing of old skins + if (skin_width != 320 || skin_height != 200) + { + skinwidth = skin_width; + skinheight = skin_height; + } + else + { + skinwidth = 0; + skinheight = 0; + } +} + +/* +============= +Skin_LoadFile + +Load a skin texture and the base.tri from the same directory +============= +*/ +void Skin_LoadFile (char *name) +{ + int i, j, p; + byte *lbmpic; + byte *lbmpal; + char trifile[1024]; + int width, height; + + modified = false; + modified_past_autosave = false; + modify_index = undo_index = 0; + strcpy (skin_filename, name); + SetWindowText (skinwindow, skin_filename); + + // + // read the texture + // + Load256Image (skin_filename, &lbmpic, &lbmpal, &width, &height); + memcpy (palette, lbmpal, sizeof(palette)); + free (lbmpal); + + SetSizes (width, height); + + memset (pic, 0, sizeof(pic)); + for (i=0 ; i= width2*height2) + return; + + if (index == skin_last_index) + return; // in same pixel + skin_last_index = index; + + if (shift) + { + Pal_SetIndex (pic[index]); + return; + } + + SetSkin (index, selected_index); + UpdateWindow (skinwindow); +} + + +void DrawModelST (void) +{ + int i, j; + + glColor4f (1,1,1,1); + + glBegin (GL_TRIANGLES); + for (i=0 ; i abs(dy)) + skin_z += 0.25*dx; + else + skin_z += 0.25*dy; + InvalidateRect (skinwindow, NULL, false); + } + if (wParam == MK_RBUTTON) + { + skin_x -= 0.25*dx; + skin_y -= 0.25*dy; + InvalidateRect (skinwindow, NULL, false); + } + } + break; + + case WM_SIZE: + InvalidateRect(camerawindow, NULL, false); + break; + case WM_NCCALCSIZE:// don't let windows copy pixels + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + return WVR_REDRAW; + case WM_CLOSE: + DestroyWindow (hWnd); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 1 if handled message, 0 if not */ + return lRet; +} + + +/* +============== +WSkin_Create +============== +*/ +void WSkin_Create (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)Skin_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = SKIN_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Sys_Error ("RegisterClass failed"); + + skinwindow = CreateWindow (SKIN_WINDOW_CLASS , + "Skin View", + QE3_STYLE, + (int)(screen_width*0.5), + (int)(screen_height*0.2), + (int)(screen_width*0.5), + (int)(screen_height*0.8), // size + mainwindow, // parent window + 0, // no menu + hInstance, + 0); + if (!skinwindow) + Error ("Couldn't create skinwindow"); + +// RestoreWindowState(palettewindow, "palettewindow"); + ShowWindow (skinwindow, SW_SHOWDEFAULT); +} + + +/* +=================================================================== + + SKIN RESAMPLING + +=================================================================== +*/ + +HWND resamplewindow; +HDC resampledc; + +#define RESAMPLE_WINDOW_CLASS "TPResample" + +/* +============ +Resample_WndProc +============ +*/ +LONG WINAPI Resample_WndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: + resampledc = GetDC(hWnd); + bSetupPixelFormat(resampledc); + break; + } + + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + +/* +============== +ResampleWindow +============== +*/ +void ResampleWindow (HINSTANCE hInstance) +{ + WNDCLASS wc; + static qboolean registered; + + if (!registered) + { + registered = true; + /* Register the camera class */ + memset (&wc, 0, sizeof(wc)); + + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)Resample_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = RESAMPLE_WINDOW_CLASS; + + if (!RegisterClass (&wc) ) + Sys_Error ("RegisterClass failed"); + } + + resamplewindow = CreateWindow (RESAMPLE_WINDOW_CLASS , + "ResampleWindow", + WS_OVERLAPPED, + 0, 0, width2+32, height2+32, // size + NULL, // parent window + 0, // no menu + hInstance, + 0); + if (!resamplewindow) + Error ("Couldn't create skinwindow"); + + ShowWindow (resamplewindow, SW_SHOWDEFAULT); +} + + +void OutlineTexture (byte *pic) +{ + int i, j; + int x, y; + int empty; + byte oldpic[1024*512]; + + memcpy (oldpic, pic, width2*height2); + + empty = oldpic[0]; + + for (i=0 ; i= height2) + continue; + if (j+x < 0 || j+x >= width2) + continue; + if (oldpic[(i+y)*width2 + j+x] != empty) + { + pic[i*width2+j] = oldpic[(i+y)*width2 + j+x]; + goto done; + } + } + } +done: ; + } + } +} + +void ResampleSkin (void) +{ + int i, j; + static float oldtmcoords[10000][3][2]; + static int newindex[1024*512]; + static byte oldpic[1024*512]; + + // open a window of the texture size + ResampleWindow (main_instance); + + // get new S/T from current frame + memcpy (oldtmcoords, tmcoords, numfaces*3*2*4); + CalcTmCoords (); + + // draw all the triangles with the index texture + if (!wglMakeCurrent( resampledc, baseRC )) + Sys_Error ("wglMakeCurrent failed"); + + glViewport (0,0,width2, height2); + glClearColor (0,0,0,0); + glClear (GL_COLOR_BUFFER_BIT); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glOrtho (0, width2, 0, height2, -100, 100); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glColor4f (1,1,1,1); + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX); +#if 0 + glDisable(GL_TEXTURE_2D); + glBegin (GL_LINE_LOOP); + glVertex3f (1,1,10); + glVertex3f (skin_width-1,0,10); + glVertex3f (skin_width-1,skin_height-1,10); + glVertex3f (1,skin_height-1,10); + glEnd (); + glEnable(GL_TEXTURE_2D); +#endif + glBegin (GL_TRIANGLES); + for (i=0 ; i