demoII13_4.cpp
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:110k
源码类别:

游戏

开发平台:

Visual C++

  1. // DEMOII13_4.CPP - BSP Demo with z buffering
  2. // READ THIS!
  3. // To compile make sure to include DDRAW.LIB, DSOUND.LIB,
  4. // DINPUT.LIB, DINPUT8.LIB, WINMM.LIB in the project link list, and of course 
  5. // the C++ source modules T3DLIB1-11.CPP and the headers T3DLIB1-11.H
  6. // be in the working directory of the compiler
  7. // also this program uses a menu, thus you need to include the resource
  8. // template DEMOII13_1.RC to complile
  9. // INCLUDES ///////////////////////////////////////////////
  10. #define DEBUG_ON
  11. #define INITGUID       // make sure al the COM interfaces are available
  12.                        // instead of this you can include the .LIB file
  13.                        // DXGUID.LIB
  14. #define WIN32_LEAN_AND_MEAN  
  15. #include <windows.h>   // include important windows stuff
  16. #include <windowsx.h> 
  17. #include <mmsystem.h>
  18. #include <iostream.h>  // include important C/C++ stuff
  19. #include <conio.h>
  20. #include <stdlib.h>  
  21. #include <malloc.h> 
  22. #include <memory.h> 
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include <stdio.h> 
  26. #include <math.h>
  27. #include <io.h>
  28. #include <fcntl.h> 
  29.  
  30. #include <ddraw.h>    // directX includes
  31. #include <dsound.h> 
  32. #include <dmksctrl.h>
  33. #include <dmusici.h>
  34. #include <dmusicc.h>
  35. #include <dmusicf.h>
  36. #include <dinput.h>
  37. #include "T3DLIB1.h"  // game library includes
  38. #include "T3DLIB2.h"
  39. #include "T3DLIB3.h"
  40. #include "T3DLIB4.h"
  41. #include "T3DLIB5.h"
  42. #include "T3DLIB6.h"
  43. #include "T3DLIB7.h"
  44. #include "T3DLIB8.h"
  45. #include "T3DLIB9.h"
  46. #include "T3DLIB10.h"
  47. #include "T3DLIB11.h"
  48. #include "demoii13_1res.h" // include the resource header
  49. // DEFINES ////////////////////////////////////////////////
  50. // defines for windows interface
  51. #define WINDOW_CLASS_NAME "WIN3DCLASS"  // class name
  52. #define WINDOW_TITLE      "T3D Graphics Console Ver 2.0"
  53. #define WINDOW_WIDTH      800           // size of window
  54. #define WINDOW_HEIGHT     600
  55. #define WINDOW_BPP        16    // bitdepth of window (8,16,24 etc.)
  56.                                 // note: if windowed and not
  57.                                 // fullscreen then bitdepth must
  58.                                 // be same as system bitdepth
  59.                                 // also if 8-bit the a pallete
  60.                                 // is created and attached
  61. #define WINDOWED_APP      1     // 0 not windowed, 1 windowed
  62. // types of gadgets
  63. #define GADGET_TYPE_TOGGLE             0  // toggles from off/on, on/off
  64. #define GADGET_TYPE_MOMENTARY          1  // lights up while you press it
  65. #define GADGET_TYPE_STATIC             2  // doesn't do anything visual
  66. // gadget ids
  67. #define GADGET_ID_SEGMENT_MODE_ID      0  // drawing a single segment
  68. #define GADGET_ID_POLYLINE_MODE_ID     2  // drawing a polyline
  69. #define GADGET_ID_DELETE_MODE_ID       4  // delete lines 
  70. #define GADGET_ID_CLEAR_ALL_ID         6  // clear all lines
  71. #define GADGET_ID_FLOOR_MODE_ID        8  // drawing floor tiles
  72. #define GADGET_ID_WALL_TEXTURE_DEC     20 // previous texture
  73. #define GADGET_ID_WALL_TEXTURE_INC     21 // next texture
  74. #define GADGET_ID_WALL_HEIGHT_DEC      22 // decrease wall height
  75. #define GADGET_ID_WALL_HEIGHT_INC      23 // increase wall height
  76. #define GADGET_ID_FLOOR_TEXTURE_DEC    30 // previous floor texture
  77. #define GADGET_ID_FLOOR_TEXTURE_INC    31 // next floor texture
  78. #define GADGET_OFF                     0  // the gadget is off
  79. #define GADGET_ON                      1  // the gadget is on
  80. #define NUM_GADGETS                    11 // number of active gadget      
  81. // texture defines
  82. #define NUM_TEXTURES                   23  // number of available textures 
  83. #define TEXTURE_SIZE                   128 // size of texture m x m
  84. #define MAX_LINES                      256 // maximum number of lines in the demo
  85.                                            // these lines will later become 3-D walls
  86. #define LINE_INVALID                   0   // constants that define the state of a line
  87. #define LINE_VALID                     1
  88. // interface action states
  89. #define ACTION_STARTING_LINE           0  // used to determine if user is starting a new line
  90. #define ACTION_ENDING_LINE             1  // or ending one
  91. #define ACTION_STARTING_POLYLINE       2  // starting a polyline
  92. #define ACTION_ADDING_POLYLINE         3  // adding polyline segment
  93. #define ACTION_ENDING_POLYLINE         4  // done with polyline
  94. #define ACTION_DELETE_LINE             5  // deleting a line
  95. #define ACTION_FLOOR_MODE              6  // adding floor tiles
  96. // control areas of GUI
  97. #define BSP_MIN_X                  0      // the bounding rectangle of the
  98. #define BSP_MAX_X                  648    // BSP editor area
  99. #define BSP_MIN_Y                  0
  100. #define BSP_MAX_Y                  576
  101. #define BSP_GRID_SIZE              24     // the width/height of each cell
  102. #define BSP_CELLS_X                28     // number of horizontal tick marks
  103. #define BSP_CELLS_Y                25     // number of vertical tick marks
  104. #define SCREEN_TO_WORLD_X    (-BSP_MAX_X/2)   // the translation factors to move the origin
  105. #define SCREEN_TO_WORLD_Z    (-BSP_MAX_Y/2)   // to the center of the 2D universe
  106. #define WORLD_SCALE_X              2      // scaling factors from screen space to world
  107. #define WORLD_SCALE_Y              2      // space (note the inversion of the Z)
  108. #define WORLD_SCALE_Z             -2
  109. // bounds of gui components
  110. #define INTERFACE_MIN_X            656    // the bounding rectangle of the control
  111. #define INTERFACE_MAX_X            800    // button area to the right of editor
  112. #define INTERFACE_MIN_Y            0
  113. #define INTERFACE_MAX_Y            600
  114. // editor states
  115. #define EDITOR_STATE_INIT          0      // the editor is initializing
  116. #define EDITOR_STATE_EDIT          1      // the editor is in edit mode
  117. #define EDITOR_STATE_VIEW          2      // the editor is in viewing mode
  118. // simple movement model defines
  119. #define CAM_DECEL                  (.25)  // deceleration/friction
  120. #define MAX_SPEED                  15     // maximum speed of camera
  121. // create some constants for ease of access
  122. #define AMBIENT_LIGHT_INDEX   0 // ambient light index
  123. #define INFINITE_LIGHT_INDEX  1 // infinite light index
  124. #define POINT_LIGHT_INDEX     2 // point light index
  125. #define POINT_LIGHT2_INDEX    3 // point light index
  126. // hacking stuff...
  127. #define NUM_SCENE_OBJECTS          500    // number of scenery objects 
  128. #define UNIVERSE_RADIUS            2000   // size of universe
  129. // new rendering context defines
  130. // M A C R O S ///////////////////////////////////////////////////////////////
  131. // TYPES //////////////////////////////////////////////////
  132. // to help a little with the buttons and controls
  133. typedef struct GADGET_TYP
  134.         {
  135.         int type;          // type of gadget
  136.         int state;         // state of gadget
  137.         int id;            // id number of gadget
  138.         int x0, y0;        // screen position of gadget
  139.         int width, height; // size of gadget
  140.         BOB_PTR bitmap;    // bitmaps of gadget
  141.         int count;
  142.  
  143.        } GADGET, *GADGET_PTR;
  144. // the bsp line type that represents single 2d lines
  145. typedef struct BSP2D_LINE_TYP 
  146.         {
  147.         int id;            // id of line
  148.         int color;         // color of line (polygon)
  149.         int attr;          // line (polygon) attributes (shading modes etc.)
  150.         int texture_id;    // texture index 
  151.         POINT2D p0, p1;    // endpoints of line
  152.         int elev, height;  // height of wall
  153.         } BSP2D_LINE, *BSP2D_LINE_PTR; 
  154. // PROTOTYPES /////////////////////////////////////////////
  155. // game console
  156. int Game_Init(void *parms=NULL);
  157. int Game_Shutdown(void *parms=NULL);
  158. int Game_Main(void *parms=NULL);
  159. // windows gui functions
  160. BOOL CALLBACK DialogProc(HWND hwnddlg,    // handle to dialog box
  161.                          UINT umsg,       // message
  162.                          WPARAM waram,    // first message parameter
  163.                          LPARAM lparam);  // second message parameter
  164. // gui interface functions
  165. int Process_Gadgets(int mx, int my, UCHAR mbuttons[]);
  166. void Draw_Gadgets(LPDIRECTDRAWSURFACE7 lpdds);
  167. void Load_Gadgets(void);
  168. void Draw_Grid(UCHAR *video_buffer, 
  169.                int mempitch,
  170.                int rgbcolor, 
  171.                int x0, int y0, 
  172.                int xpitch, int ypitch,
  173.                int xcells, int ycells);
  174. int Delete_Line(int x,int y,int delete_line);
  175. void Draw_Lines(UCHAR *video_buffer, int mempitch);
  176. void Draw_Floors(LPDIRECTDRAWSURFACE7 lpdds);
  177. void Reset_Editor(void);
  178. // bsp loading and saving
  179. int Load_BSP_File_LEV(char *filename);
  180. int Save_BSP_File_LEV(char *filename, int flags);
  181. void Convert_Lines_To_Walls(void);
  182. int Generate_Floors_OBJECT4DV2(OBJECT4DV2_PTR obj,   // pointer to object
  183.                                 int rgbcolor,       // color of floor if no texture        
  184.                                 VECTOR4D_PTR pos,   // initial position 
  185.                                 VECTOR4D_PTR rot,   // initial rotations
  186.                                 int poly_attr);     // the shading attributes we would like
  187. // GLOBALS ////////////////////////////////////////////////
  188. HWND main_window_handle           = NULL; // save the window handle
  189. HINSTANCE main_instance           = NULL; // save the instance
  190. char buffer[2048];                        // used to print text
  191. char ascfilename[256]; // holds file name when loader loads
  192. BOB background;        // the background image
  193. BOB button_img;        // holds the button images
  194. BITMAP_IMAGE background_bmp;   // holds the background
  195. BOB textures;          // holds the textures for display in editor
  196. BITMAP_IMAGE texturemaps[NUM_TEXTURES]; // holds the textures for the 3D display
  197.                                         // copies basically...
  198. BSP2D_LINE lines[MAX_LINES];   // this holds the lines in the system, we could
  199.                                // use a linked list, but let's not make this harder
  200.                                // than it already is!
  201. BSPNODEV1_PTR wall_list = NULL,  // global pointer to the linked list of walls
  202.               bsp_root  = NULL;  // global pointer to root of BSP tree
  203. int floors[BSP_CELLS_Y-1][BSP_CELLS_X-1]; // hold the texture id's for the floor
  204.                                           // which we will turn into a mesh later
  205. // sound ids
  206. int beep0_sound_id = 0;      // button beep sound
  207. int total_lines     = 0;     // number of lines that have been defined
  208. int starting_line   = 0;     // used to close contours
  209. int snap_to_grid    = 1;     // flag to snap to grid        
  210. int view_grid       = 1;     // flag to show grid
  211. int view_walls      = 1;     // flag to show walls
  212. int view_floors     = 1;     // flag to show floors
  213. int mouse_debounce[3]   = {0,0,0}; // used to debounce left, middle, right buttons
  214. int nearest_line        = -1;      // index of nearest line to mouse pointer
  215. int texture_index_wall  = 11;      // index of wall texture
  216. int texture_index_floor = 13;      // index of floor texture
  217. int wall_height         = 64;      // initial wall height
  218. int num_floor_tiles     = 0;       // current number of floor tiles
  219. int poly_attr           = 0;       // general polygon attribute
  220. int poly_color          = 0;       // general polygon color
  221. int ceiling_height      = 0;       // height of ceiling 
  222. int editor_state        = EDITOR_STATE_INIT; // starting state of editor
  223. // define all the gadgets, their type, state, bitmap index, position, etc.
  224. GADGET buttons[NUM_GADGETS] = 
  225.        { 
  226.        {GADGET_TYPE_TOGGLE,    GADGET_ON, GADGET_ID_SEGMENT_MODE_ID,    670, 50,          116,32, NULL,0}, 
  227.        {GADGET_TYPE_TOGGLE,    GADGET_OFF, GADGET_ID_POLYLINE_MODE_ID,  670, 50+(50-12),  116,32, NULL,0}, 
  228.        {GADGET_TYPE_TOGGLE,    GADGET_OFF, GADGET_ID_DELETE_MODE_ID,    670, 50+(100-24), 116,32, NULL,0}, 
  229.        {GADGET_TYPE_MOMENTARY, GADGET_OFF, GADGET_ID_CLEAR_ALL_ID,      670, 348,         116,32, NULL,0}, 
  230.        {GADGET_TYPE_TOGGLE,    GADGET_OFF, GADGET_ID_FLOOR_MODE_ID,     670, 556,         116,32, NULL,0}, 
  231.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_WALL_TEXTURE_DEC,  680, 316,         16,16, NULL,0}, 
  232.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_WALL_TEXTURE_INC,  700, 316,         16,16, NULL,0}, 
  233.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_WALL_HEIGHT_DEC,   680, 208,         16,16, NULL,0}, 
  234.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_WALL_HEIGHT_INC,   700, 208,         16,16, NULL,0}, 
  235.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_FLOOR_TEXTURE_DEC, 680, 522,         16,16, NULL,0}, 
  236.        {GADGET_TYPE_STATIC,    GADGET_OFF, GADGET_ID_FLOOR_TEXTURE_INC, 700, 522,         16,16, NULL,0}, 
  237.        };
  238. // set initial action state
  239. int action = ACTION_STARTING_LINE;
  240. // 3D viewing stuff
  241. // initialize camera position and direction
  242. POINT4D  cam_pos    = {0,0,0,1};
  243. POINT4D  cam_target = {0,0,0,1};
  244. VECTOR4D cam_dir    = {0,0,0,1};
  245. VECTOR4D vz    = {0,0,1,1};
  246. VECTOR4D vdir  = {0,0,0,1};
  247. // all your initialization code goes here...
  248. VECTOR4D vscale={1.0,1.0,1.0,1},  
  249.          vpos = {0,0,150,1}, 
  250.          vrot = {0,0,0,1};
  251. CAM4DV1         cam;           // the single camera
  252. OBJECT4DV2      obj_scene,     // floor/ceiling object
  253.                 obj_moveable;  // the movable object
  254. RENDERLIST4DV2  rend_list;     // the render list
  255. ZBUFFERV1       zbuffer;       // out little z buffer!
  256. RENDERCONTEXTV1 rc;            // the rendering context
  257. RGBAV1          white,          // general colors 
  258.                 gray, 
  259.                 black, 
  260.                 red, 
  261.                 green, 
  262.                 blue,
  263.                 yellow,
  264.                 orange; 
  265. // physical model defines
  266. float cam_speed  = 0;       // speed of the camera/jeep
  267. // hacking stuff
  268. POINT4D scene_objects[NUM_SCENE_OBJECTS]; // positions of scenery objects
  269. // MACROS ////////////////////////////////////////////////
  270. // FUNCTIONS //////////////////////////////////////////////
  271. LRESULT CALLBACK WindowProc(HWND hwnd, 
  272.     UINT msg, 
  273.                             WPARAM wparam, 
  274.                             LPARAM lparam)
  275. {
  276. // this is the main message handler of the system
  277. PAINTSTRUCT ps;    // used in WM_PAINT
  278. HDC hdc;    // handle to a device context
  279. HMENU       hmenu;     // menu handle sending commands
  280.   
  281. // what is the message 
  282. switch(msg)
  283. {
  284. case WM_CREATE: 
  285.         {
  286. // do initialization stuff here
  287. return(0);
  288. } break;
  289.     case WM_PAINT:
  290.          {
  291.          // start painting
  292.          hdc = BeginPaint(hwnd,&ps);
  293.          // end painting
  294.          EndPaint(hwnd,&ps);
  295.          return(0);
  296.         } break;
  297.      // pass mouse events out to globals
  298.      case WM_MOUSEMOVE:
  299.           {
  300.           int fwkeys     = wparam;          // key flags 
  301.           mouse_state.lX = LOWORD(lparam);  // horizontal position of cursor 
  302.           mouse_state.lY = HIWORD(lparam);  // vertical position of cursor 
  303.           } break;
  304.      
  305.      case WM_LBUTTONDOWN:
  306.           {
  307.           int fwkeys     = wparam;          // key flags 
  308.           mouse_state.lX = LOWORD(lparam);  // horizontal position of cursor 
  309.           mouse_state.lY = HIWORD(lparam);  // vertical position of cursor 
  310.           mouse_state.rgbButtons[0] = 1;
  311.           } break;
  312.      case WM_MBUTTONDOWN:
  313.           {
  314.           int fwkeys     = wparam;          // key flags 
  315.           mouse_state.lX = LOWORD(lparam);  // horizontal position of cursor 
  316.           mouse_state.lY = HIWORD(lparam);  // vertical position of cursor 
  317.           mouse_state.rgbButtons[1] = 1;
  318.           } break;
  319.      case WM_RBUTTONDOWN:
  320.           {
  321.           int fwkeys     = wparam;          // key flags 
  322.           mouse_state.lX = LOWORD(lparam);  // horizontal position of cursor 
  323.           mouse_state.lY = HIWORD(lparam);  // vertical position of cursor 
  324.           mouse_state.rgbButtons[2] = 1;
  325.           } break;
  326.      case WM_COMMAND:
  327.          {
  328.          // get the menu that has generated this command
  329.          hmenu = GetMenu(hwnd);
  330.          
  331.           // what is the id of the command
  332.           switch(LOWORD(wparam))
  333.                 {
  334.                 // handle the FILE menu
  335.                 case ID_FILE_EXIT:
  336.                      {
  337.                      // terminate window
  338.                      PostQuitMessage(0);
  339.                      } break;
  340.                 case ID_FILE_LOAD_LEV:
  341.                      {
  342.                      // call load dialog and load .lev file
  343.                      if (DialogBox (main_instance, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, DialogProc ) == IDOK )
  344.      {
  345.                        Load_BSP_File_LEV(ascfilename);
  346.                        } // end if
  347.                      } break;
  348.                 case ID_FILE_SAVE_LEV:
  349.                      {
  350.                      // call save dialog and load .lev file
  351.                      if (DialogBox (main_instance, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, DialogProc ) == IDOK )
  352.       {
  353.                         Save_BSP_File_LEV(ascfilename,0);
  354.                         } // end if
  355.                      } break;
  356.                 case IDC_VIEWGRID:
  357.                      {
  358.                      // toggle viewing state
  359.                      view_grid = -view_grid;
  360.  
  361.                      // toggle checkmark
  362.                      if (view_grid==1)
  363.                         CheckMenuItem(hmenu, IDC_VIEWGRID, MF_CHECKED);
  364.                      else
  365.                         CheckMenuItem(hmenu, IDC_VIEWGRID, MF_UNCHECKED);
  366.                      } break;
  367.                 case IDC_VIEWWALLS:
  368.                      {
  369.                      // toggle viewing state
  370.                      view_walls = -view_walls;
  371.  
  372.                      // toggle checkmark
  373.                      if (view_walls==1)
  374.                         CheckMenuItem(hmenu, IDC_VIEWWALLS, MF_CHECKED);
  375.                      else
  376.                         CheckMenuItem(hmenu, IDC_VIEWWALLS, MF_UNCHECKED);
  377.                      } break;
  378.                 case IDC_VIEWFLOORS:
  379.                      {
  380.                      // toggle viewing state
  381.                      view_floors = -view_floors;
  382.  
  383.                      // toggle checkmark
  384.                      if (view_floors==1)
  385.                         CheckMenuItem(hmenu, IDC_VIEWFLOORS, MF_CHECKED);
  386.                      else
  387.                         CheckMenuItem(hmenu, IDC_VIEWFLOORS, MF_UNCHECKED);
  388.                      } break;
  389.                 case ID_BUILD_TO_FILE:
  390.                      {
  391.                      // not fully implemented yet....
  392.                      // first delete any previous tree
  393.                      Bsp_Delete(bsp_root);
  394.                      // convert 2-d lines to 3-d walls
  395.                      Convert_Lines_To_Walls();
  396.                      // build the 3-D bsp tree
  397.                      Bsp_Build_Tree(wall_list);
  398.                      // alias the bsp tree to the wall list first node
  399.                      // which has now become the root of the tree
  400.                      bsp_root = wall_list;
  401.    
  402.                      // print out to error file
  403.                      Bsp_Print(bsp_root);
  404.                      // save .bsp to file
  405.                      } break;
  406.                 case ID_COMPILE_VIEW:
  407.                      {
  408.                      // compile bsp
  409.                      // first delete any previous tree
  410.                      Bsp_Delete(bsp_root);
  411.                      // reset ceiling height
  412.                      // conversion will find heighest
  413.                      ceiling_height  = 0;
  414.              
  415.                      // convert 2-d lines to 3-d walls
  416.                      Convert_Lines_To_Walls();
  417.                      // build the 3-D bsp tree
  418.                      Bsp_Build_Tree(wall_list);
  419.                      // alias the bsp tree to the wall list first node
  420.                      // which has now become the root of the tree
  421.                      bsp_root = wall_list;
  422.    
  423.                      // print out to error file
  424.                      Bsp_Print(bsp_root);
  425.                      // position camera at (0,0,0) and wall height
  426.                      cam.pos.x = 0;
  427.                      cam.pos.y = wall_height; 
  428.                      cam.pos.z = 0;
  429.                      // set heading and speed
  430.                      cam.dir.y = 0;
  431.                      cam_speed = 0;
  432.                      // set position of floor to (0,0,0)
  433.                      vpos.x = 0;
  434.                      vpos.y = 0;
  435.                      vpos.z = 0;
  436.                      // generate the floor mesh object
  437.                      Generate_Floors_OBJECT4DV2(&obj_scene,   // pointer to object
  438.                               RGB16Bit(255,255,255),         // color of floor if no texture        
  439.                               &vpos,                         // initial position
  440.                               NULL,                          // initial rotations
  441.                               POLY4DV2_ATTR_DISABLE_MATERIAL 
  442.                               | POLY4DV2_ATTR_2SIDED 
  443.                               | POLY4DV2_ATTR_RGB16 
  444.                               | POLY4DV2_ATTR_SHADE_MODE_TEXTURE
  445.                               | POLY4DV2_ATTR_SHADE_MODE_FLAT); // the shading attributes we would like
  446.                      // switch states to view state
  447.                      editor_state = EDITOR_STATE_VIEW;
  448.                      } break;
  449.                 // handle the HELP menu
  450.                 case ID_HELP_ABOUT:                 
  451.                      {
  452.                      //  pop up a message box
  453.                      MessageBox(hwnd, "Version 1.0", 
  454.                                "BSP Level Generator",
  455.                                 MB_OK);
  456.                      } break;
  457.                 default: break;
  458.              } // end switch wparam
  459.           } break; // end WM_COMMAND
  460. case WM_DESTROY: 
  461. {
  462. // kill the application
  463. PostQuitMessage(0);
  464. return(0);
  465. } break;
  466. default:break;
  467.     } // end switch
  468. // process any messages that we didn't take care of 
  469. return (DefWindowProc(hwnd, msg, wparam, lparam));
  470. } // end WinProc
  471. ///////////////////////////////////////////////////////////
  472. BOOL CALLBACK DialogProc(HWND hwnddlg,  // handle to dialog box
  473.                          UINT umsg,     // message
  474.                          WPARAM wparam, // first message parameter
  475.                          LPARAM lparam)  // second message parameter
  476. {
  477. // dialog handler for the line input
  478. // get the handles to controls...
  479. HWND htextedit = GetDlgItem(hwnddlg, IDC_EDIT1);
  480. // options (not implemented yet...)
  481. HWND hoption1 = GetDlgItem(hwnddlg, IDC_OPTION1);
  482. HWND hoption2 = GetDlgItem(hwnddlg, IDC_OPTION2);
  483. HWND hoption3 = GetDlgItem(hwnddlg, IDC_OPTION3);
  484. HWND hoption4 = GetDlgItem(hwnddlg, IDC_OPTION4);
  485. switch (umsg)
  486.     {
  487. case WM_INITDIALOG:
  488. {
  489. SetFocus ( htextedit );
  490. } break;
  491. case WM_COMMAND:
  492.  {
  493.  switch (LOWORD(wparam))
  494.                 {
  495.                 case IDOK:
  496.     {
  497.                      // text has been entered, update gloabal string with filename
  498.  int linelength = SendMessage ( htextedit, EM_LINELENGTH, 0, 0 );
  499.    ascfilename[0] = (unsigned char )255;
  500.  SendMessage (htextedit, EM_GETLINE, 0, (LPARAM) (LPCSTR) ascfilename );
  501.  ascfilename[linelength] = 0;
  502.                      // get checks 
  503.                      SendMessage(hoption1, BM_GETCHECK, 0,0);
  504.                      SendMessage(hoption2, BM_GETCHECK, 0,0);
  505.                      SendMessage(hoption3, BM_GETCHECK, 0,0);
  506.                      SendMessage(hoption4, BM_GETCHECK, 0,0);
  507.  
  508.                      // terminate dialog
  509.  EndDialog (hwnddlg, IDOK );
  510.          return TRUE;
  511.  } break;
  512. case IDCANCEL:
  513. {
  514.                     // terminate dialog
  515. EndDialog ( hwnddlg, IDCANCEL );
  516. return TRUE;
  517.        } break;
  518.       default: break;
  519. } // end switch 
  520.        
  521.           } break;
  522. } // end switch
  523. // return normal
  524. return 0;
  525. } // end DialogProc
  526. // WINMAIN ////////////////////////////////////////////////
  527. int WINAPI WinMain( HINSTANCE hinstance,
  528. HINSTANCE hprevinstance,
  529. LPSTR lpcmdline,
  530. int ncmdshow)
  531. {
  532. // this is the winmain function
  533. WNDCLASS winclass; // this will hold the class we create
  534. HWND  hwnd; // generic window handle
  535. MSG  msg; // generic message
  536. HDC      hdc;       // generic dc
  537. PAINTSTRUCT ps;     // generic paintstruct
  538. // first fill in the window class stucture
  539. winclass.style = CS_DBLCLKS | CS_OWNDC | 
  540.                           CS_HREDRAW | CS_VREDRAW;
  541. winclass.lpfnWndProc = WindowProc;
  542. winclass.cbClsExtra = 0;
  543. winclass.cbWndExtra = 0;
  544. winclass.hInstance = hinstance;
  545. winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  546. winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  547. winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  548. winclass.lpszMenuName = MAKEINTRESOURCE(IDR_ASCMENU);
  549. winclass.lpszClassName = WINDOW_CLASS_NAME;
  550. // register the window class
  551. if (!RegisterClass(&winclass))
  552. return(0);
  553. // create the window, note the test to see if WINDOWED_APP is
  554. // true to select the appropriate window flags
  555. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  556.   WINDOW_TITLE,  // title
  557.   (WINDOWED_APP ? (WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION) : (WS_POPUP | WS_VISIBLE)),
  558.     0,0,    // x,y
  559.   WINDOW_WIDTH,  // width
  560.                           WINDOW_HEIGHT, // height
  561.   NULL,    // handle to parent 
  562.   NULL,    // handle to menu
  563.   hinstance,// instance
  564.   NULL))) // creation parms
  565. return(0);
  566. // save the window handle and instance in a global
  567. main_window_handle = hwnd;
  568. main_instance      = hinstance;
  569. // resize the window so that client is really width x height
  570. if (WINDOWED_APP)
  571. {
  572. // now resize the window, so the client area is the actual size requested
  573. // since there may be borders and controls if this is going to be a windowed app
  574. // if the app is not windowed then it won't matter
  575. RECT window_rect = {0,0,WINDOW_WIDTH-1,WINDOW_HEIGHT-1};
  576. // make the call to adjust window_rect
  577. AdjustWindowRectEx(&window_rect,
  578.      GetWindowStyle(main_window_handle),
  579.      GetMenu(main_window_handle) != NULL,  
  580.      GetWindowExStyle(main_window_handle));
  581. // save the global client offsets, they are needed in DDraw_Flip()
  582. window_client_x0 = -window_rect.left;
  583. window_client_y0 = -window_rect.top;
  584. // now resize the window with a call to MoveWindow()
  585. MoveWindow(main_window_handle,
  586.            0, // x position
  587.            0, // y position
  588.            window_rect.right - window_rect.left, // width
  589.            window_rect.bottom - window_rect.top, // height
  590.            FALSE);
  591. // show the window, so there's no garbage on first render
  592. ShowWindow(main_window_handle, SW_SHOW);
  593. } // end if windowed
  594. // perform all game console specific initialization
  595. Game_Init();
  596. // disable CTRL-ALT_DEL, ALT_TAB, comment this line out 
  597. // if it causes your system to crash
  598. SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, NULL, 0);
  599. // enter main event loop
  600. while(1)
  601. {
  602. if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  603. // test if this is a quit
  604.         if (msg.message == WM_QUIT)
  605.            break;
  606. // translate any accelerator keys
  607. TranslateMessage(&msg);
  608. // send the message to the window proc
  609. DispatchMessage(&msg);
  610. } // end if
  611.     
  612.     // main game processing goes here
  613.     Game_Main();
  614. } // end while
  615. // shutdown game and release all resources
  616. Game_Shutdown();
  617. // enable CTRL-ALT_DEL, ALT_TAB, comment this line out 
  618. // if it causes your system to crash
  619. SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, NULL, 0);
  620. // return to Windows like this
  621. return(msg.wParam);
  622. } // end WinMain
  623. // T3D II GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  624. int Game_Init(void *parms)
  625. {
  626. // this function is where you do all the initialization 
  627. // for your game
  628. int index; // looping var
  629. // start up DirectDraw (replace the parms as you desire)
  630. DDraw_Init2(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, WINDOWED_APP);
  631. // initialize directinput
  632. DInput_Init();
  633. // acquire the keyboard 
  634. DInput_Init_Keyboard();
  635. //DInput_Init_Mouse();
  636. // add calls to acquire other directinput devices here...
  637. // initialize directsound and directmusic
  638. DSound_Init();
  639. DMusic_Init();
  640. // hide the mouse
  641. if (!WINDOWED_APP)
  642.     ShowCursor(FALSE);
  643. // seed random number generator 
  644. srand(Start_Clock());
  645. Open_Error_File("BSPERROR.TXT");
  646. // initialize math engine
  647. Build_Sin_Cos_Tables();
  648. // build the inverse cosine lookup
  649. Build_Inverse_Cos_Table(dp_inverse_cos, 360);
  650. // load in the background
  651. Create_BOB(&background, 0,0,800,600,1, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  652. Load_Bitmap_File(&bitmap16bit, "bspgui02.bmp");
  653. Load_Frame_BOB16(&background, &bitmap16bit,0,0,0,BITMAP_EXTRACT_MODE_ABS);
  654. Unload_Bitmap_File(&bitmap16bit);
  655. // load all the gadget imagery
  656. Load_Gadgets();
  657. // load the sounds
  658. beep0_sound_id = DSound_Load_WAV("menuitem.wav");
  659. // load the textures
  660. // create the bob image to hold all the textures
  661. Create_BOB(&textures, 0,0,TEXTURE_SIZE,TEXTURE_SIZE,NUM_TEXTURES, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  662. // set visibility
  663. textures.attr |= BOB_ATTR_VISIBLE;
  664. // interate and extract both the off and on bitmaps for each animated button
  665. for (index = 0; index < NUM_TEXTURES; index++)
  666.     {
  667.     // load the bitmap to extract imagery
  668.     sprintf(buffer, "bspdemotext128_%d.bmp", index);
  669.     Load_Bitmap_File(&bitmap16bit, buffer);
  670.     // load the frame for the bob
  671.     Load_Frame_BOB16(&textures, &bitmap16bit,index,0,0,BITMAP_EXTRACT_MODE_ABS);
  672.     // load in the frame for the bitmap
  673.     Create_Bitmap(&texturemaps[index],0,0, TEXTURE_SIZE, TEXTURE_SIZE, 16);
  674.     Load_Image_Bitmap16(&texturemaps[index], &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  675.     // unload the bitmap
  676.     Unload_Bitmap_File(&bitmap16bit);
  677.     } // end for index
  678. // initialize the camera with 90 FOV, normalized coordinates
  679. Init_CAM4DV1(&cam,            // the camera object
  680.              CAM_MODEL_EULER, // the euler model
  681.              &cam_pos,        // initial camera position
  682.              &cam_dir,        // initial camera angles
  683.              &cam_target,     // no target
  684.              5.0,            // near and far clipping planes
  685.              12000.0,
  686.              120.0,           // field of view in degrees
  687.              WINDOW_WIDTH,    // size of final screen viewport
  688.              WINDOW_HEIGHT);
  689.  
  690. // set a scaling vector
  691. VECTOR4D_INITXYZ(&vscale,.15,.15,.15); 
  692. // load the object in
  693. Load_OBJECT4DV2_COB2(&obj_moveable, "rec_flat_textured_01.cob",  
  694.                      &vscale, &vpos, &vrot, VERTEX_FLAGS_SWAP_YZ  | VERTEX_FLAGS_INVERT_Z |
  695.                                             VERTEX_FLAGS_TRANSFORM_LOCAL 
  696.                                            /* VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD*/,0 );
  697. // position the scenery objects randomly
  698. for (index = 0; index < NUM_SCENE_OBJECTS; index++)
  699.     {
  700.     // randomly position object
  701.     scene_objects[index].x = RAND_RANGE(-UNIVERSE_RADIUS, UNIVERSE_RADIUS);
  702.     scene_objects[index].y = RAND_RANGE(-200, 200);
  703.     scene_objects[index].z = RAND_RANGE(-UNIVERSE_RADIUS, UNIVERSE_RADIUS);
  704.     } // end for
  705. // set up lights
  706. Reset_Lights_LIGHTV2(lights2, MAX_LIGHTS);
  707. // create some working colors
  708. white.rgba = _RGBA32BIT(255,255,255,0);
  709. gray.rgba  = _RGBA32BIT(128,128,128,0);
  710. black.rgba = _RGBA32BIT(0,0,0,0);
  711. red.rgba   = _RGBA32BIT(255,0,0,0);
  712. green.rgba = _RGBA32BIT(0,255,0,0);
  713. blue.rgba  = _RGBA32BIT(0,0,255,0);
  714. orange.rgba = _RGBA32BIT(255,128,0,0);
  715. yellow.rgba  = _RGBA32BIT(255,255,0,0);
  716. // ambient light
  717. Init_Light_LIGHTV2(lights2,               // array of lights to work with
  718.                    AMBIENT_LIGHT_INDEX,   
  719.                    LIGHTV2_STATE_ON,      // turn the light on
  720.                    LIGHTV2_ATTR_AMBIENT,  // ambient light type
  721.                    gray, black, black,    // color for ambient term only
  722.                    NULL, NULL,            // no need for pos or dir
  723.                    0,0,0,                 // no need for attenuation
  724.                    0,0,0);                // spotlight info NA
  725. VECTOR4D dlight_dir = {-1,0,-1,1}; 
  726. // directional light
  727. Init_Light_LIGHTV2(lights2,               // array of lights to work with
  728.                    INFINITE_LIGHT_INDEX,  
  729.                    LIGHTV2_STATE_ON,      // turn the light on
  730.                    LIGHTV2_ATTR_INFINITE, // infinite light type
  731.                    black, gray, black,    // color for diffuse term only
  732.                    NULL, &dlight_dir,     // need direction only
  733.                    0,0,0,                 // no need for attenuation
  734.                    0,0,0);                // spotlight info NA
  735. VECTOR4D plight_pos = {0,200,0,1};
  736. // point light
  737. Init_Light_LIGHTV2(lights2,
  738.                    POINT_LIGHT_INDEX,
  739.                    LIGHTV2_STATE_ON,      // turn the light on
  740.                    LIGHTV2_ATTR_POINT,    // pointlight type
  741.                    black, gray, black,  // color for diffuse term only
  742.                    &plight_pos, NULL,     // need pos only
  743.                    0,.001,0,              // linear attenuation only
  744.                    0,0,1);                // spotlight info NA
  745. // point light
  746. Init_Light_LIGHTV2(lights2,
  747.                    POINT_LIGHT2_INDEX,
  748.                    LIGHTV2_STATE_ON,    // turn the light on
  749.                    LIGHTV2_ATTR_POINT,  // pointlight type
  750.                    black, white, black,   // color for diffuse term only
  751.                    &plight_pos, NULL,   // need pos only
  752.                    0,.002,0,            // linear attenuation only
  753.                    0,0,1);              // spotlight info NA
  754. // create the z buffer
  755. Create_Zbuffer(&zbuffer,
  756.                WINDOW_WIDTH,
  757.                WINDOW_HEIGHT,
  758.                ZBUFFER_ATTR_32BIT);
  759. // reset the editor
  760. Reset_Editor();
  761. // load background image that scrolls 
  762. Load_Bitmap_File(&bitmap16bit, "red01a.BMP");
  763. Create_Bitmap(&background_bmp,0,0,800,600,16);
  764. Load_Image_Bitmap16(&background_bmp, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  765. Unload_Bitmap_File(&bitmap16bit);
  766. // return success
  767. return(1);
  768. } // end Game_Init
  769. ///////////////////////////////////////////////////////////
  770. int Game_Shutdown(void *parms)
  771. {
  772. // this function is where you shutdown your game and
  773. // release all resources that you allocated
  774. // shut everything down
  775. // release all your resources created for the game here....
  776. // now directsound
  777. DSound_Stop_All_Sounds();
  778. DSound_Delete_All_Sounds();
  779. DSound_Shutdown();
  780. // directmusic
  781. DMusic_Delete_All_MIDI();
  782. DMusic_Shutdown();
  783. // shut down directinput
  784. DInput_Release_Keyboard();
  785. // shutdown directinput
  786. DInput_Shutdown();
  787. // shutdown directdraw last
  788. DDraw_Shutdown();
  789. // release the z buffer
  790. Delete_Zbuffer(&zbuffer);
  791. // close the error file
  792. Close_Error_File();
  793. // return success
  794. return(1);
  795. } // end Game_Shutdown
  796. ///////////////////////////////////////////////////////////////////////////////
  797. int Game_Main(void *parms)
  798. {
  799. // this is the workhorse of your game it will be called
  800. // continuously in real-time this is like main() in C
  801. // all the calls for you game go here!
  802. static int id = -1;
  803. static MATRIX4X4 mrot;   // general rotation matrix
  804. static float plight_ang = 0, 
  805.              slight_ang = 0; // angles for light motion
  806. // use these to rotate objects
  807. static float x_ang = 0, y_ang = 0, z_ang = 0;
  808. // state variables for different rendering modes and help
  809. static int wireframe_mode = 1;
  810. static int backface_mode  = -1;
  811. static int lighting_mode  = 1;
  812. static int help_mode      = 1;
  813. static int zsort_mode     = -1;
  814. static int x_clip_mode    = 1;
  815. static int y_clip_mode    = 1;
  816. static int z_clip_mode    = 1;
  817. static int z_buffer_mode  = 1;
  818. static int display_mode   = 1;
  819. static int bsp_backface_mode   = 1;
  820. char work_string[256]; // temp string
  821. int index; // looping var
  822. // is user in editor mode or viewing mode?
  823. switch(editor_state)
  824.       {
  825.       case EDITOR_STATE_INIT: /////////////////////////////////////////////////
  826.       {
  827.        
  828.       // now transition to edit mode
  829.       editor_state = EDITOR_STATE_EDIT;
  830.       } break;
  831.       case EDITOR_STATE_EDIT: /////////////////////////////////////////////////
  832.       {
  833.     // start the timing clock
  834.     Start_Clock();
  835.     // clear the drawing surface 
  836.     //DDraw_Fill_Surface(lpddsback, 0);
  837.     lpddsback->Blt(NULL, background.images[0], NULL, DDBLT_WAIT, NULL);
  838.     // read keyboard and other devices here
  839.     DInput_Read_Keyboard();
  840.     //DInput_Read_Mouse();
  841.     // game logic here...
  842.     // find nearest line 
  843.     nearest_line = Delete_Line(mouse_state.lX, mouse_state.lY,0);
  844.     // is user trying to press left button?
  845.     if (mouse_state.rgbButtons[0] || mouse_state.rgbButtons[2])// && mouse_debounce[0] == 0)
  846.        {
  847.        // determine area click is occuring in
  848.        if (mouse_state.lX > INTERFACE_MIN_X && mouse_state.lX < INTERFACE_MAX_X && 
  849.            mouse_state.lY > INTERFACE_MIN_Y && mouse_state.lY < INTERFACE_MAX_Y)
  850.        { 
  851.        // check for gadget
  852.        if ((id = Process_Gadgets(mouse_state.lX, mouse_state.lY, mouse_state.rgbButtons)) >= 0)
  853.           {
  854.           // play a sound first
  855.           //DSound_Play(beep0_sound_id);
  856.           // process clicks
  857.           switch(id)
  858.                 {
  859.                 case GADGET_ID_SEGMENT_MODE_ID:
  860.                 {
  861.                 action = ACTION_STARTING_LINE;
  862.                 } break;
  863.                 case GADGET_ID_POLYLINE_MODE_ID:
  864.                 {
  865.                 action = ACTION_STARTING_POLYLINE; 
  866.                 } break;
  867.                 case GADGET_ID_DELETE_MODE_ID: 
  868.                 {
  869.                 action = ACTION_DELETE_LINE;
  870.                 } break;
  871.                 case GADGET_ID_CLEAR_ALL_ID:
  872.                 {
  873.                 // reset everything
  874.                 Reset_Editor();
  875.                 } break;
  876.                 case GADGET_ID_FLOOR_MODE_ID:
  877.                 {
  878.                 action = ACTION_FLOOR_MODE;
  879.                 } break;
  880.                 case GADGET_ID_WALL_TEXTURE_DEC:
  881.                 {
  882.                 if (--texture_index_wall < -1)
  883.                    texture_index_wall = -1;
  884.                 } break;
  885.                 case GADGET_ID_WALL_TEXTURE_INC:
  886.                 {
  887.                 if (++texture_index_wall >= NUM_TEXTURES)
  888.                    texture_index_wall = NUM_TEXTURES-1;
  889.             
  890.                 } break;
  891.                 case GADGET_ID_WALL_HEIGHT_DEC:
  892.                 {
  893.                 if ((wall_height-=8) < 0)
  894.                    wall_height = 0;
  895.                 } break;
  896.                 case GADGET_ID_WALL_HEIGHT_INC:
  897.                 {
  898.                 wall_height+=8;
  899.             
  900.                 } break;
  901.                 case GADGET_ID_FLOOR_TEXTURE_DEC:
  902.                 {
  903.                 if (--texture_index_floor < -1)
  904.                    texture_index_floor = -1;
  905.                 } break;
  906.                 case GADGET_ID_FLOOR_TEXTURE_INC:
  907.                 {
  908.                 if (++texture_index_floor >= NUM_TEXTURES)
  909.                    texture_index_floor = NUM_TEXTURES-1;
  910.                 } break;
  911.                 default: break;
  912.                 } // end switch
  913.           } // end if
  914.        else
  915.           {
  916.           } // end else
  917.        } // end if interface
  918.        // test for bsp area
  919.        if (mouse_state.lX > BSP_MIN_X && mouse_state.lX < BSP_MAX_X && 
  920.            mouse_state.lY > BSP_MIN_Y && mouse_state.lY < BSP_MAX_Y)
  921.          {
  922.                // process bsp editor area click
  923.                // test if this is starting point or endpoint
  924.                if (action == ACTION_STARTING_LINE)
  925.                   {
  926.                   // set starting field, note the offsets to center the
  927.                   // starting point in middle of cross hairs
  928.                   if (!snap_to_grid)
  929.                      {
  930.                      lines[total_lines].p0.x = mouse_state.lX;
  931.                      lines[total_lines].p0.y = mouse_state.lY;
  932.                      } // end if
  933.                   else
  934.                      {
  935.                      lines[total_lines].p0.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
  936.                      lines[total_lines].p0.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
  937.                      } // end if
  938.                   // remember starting line to close contour
  939.                   starting_line = total_lines;
  940.               
  941.                   // set point type to ending point
  942.                   action = ACTION_ENDING_LINE;
  943.                   // wait for mouse button release
  944.                   // Wait_For_Mouse_Up();
  945.                   } // end if start of wall
  946.                else
  947.                if (action == ACTION_ENDING_LINE)
  948.                   {
  949.                   // check for normal left mouse click
  950.                   if (mouse_state.rgbButtons[0])
  951.                      {
  952.                      // must be the end of a wall or ending point
  953.                   if (!snap_to_grid)
  954.                      {
  955.                      lines[total_lines].p1.x = mouse_state.lX;
  956.                      lines[total_lines].p1.y = mouse_state.lY;
  957.                      } // end if
  958.                   else
  959.                      {
  960.                      lines[total_lines].p1.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
  961.                      lines[total_lines].p1.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
  962.                      } // end if
  963.                      // set texture id
  964.                      lines[total_lines].texture_id = texture_index_wall;
  965.                      // set height
  966.                      lines[total_lines].height = wall_height;
  967.                      // set attributes
  968.                      lines[total_lines].attr   = poly_attr;
  969.                      // set color
  970.                      lines[total_lines].color  = poly_color;
  971.             
  972.                      // set action back to starting point
  973.                      action = ACTION_STARTING_LINE;
  974.                      // advance number of lines
  975.                      if (++total_lines >= MAX_LINES)
  976.                         total_lines = MAX_LINES - 1;
  977.                      // wait for mouse button release
  978.                      // Wait_For_Mouse_Up();
  979.                      } // end if
  980.                   else
  981.                   // check for right mouse click trying to close contour
  982.                   if (mouse_state.rgbButtons[2])
  983.                      {
  984.                      // reset, user wants to restart segment
  985.                      action = ACTION_STARTING_LINE;
  986.                      } // end if
  987.                   } // end else if
  988.                else
  989.                // test if this is starting point or endpoint
  990.                if (action == ACTION_STARTING_POLYLINE)
  991.                   {
  992.                   // set starting field, note the offsets to center the
  993.                   // starting point in middle of cross hairs
  994.                   if (!snap_to_grid)
  995.                      {
  996.                      lines[total_lines].p0.x = mouse_state.lX;
  997.                      lines[total_lines].p0.y = mouse_state.lY;
  998.                      } // end if
  999.                   else
  1000.                      {
  1001.                      lines[total_lines].p0.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
  1002.                      lines[total_lines].p0.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
  1003.                      } // end if
  1004.                   // remember starting line to close contour
  1005.                   starting_line = total_lines;
  1006.               
  1007.                   // set point type to ending point
  1008.                   action = ACTION_ADDING_POLYLINE;
  1009.                   // wait for mouse button release
  1010.                   // Wait_For_Mouse_Up();
  1011.                   } // end if start of wall
  1012.                else
  1013.                if (action == ACTION_ADDING_POLYLINE)
  1014.                   {
  1015.                   // check for normal left mouse click
  1016.                   if (mouse_state.rgbButtons[0])
  1017.                      {
  1018.                      // must be the end of a wall or ending point
  1019.                   if (!snap_to_grid)
  1020.                      {
  1021.                      lines[total_lines].p1.x = mouse_state.lX;
  1022.                      lines[total_lines].p1.y = mouse_state.lY;
  1023.                      } // end if
  1024.                   else
  1025.                      {
  1026.                      lines[total_lines].p1.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
  1027.                      lines[total_lines].p1.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
  1028.                      } // end if
  1029.                      // set texture id
  1030.                      lines[total_lines].texture_id = texture_index_wall;
  1031.                      // set height
  1032.                      lines[total_lines].height = wall_height;
  1033.                      // set attributes
  1034.                      lines[total_lines].attr   = poly_attr;
  1035.                      // set color
  1036.                      lines[total_lines].color  = poly_color;
  1037.                      // set action back to starting point
  1038.                      action = ACTION_ADDING_POLYLINE;
  1039.                      // advance number of lines
  1040.                      if (++total_lines >= MAX_LINES)
  1041.                         total_lines = MAX_LINES - 1;
  1042.                      // set start point as last endpoint
  1043.                      lines[total_lines].p0.x = lines[total_lines-1].p1.x;
  1044.                      lines[total_lines].p0.y = lines[total_lines-1].p1.y;
  1045.                      // wait for mouse button release
  1046.                      // Wait_For_Mouse_Up();
  1047.                      } // end if
  1048.                   else
  1049.                   // check for right mouse click trying to close contour
  1050.                   if (mouse_state.rgbButtons[2])
  1051.                      {
  1052.                      // end the polyline
  1053.                      action = ACTION_STARTING_POLYLINE;
  1054.                      // Wait_For_Mouse_Up();
  1055.                      } // end if
  1056.                   } // end else if
  1057.                else
  1058.                if (action==ACTION_DELETE_LINE)
  1059.                   {
  1060.                   // try and delete the line nearest selected point
  1061.                   Delete_Line(mouse_state.lX, mouse_state.lY,1);
  1062.                   // wait for mouse release
  1063.                   // Wait_For_Mouse_Up();
  1064.                   } // end if
  1065.                else
  1066.                if (action==ACTION_FLOOR_MODE)
  1067.                   {
  1068.                   // compute cell that mouse is on
  1069.                   int cell_x = (mouse_state.lX - BSP_MIN_X) / BSP_GRID_SIZE;
  1070.                   int cell_y = (mouse_state.lY - BSP_MIN_Y) / BSP_GRID_SIZE;
  1071.                   // drawing or erasing
  1072.                   if (mouse_state.rgbButtons[0])
  1073.                      {
  1074.                      // set texture id
  1075.                      floors[cell_y][cell_x] = texture_index_floor;
  1076.                      } // end if
  1077.                   else
  1078.                   if (mouse_state.rgbButtons[2])
  1079.                      {
  1080.                      // set texture id
  1081.                      floors[cell_y][cell_x] = -1;
  1082.                      } // end if
  1083.         
  1084.                   } // end if
  1085.        } // end if in bsp area
  1086.        // force button debounce
  1087.        if (mouse_state.rgbButtons[0])
  1088.            mouse_state.rgbButtons[0] = 0;
  1089.        if (mouse_state.rgbButtons[2])
  1090.            mouse_state.rgbButtons[2] = 0;
  1091.        //mouse_debounce[0] = 1;
  1092.        } // end if
  1093.     // debounce mouse
  1094.     //if (!mouse_state.rgbButtons[0] && mouse_debounce[0] == 1)
  1095.     //   mouse_debounce[0] = 0;
  1096.     // draw the floors
  1097.     if (view_floors == 1)
  1098.         Draw_Floors(lpddsback);
  1099.     // lock the back buffer
  1100.     DDraw_Lock_Back_Surface();
  1101.     // draw the lines
  1102.     if (view_walls == 1)
  1103.        Draw_Lines(back_buffer, back_lpitch);
  1104.     // draw the grid
  1105.     if (view_grid==1)
  1106.        Draw_Grid(back_buffer, back_lpitch, RGB16Bit(255,255,255), BSP_MIN_X, BSP_MIN_Y,
  1107.                                                                BSP_GRID_SIZE, BSP_GRID_SIZE,
  1108.                                                                BSP_CELLS_X,BSP_CELLS_Y);
  1109.     // unlock the back buffer
  1110.     DDraw_Unlock_Back_Surface();
  1111.     // draw all the buttons
  1112.     Draw_Gadgets(lpddsback);
  1113.     // draw the textures previews
  1114.     if (texture_index_wall >= 0)
  1115.        {
  1116.        // selected texture
  1117.        textures.x = 665;
  1118.        textures.y = 302-55;
  1119.        textures.curr_frame = texture_index_wall;
  1120.        Draw_Scaled_BOB16(&textures, 64,64,lpddsback);
  1121.        // get the line that mouse is closest to
  1122.        nearest_line = Delete_Line(mouse_state.lX, mouse_state.lY,0);
  1123.        // draw texture that is applied to line in secondary preview window
  1124.        if (nearest_line >= 0)
  1125.           {
  1126.           textures.x = 736;
  1127.           textures.y = 247;
  1128.           textures.curr_frame = lines[nearest_line].texture_id;
  1129.           Draw_Scaled_BOB16(&textures, 32,32,lpddsback);
  1130.           // now draw height of line
  1131.           sprintf(buffer,"%d",lines[nearest_line].height);
  1132.           Draw_Text_GDI(buffer, 750,188,RGB(0,255,0),lpddsback);      
  1133.           } // end if
  1134.        } // end if 
  1135.     // draw the floor texture preview
  1136.     if (texture_index_floor >= 0)
  1137.        {
  1138.        textures.x = 665;
  1139.        textures.y = 453;
  1140.        textures.curr_frame = texture_index_floor;
  1141.        Draw_Scaled_BOB16(&textures, 64,64,lpddsback);
  1142.        } // end if
  1143.     // draw the wall index
  1144.     if (texture_index_wall >= 0)
  1145.        {
  1146.        sprintf(buffer,"%d",texture_index_wall);
  1147.        Draw_Text_GDI(buffer, 738,336-56,RGB(0,255,0),lpddsback);
  1148.        } // end if
  1149.     else
  1150.        {
  1151.        Draw_Text_GDI("None", 738,336,RGB(0,255,0),lpddsback);
  1152.        } // end 
  1153.     // wall height
  1154.     sprintf(buffer,"%d",wall_height);
  1155.     Draw_Text_GDI(buffer, 688, 188,RGB(0,255,0),lpddsback);
  1156.     // texture index for floors
  1157.     if (texture_index_floor >= 0)
  1158.        {
  1159.        sprintf(buffer,"%d",texture_index_floor);
  1160.        Draw_Text_GDI(buffer, 738,488,RGB(0,255,0),lpddsback);
  1161.        } // end if
  1162.     else
  1163.        {
  1164.        Draw_Text_GDI("None", 738,488,RGB(0,255,0),lpddsback);
  1165.        } // end 
  1166.     // display stats
  1167.     sprintf(buffer,"WorldPos=(%d,%d). Num Walls=%d. Num Floor Tiles=%d. Total Polys=%d.",
  1168.             mouse_state.lX, mouse_state.lY, total_lines+1, num_floor_tiles, 2*(total_lines+1+num_floor_tiles));
  1169.     Draw_Text_GDI(buffer, 8,WINDOW_HEIGHT - 18,RGB(0,255,0),lpddsback);
  1170.     // flip the surfaces
  1171.     DDraw_Flip2();
  1172.     // sync to 30ish fps
  1173.     Sleep(10);
  1174.     #if 0
  1175.     // check of user is trying to exit
  1176.     if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
  1177.         {
  1178.         PostMessage(main_window_handle, WM_DESTROY,0,0);
  1179.         } // end if
  1180.     #endif
  1181.       } break;
  1182.       case EDITOR_STATE_VIEW: ///////////////////////////////////////////////
  1183.       {
  1184.     // start the timing clock
  1185.     Start_Clock();
  1186.     // clear the drawing surface 
  1187.     DDraw_Fill_Surface(lpddsback, 0);
  1188.     // read keyboard and other devices here
  1189.     DInput_Read_Keyboard();
  1190.     // game logic here...
  1191.     // modes and lights
  1192.     // wireframe mode
  1193.     if (keyboard_state[DIK_W]) 
  1194.        {
  1195.        // toggle wireframe mode
  1196.        if (++wireframe_mode > 1)
  1197.            wireframe_mode=0;
  1198.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1199.        } // end if
  1200.     // backface removal
  1201.     if (keyboard_state[DIK_B])
  1202.        {
  1203.        // toggle backface removal
  1204.        backface_mode = -backface_mode;
  1205.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1206.        } // end if
  1207.     // BSP backface removal
  1208.     if (keyboard_state[DIK_C])
  1209.        {
  1210.        // toggle backface removal
  1211.        bsp_backface_mode = -bsp_backface_mode;
  1212.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1213.        } // end if
  1214.     // lighting
  1215.     if (keyboard_state[DIK_L])
  1216.        {
  1217.        // toggle lighting engine completely
  1218.        lighting_mode = -lighting_mode;
  1219.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1220.        } // end if
  1221.     // toggle ambient light
  1222.     if (keyboard_state[DIK_A])
  1223.        {
  1224.        // toggle ambient light
  1225.        if (lights2[AMBIENT_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  1226.           lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  1227.        else
  1228.           lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  1229.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1230.        } // end if
  1231.     // toggle point light
  1232.     if (keyboard_state[DIK_P])
  1233.        {
  1234.        // toggle point light
  1235.        if (lights2[POINT_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  1236.           lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  1237.        else
  1238.           lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  1239.        // toggle point light
  1240.        if (lights2[POINT_LIGHT2_INDEX].state == LIGHTV2_STATE_ON)
  1241.           lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_OFF;
  1242.        else
  1243.           lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_ON;
  1244.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1245.        } // end if
  1246.     // toggle infinite light
  1247.     if (keyboard_state[DIK_I])
  1248.        {
  1249.        // toggle ambient light
  1250.        if (lights2[INFINITE_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  1251.           lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  1252.        else
  1253.           lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  1254.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1255.        } // end if
  1256.     // help menu
  1257.     if (keyboard_state[DIK_H])
  1258.        {
  1259.        // toggle help menu 
  1260.        help_mode = -help_mode;
  1261.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1262.        } // end if
  1263.     // z-sorting
  1264.     if (keyboard_state[DIK_S])
  1265.        {
  1266.        // toggle z sorting
  1267.        zsort_mode = -zsort_mode;
  1268.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1269.        } // end if
  1270.     // z buffer
  1271.     if (keyboard_state[DIK_Z])
  1272.        {
  1273.        // toggle z buffer
  1274.        z_buffer_mode = -z_buffer_mode;
  1275.        Wait_Clock(100); // wait, so keyboard doesn't bounce
  1276.        } // end if
  1277.     // forward/backward
  1278.     if (keyboard_state[DIK_UP])
  1279.        {
  1280.        // move forward
  1281.        if ( (cam_speed+=2) > MAX_SPEED) cam_speed = MAX_SPEED;
  1282.        } // end if
  1283.     else
  1284.     if (keyboard_state[DIK_DOWN])
  1285.        {
  1286.        // move backward
  1287.        if ((cam_speed-=2) < -MAX_SPEED) cam_speed = -MAX_SPEED;
  1288.        } // end if
  1289.     // rotate around y axis or yaw
  1290.     if (keyboard_state[DIK_RIGHT])
  1291.        {
  1292.        cam.dir.y+=10;
  1293.        // scroll the background
  1294.        Scroll_Bitmap(&background_bmp, -10);
  1295.        } // end if
  1296.     if (keyboard_state[DIK_LEFT])
  1297.        {
  1298.        cam.dir.y-=10;
  1299.        // scroll the background
  1300.        Scroll_Bitmap(&background_bmp, 10);
  1301.        } // end if
  1302.       // ambient scrolling 
  1303.       static int scroll_counter = 0;
  1304.       if (++scroll_counter > 5)
  1305.          {
  1306.          // scroll the background
  1307.          Scroll_Bitmap(&background_bmp, 1);
  1308.          // reset scroll counter
  1309.          scroll_counter = 0;
  1310.          } // end if
  1311.     // move point light source in ellipse around game world
  1312.     lights2[POINT_LIGHT_INDEX].pos.x = 1000*Fast_Cos(plight_ang);
  1313.     lights2[POINT_LIGHT_INDEX].pos.y = 100;
  1314.     lights2[POINT_LIGHT_INDEX].pos.z = 1000*Fast_Sin(plight_ang);
  1315.     // move point light source in ellipse around game world
  1316.     lights2[POINT_LIGHT2_INDEX].pos.x = 500*Fast_Cos(-2*plight_ang);
  1317.     lights2[POINT_LIGHT2_INDEX].pos.y = 200;
  1318.     lights2[POINT_LIGHT2_INDEX].pos.z = 1000*Fast_Sin(-2*plight_ang);
  1319.     if ((plight_ang+=3) > 360)
  1320.         plight_ang = 0;
  1321.     // decelerate camera
  1322.     if (cam_speed > (CAM_DECEL) ) cam_speed-=CAM_DECEL;
  1323.     else
  1324.     if (cam_speed < (-CAM_DECEL) ) cam_speed+=CAM_DECEL;
  1325.     else
  1326.        cam_speed = 0;
  1327.     // move camera
  1328.     cam.pos.x += cam_speed*Fast_Sin(cam.dir.y);
  1329.     cam.pos.z += cam_speed*Fast_Cos(cam.dir.y);
  1330.     
  1331.     // generate camera matrix
  1332.     Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX);
  1333.     // build the camera vector rotation matrix ////////////////////////////////
  1334.     Build_XYZ_Rotation_MATRIX4X4(cam.dir.x, 
  1335.                                  cam.dir.y, 
  1336.                                  cam.dir.z,
  1337.                                  &mrot);
  1338.     // transform the (0,0,1) vector and store it in the cam.n vector, this is now the 
  1339.     // view direction vector
  1340.     Mat_Mul_VECTOR4D_4X4(&vz, &mrot, &cam.n);
  1341.     // normalize the viewing vector
  1342.     VECTOR4D_Normalize(&cam.n); ///////////////////////////////////////////////
  1343.     //////////////////////////////////////////////////////////////////////////////
  1344.     // begin pass one -- with all static objects with writethru on the Z buffer...
  1345.     //////////////////////////////////////////////////////////////////////////////
  1346.     // reset the render list
  1347.     Reset_RENDERLIST4DV2(&rend_list);
  1348.     // render the floors into polylist first
  1349.     // reset the object (this only matters for backface and object removal)
  1350.     Reset_OBJECT4DV2(&obj_scene);
  1351.     // set position of floor
  1352.     obj_scene.world_pos.x = 0;
  1353.     obj_scene.world_pos.y = 0;
  1354.     obj_scene.world_pos.z = 0;
  1355.     // attempt to cull object   
  1356.     if (!Cull_OBJECT4DV2(&obj_scene, &cam, CULL_OBJECT_XYZ_PLANES))
  1357.        {
  1358.        // create an identity to work with
  1359.        MAT_IDENTITY_4X4(&mrot);
  1360.  
  1361.        // rotate the local coords of the object
  1362.        Transform_OBJECT4DV2(&obj_scene, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
  1363.        // perform world transform
  1364.        Model_To_World_OBJECT4DV2(&obj_scene, TRANSFORM_TRANS_ONLY);
  1365.        // insert the object into render list
  1366.        Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_scene,0);
  1367.        } // end if
  1368.     // reset the object (this only matters for backface and object removal)
  1369.     Reset_OBJECT4DV2(&obj_scene);
  1370.     // set position of ceiling
  1371.     obj_scene.world_pos.x = 0;
  1372.     obj_scene.world_pos.y = ceiling_height;
  1373.     obj_scene.world_pos.z = 0;
  1374.     // attempt to cull object   
  1375.     if (!Cull_OBJECT4DV2(&obj_scene, &cam, CULL_OBJECT_XYZ_PLANES))
  1376.        {
  1377.        // create an identity to work with
  1378.        MAT_IDENTITY_4X4(&mrot);
  1379.  
  1380.        // rotate the local coords of the object
  1381.        Transform_OBJECT4DV2(&obj_scene, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
  1382.        // perform world transform
  1383.        Model_To_World_OBJECT4DV2(&obj_scene, TRANSFORM_TRANS_ONLY);
  1384.        // insert the object into render list
  1385.        Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_scene,0);
  1386.        } // end if
  1387.     int polycount = rend_list.num_polys;
  1388.     if (bsp_backface_mode == 1)
  1389.        {
  1390.        // insert the bsp into rendering list
  1391.        Bsp_Insertion_Traversal_FrustrumCull_RENDERLIST4DV2(&rend_list, bsp_root, &cam, 1);
  1392.        }
  1393.    else
  1394.        {
  1395.        // insert the bsp into rendering list without culling
  1396.        Bsp_Insertion_Traversal_RENDERLIST4DV2(&rend_list, bsp_root, &cam, 1);
  1397.        } 
  1398.     // compute total number of polys inserted into list
  1399.     polycount = rend_list.num_polys - polycount;
  1400.  
  1401.     // reset number of polys rendered
  1402.     debug_polys_rendered_per_frame = 0;
  1403.     debug_polys_lit_per_frame = 0;
  1404.     // remove backfaces
  1405.     if (backface_mode==1)
  1406.        Remove_Backfaces_RENDERLIST4DV2(&rend_list, &cam);
  1407.     // apply world to camera transform
  1408.     World_To_Camera_RENDERLIST4DV2(&rend_list, &cam);
  1409.     // clip the polygons themselves now
  1410.     Clip_Polys_RENDERLIST4DV2(&rend_list, &cam, ((x_clip_mode == 1) ? CLIP_POLY_X_PLANE : 0) | 
  1411.                                                 ((y_clip_mode == 1) ? CLIP_POLY_Y_PLANE : 0) | 
  1412.                                                 ((z_clip_mode == 1) ? CLIP_POLY_Z_PLANE : 0) );
  1413.     // light scene all at once 
  1414.     if (lighting_mode==1)
  1415.        {
  1416.        Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS);
  1417.        Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4);
  1418.        } // end if
  1419.     // sort the polygon list (hurry up!)
  1420.     if (zsort_mode == 1)
  1421.        Sort_RENDERLIST4DV2(&rend_list,  SORT_POLYLIST_AVGZ);
  1422.     // apply camera to perspective transformation
  1423.     Camera_To_Perspective_RENDERLIST4DV2(&rend_list, &cam);
  1424.     // apply screen transform
  1425.     Perspective_To_Screen_RENDERLIST4DV2(&rend_list, &cam);
  1426.     // lock the back buffer
  1427.     DDraw_Lock_Back_Surface();
  1428.     // draw background
  1429.     Draw_Bitmap16(&background_bmp, back_buffer, back_lpitch,0);
  1430.     // reset number of polys rendered
  1431.     debug_polys_rendered_per_frame = 0;
  1432.     // render the renderinglist
  1433.     if (wireframe_mode  == 0)
  1434.        Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
  1435.     else
  1436.     if (wireframe_mode  == 1)
  1437.        {
  1438.        // is z buffering enabled
  1439.        if (z_buffer_mode == 1)
  1440.        {
  1441.        // set up rendering context for 1/z buffer
  1442.        rc.attr         = RENDER_ATTR_WRITETHRUZBUFFER  
  1443.                          //| RENDER_ATTR_ALPHA  
  1444.                          //| RENDER_ATTR_MIPMAP  
  1445.                          //| RENDER_ATTR_BILERP
  1446.                          | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
  1447.        } // end if
  1448.        else
  1449.        {    
  1450.        // set up rendering context for no zbuffer
  1451.        rc.attr         = RENDER_ATTR_NOBUFFER  
  1452.                          //| RENDER_ATTR_ALPHA  
  1453.                          //| RENDER_ATTR_MIPMAP  
  1454.                          // | RENDER_ATTR_BILERP
  1455.                          | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
  1456.         } // end else
  1457.       // if z abuffer or 1/z buffer is being used then clear z buffer    
  1458.       if (rc.attr & RENDER_ATTR_ZBUFFER || rc.attr & RENDER_ATTR_WRITETHRUZBUFFER)
  1459.          {
  1460.          // clear the z buffer
  1461.          Clear_Zbuffer(&zbuffer, (32000 << FIXP16_SHIFT));
  1462.          } // end if
  1463.       else
  1464.       if (rc.attr & RENDER_ATTR_INVZBUFFER)
  1465.          {
  1466.          // clear the 1/z buffer
  1467.          Clear_Zbuffer(&zbuffer, (0 << FIXP16_SHIFT));
  1468.          } // end if
  1469.    
  1470.        rc.video_buffer   = back_buffer;
  1471.        rc.lpitch         = back_lpitch;
  1472.        rc.mip_dist       = 0;
  1473.        rc.zbuffer        = (UCHAR *)zbuffer.zbuffer;
  1474.        rc.zpitch         = WINDOW_WIDTH*4;
  1475.        rc.rend_list      = &rend_list;
  1476.        rc.texture_dist   = 0;
  1477.        rc.alpha_override = -1;
  1478.        // render scene
  1479.        Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_2(&rc);
  1480.        } // end if
  1481.     //////////////////////////////////////////////////////////////////////
  1482.     // begin pass two -- with all moveable objects with normal z buffer...
  1483.     //////////////////////////////////////////////////////////////////////
  1484.     // reset the render list
  1485.     Reset_RENDERLIST4DV2(&rend_list);
  1486.     // render the object
  1487.     // reset the object (this only matters for backface and object removal)
  1488.     Reset_OBJECT4DV2(&obj_moveable);
  1489.     static float rec_count = 0;
  1490.     // set position of object
  1491.     obj_moveable.world_pos.x = 500*Fast_Cos(rec_count);
  1492.     obj_moveable.world_pos.y = 40 + 20*Fast_Sin(rec_count*2);
  1493.     obj_moveable.world_pos.z = 500*Fast_Sin(rec_count);
  1494.     if ((rec_count+=.5) > 360)
  1495.        rec_count =- 360;
  1496.     // attempt to cull object   
  1497.     if (!Cull_OBJECT4DV2(&obj_moveable, &cam, CULL_OBJECT_XYZ_PLANES))
  1498.        {
  1499.        // create an identity to work with
  1500.        MAT_IDENTITY_4X4(&mrot);
  1501. /*
  1502.        // now align recognizer with circular path by creating a coordinate
  1503.        // system such that Z is aligned with the direction of travel
  1504.        // or we can use the rotation function to do it for us :)
  1505.        mrot.M[0][0] = Fast_Cos(rec_count);
  1506.        mrot.M[0][1] = 0;
  1507.        mrot.M[0][2] = Fast_Sin(rec_count);
  1508.  
  1509.        mrot.M[1][0] = 0;
  1510.        mrot.M[1][1] = 1;
  1511.        mrot.M[1][2] = 0;
  1512.        mrot.M[2][0] = -Fast_Sin(rec_count);
  1513.        mrot.M[2][1] = 0;
  1514.        mrot.M[2][2] = Fast_Cos(rec_count);
  1515. */
  1516.        // generate rotation matrix around y axis
  1517.        Build_XYZ_Rotation_MATRIX4X4(0, -rec_count, 0, &mrot);       
  1518.        // rotate the local coords of the object
  1519.        Transform_OBJECT4DV2(&obj_moveable, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
  1520.        // perform world transform
  1521.        Model_To_World_OBJECT4DV2(&obj_moveable, TRANSFORM_TRANS_ONLY);
  1522.        // insert the object into render list
  1523.        Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_moveable,0);
  1524.        } // end if
  1525.     // remove backfaces
  1526.     if (backface_mode==1)
  1527.        Remove_Backfaces_RENDERLIST4DV2(&rend_list, &cam);
  1528.     // apply world to camera transform
  1529.     World_To_Camera_RENDERLIST4DV2(&rend_list, &cam);
  1530.     // clip the polygons themselves now
  1531.     Clip_Polys_RENDERLIST4DV2(&rend_list, &cam, ((x_clip_mode == 1) ? CLIP_POLY_X_PLANE : 0) | 
  1532.                                                 ((y_clip_mode == 1) ? CLIP_POLY_Y_PLANE : 0) | 
  1533.                                                 ((z_clip_mode == 1) ? CLIP_POLY_Z_PLANE : 0) );
  1534.     // light scene all at once 
  1535.     if (lighting_mode==1)
  1536.        {
  1537.        Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS);
  1538.        Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4);
  1539.        } // end if
  1540.     // sort the polygon list (hurry up!)
  1541.     if (zsort_mode == 1)
  1542.        Sort_RENDERLIST4DV2(&rend_list,  SORT_POLYLIST_AVGZ);
  1543.     // apply camera to perspective transformation
  1544.     Camera_To_Perspective_RENDERLIST4DV2(&rend_list, &cam);
  1545.     // apply screen transform
  1546.     Perspective_To_Screen_RENDERLIST4DV2(&rend_list, &cam);
  1547.     // lock the back buffer
  1548.     DDraw_Lock_Back_Surface();
  1549.     // render the renderinglist
  1550.     if (wireframe_mode  == 0)
  1551.        Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
  1552.     else
  1553.     if (wireframe_mode  == 1)
  1554.        {
  1555.        // is z buffering enabled
  1556.        if (z_buffer_mode == 1)
  1557.        {
  1558.        // set up rendering context for 1/z buffer
  1559.        rc.attr         = RENDER_ATTR_ZBUFFER  
  1560.                          //| RENDER_ATTR_ALPHA  
  1561.                          //| RENDER_ATTR_MIPMAP  
  1562.                          //| RENDER_ATTR_BILERP
  1563.                          | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
  1564.        } // end if
  1565.        else
  1566.        {    
  1567.        // set up rendering context for no zbuffer
  1568.        rc.attr         = RENDER_ATTR_NOBUFFER  
  1569.                          //| RENDER_ATTR_ALPHA  
  1570.                          //| RENDER_ATTR_MIPMAP  
  1571.                          // | RENDER_ATTR_BILERP
  1572.                          | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
  1573.         } // end else
  1574.       // no clearing the Z buffer!!!!
  1575. /*
  1576.       // if z abuffer or 1/z buffer is being used then clear z buffer    
  1577.       if (rc.attr & RENDER_ATTR_ZBUFFER || rc.attr & RENDER_ATTR_WRITETHRUZBUFFER)
  1578.          {
  1579.          // clear the z buffer
  1580.          Clear_Zbuffer(&zbuffer, (32000 << FIXP16_SHIFT));
  1581.          } // end if
  1582.       else
  1583.       if (rc.attr & RENDER_ATTR_INVZBUFFER)
  1584.          {
  1585.          // clear the 1/z buffer
  1586.          Clear_Zbuffer(&zbuffer, (0 << FIXP16_SHIFT));
  1587.          } // end if
  1588. */
  1589.    
  1590.        rc.video_buffer   = back_buffer;
  1591.        rc.lpitch         = back_lpitch;
  1592.        rc.mip_dist       = 0;
  1593.        rc.zbuffer        = (UCHAR *)zbuffer.zbuffer;
  1594.        rc.zpitch         = WINDOW_WIDTH*4;
  1595.        rc.rend_list      = &rend_list;
  1596.        rc.texture_dist   = 0;
  1597.        rc.alpha_override = -1;
  1598.        // render scene 
  1599.        Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_2(&rc);
  1600.        } // end if
  1601.     // unlock the back buffer
  1602.     DDraw_Unlock_Back_Surface();
  1603.     sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, BckFceRM [%s], BSP Frustrum Cull [%s], Zsort [%s], Zbuffer [%s]", 
  1604.                                                                                      ((lighting_mode == 1) ? "ON" : "OFF"),
  1605.                                                                                      lights[AMBIENT_LIGHT_INDEX].state,
  1606.                                                                                      lights[INFINITE_LIGHT_INDEX].state, 
  1607.                                                                                      ((backface_mode == 1) ? "ON" : "OFF"),
  1608.                                                                                      ((bsp_backface_mode == 1) ? "ON" : "OFF"),
  1609.                                                                                      ((zsort_mode == 1) ? "ON" : "OFF"),
  1610.                                                                                      ((z_buffer_mode == 1) ? "ON" : "OFF"));
  1611.     Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16, RGB(0,255,0), lpddsback);
  1612.     // draw instructions
  1613.     Draw_Text_GDI("Press ESC to return to editor mode. Press <H> for Help.", 0, 0, RGB(0,255,0), lpddsback);
  1614.     // should we display help
  1615.     int text_y = 16;
  1616.     if (help_mode==1)
  1617.         {
  1618.         // draw help menu
  1619.         Draw_Text_GDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1620.         Draw_Text_GDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1621.         Draw_Text_GDI("<P>..............Toggle point lights.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1622.         Draw_Text_GDI("<B>..............Toggle backface removal.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1623.         Draw_Text_GDI("<S>..............Toggle Z sorting.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1624.         Draw_Text_GDI("<C>..............Toggle BSP Backface Culling.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1625.         Draw_Text_GDI("<Z>..............Toggle Z buffering.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1626.         Draw_Text_GDI("<Z>..............Toggle Wireframe mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1627.         Draw_Text_GDI("<H>..............Toggle Help.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1628.         Draw_Text_GDI("<ESC>............Exit demo.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1629.         } // end help
  1630.     sprintf(work_string,"Polys Rendered: %d, Polys lit: %d, Polys Inserted from BSP: %d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame, polycount);
  1631.     Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16, RGB(0,255,0), lpddsback);
  1632.     sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f]",  cam.pos.x, cam.pos.y, cam.pos.z);
  1633.     Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), lpddsback);
  1634.     // flip the surfaces
  1635.     DDraw_Flip2();
  1636.     // sync to 30ish fps
  1637.     Wait_Clock(30);
  1638.     // check of user is trying to exit
  1639.     if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
  1640.        {
  1641.        // switch game state back to editor more
  1642.        editor_state = EDITOR_STATE_EDIT;
  1643.        } // end if
  1644.       } break;     
  1645.       default: break;
  1646.       } // end switch
  1647. // return success
  1648. return(1);
  1649.  
  1650. } // end Game_Main
  1651. /////////////////////////////////////////////////////////////////////////////
  1652. void Reset_Editor(void)
  1653. {
  1654. // this function resets all the runtime variables of the editor and zeros things
  1655. // out
  1656. // reset all variables
  1657. total_lines         = 0;     // number of lines that have been defined
  1658. starting_line       = 0;     // used to close contours
  1659. snap_to_grid        = 1;     // flag to snap to grid        
  1660. view_grid           = 1;     // flag to show grid
  1661. view_walls          = 1;
  1662. view_floors         = 1;
  1663. nearest_line        = -1;
  1664. texture_index_wall  = 11;
  1665. texture_index_floor = 13;
  1666. wall_height         = 64;
  1667. ceiling_height      = 0;   
  1668. num_floor_tiles     = 0; 
  1669. poly_attr           = (POLY4DV2_ATTR_DISABLE_MATERIAL | POLY4DV2_ATTR_2SIDED | POLY4DV2_ATTR_RGB16 | POLY4DV2_ATTR_SHADE_MODE_FLAT );
  1670. poly_color          = RGB16Bit(255,255,255);
  1671. // initialize the floors
  1672. for (int cell_y = 0; cell_y < BSP_CELLS_Y-1; cell_y++)
  1673.     for (int cell_x = 0; cell_x < BSP_CELLS_X-1; cell_x++)
  1674.          floors[cell_y][cell_x] = -1;
  1675. // initialize the wall lines
  1676. memset(lines, 0, sizeof BSP2D_LINE*MAX_LINES);
  1677. } // end Reset_Editor
  1678. //////////////////////////////////////////////////////////////////////////////
  1679. void Draw_Floors(LPDIRECTDRAWSURFACE7 lpdds)
  1680. {
  1681. // this function draws all the floors by rendering the textures that are 
  1682. // mapped onto the floor scaled down (it very cute)
  1683. // reset number of floor tiles
  1684. num_floor_tiles = 0;
  1685. for (int cell_y = 0; cell_y < BSP_CELLS_Y-1; cell_y++)
  1686.     {
  1687.     for (int cell_x = 0; cell_x < BSP_CELLS_X-1; cell_x++)
  1688.         {
  1689.         // extract texture id
  1690.         int texture_id = floors[cell_y][cell_x];
  1691.         // is there a texture here?
  1692.         if (texture_id > -1)
  1693.            {
  1694.            // set position of texture on level editor space
  1695.            textures.x = BSP_MIN_X + (cell_x * BSP_GRID_SIZE);
  1696.            textures.y = BSP_MIN_Y + (cell_y * BSP_GRID_SIZE);
  1697.            // set texture id
  1698.            textures.curr_frame = texture_id;
  1699.            Draw_Scaled_BOB16(&textures, BSP_GRID_SIZE,BSP_GRID_SIZE,lpdds);
  1700.       
  1701.            // increment number of floor tiles
  1702.            num_floor_tiles++;
  1703.            } // end if 
  1704.         } // end for cell_y
  1705.    } // end for cell_y
  1706. } // end Draw_Floors
  1707. //////////////////////////////////////////////////////////////////////////////
  1708. void Draw_Lines(UCHAR *video_buffer, 
  1709.                 int mempitch)
  1710. {
  1711. // this function draws all the lines for the BSP
  1712. for (int index = 0; index < total_lines; index++)
  1713.     {
  1714.     // draw each line, textured lines red, blank lines blue
  1715.     if (lines[index].texture_id >= 0)
  1716.        {
  1717.        Draw_Line16( lines[index].p0.x, lines[index].p0.y,
  1718.                     lines[index].p1.x, lines[index].p1.y,
  1719.                     RGB16Bit(255,0,0), video_buffer, mempitch);
  1720.        } // end if
  1721.     else
  1722.        {
  1723.        Draw_Line16( lines[index].p0.x, lines[index].p0.y,
  1724.                     lines[index].p1.x, lines[index].p1.y,
  1725.                     RGB16Bit(128,128,128), video_buffer, mempitch);
  1726.        } // end if
  1727.  
  1728.     // mark endpoints with X
  1729.     Draw_Line16( lines[index].p0.x-4, lines[index].p0.y-4,
  1730.                  lines[index].p0.x+4, lines[index].p0.y+4,
  1731.                  RGB16Bit(0,255,0), video_buffer, mempitch);
  1732.       
  1733.     Draw_Line16( lines[index].p0.x+4, lines[index].p0.y-4,
  1734.                  lines[index].p0.x-4, lines[index].p0.y+4,
  1735.                  RGB16Bit(0,255,0), video_buffer, mempitch);
  1736.     Draw_Line16( lines[index].p1.x-4, lines[index].p1.y-4,
  1737.                  lines[index].p1.x+4, lines[index].p1.y+4,
  1738.                  RGB16Bit(0,255,0), video_buffer, mempitch);
  1739.       
  1740.     Draw_Line16( lines[index].p1.x+4, lines[index].p1.y-4,
  1741.                  lines[index].p1.x-4, lines[index].p1.y+4,
  1742.                  RGB16Bit(0,255,0), video_buffer, mempitch);
  1743.     } // end for index
  1744. // now draw special lines
  1745. if (action == ACTION_ENDING_LINE &&
  1746.    mouse_state.lX > BSP_MIN_X && mouse_state.lX < BSP_MAX_X && 
  1747.    mouse_state.lY > BSP_MIN_Y && mouse_state.lY < BSP_MAX_Y)
  1748.    {
  1749.    Draw_Line16( lines[total_lines].p0.x, lines[total_lines].p0.y,
  1750.                 mouse_state.lX, mouse_state.lY,
  1751.                 RGB16Bit(255,255,255), video_buffer, mempitch);
  1752.  
  1753.    } // end if
  1754. // hightlight path to end point
  1755. if (action == ACTION_ADDING_POLYLINE &&
  1756.    mouse_state.lX > BSP_MIN_X && mouse_state.lX < BSP_MAX_X && 
  1757.    mouse_state.lY > BSP_MIN_Y && mouse_state.lY < BSP_MAX_Y)
  1758.    {
  1759.    Draw_Line16( lines[total_lines].p0.x, lines[total_lines].p0.y,
  1760.                 mouse_state.lX, mouse_state.lY,
  1761.                 RGB16Bit(255,255,255), video_buffer, mempitch);
  1762.  
  1763.    } // end if
  1764. static int red_counter = 0; // used to flicker delete candidate 
  1765. if ((red_counter+=32) > 255) red_counter = 0;
  1766. // highlight line mouse is hovering over
  1767. if (mouse_state.lX > BSP_MIN_X && mouse_state.lX < BSP_MAX_X && 
  1768.     mouse_state.lY > BSP_MIN_Y && mouse_state.lY < BSP_MAX_Y)
  1769.    {
  1770.    if (nearest_line >= 0)
  1771.       {
  1772.       if (action == ACTION_DELETE_LINE)
  1773.          {
  1774.           Draw_Line16( lines[nearest_line].p0.x, lines[nearest_line].p0.y,
  1775.                    lines[nearest_line].p1.x, lines[nearest_line].p1.y,
  1776.                       RGB16Bit(red_counter,red_counter,red_counter), video_buffer, mempitch);
  1777.          } // end if
  1778.       else
  1779.          {
  1780.           Draw_Line16( lines[nearest_line].p0.x, lines[nearest_line].p0.y,
  1781.                    lines[nearest_line].p1.x, lines[nearest_line].p1.y,
  1782.                       RGB16Bit(255,255,255), video_buffer, mempitch);
  1783.          } // end if
  1784.       } // end if
  1785.  
  1786.    } // end if         
  1787. } // end Draw_Lines
  1788. //////////////////////////////////////////////////////////////////////////////
  1789. int Delete_Line(int x, int y, int delete_line)
  1790. {
  1791. // this function hunts thru the lines and deletes the one closest to
  1792. // the sent position (which is the center of the cross hairs
  1793. int curr_line,          // current line being processed
  1794.     best_line=-1;       // the best match so far in process 
  1795. float sx,sy,            // starting coordinates of test line
  1796.       ex,ey,            // ending coordinates of test line
  1797.       length_line,      // total length of line being tested
  1798.       length_1,         // length of lines from endpoints of test line to target area
  1799.       length_2,
  1800.       min_x,max_x,      // bounding box of test line
  1801.       min_y,max_y;
  1802.       
  1803. float best_error=10000, // start error off really large
  1804.       test_error;       // current error being processed
  1805. // process each line and find best fit
  1806. for (curr_line=0; curr_line < total_lines; curr_line++)
  1807.     {
  1808.     // extract line parameters
  1809.     sx = lines[curr_line].p0.x;
  1810.     sy = lines[curr_line].p0.y;
  1811.     ex = lines[curr_line].p1.x;
  1812.     ey = lines[curr_line].p1.y;
  1813.     // first compute length of line
  1814.     length_line = sqrt( (ex-sx) * (ex-sx) + (ey-sy) * (ey-sy) );
  1815.     // compute length of first endpoint to selected position
  1816.     length_1    = sqrt( (x-sx) * (x-sx) + (y-sy) * (y-sy) );
  1817.     // compute length of second endpoint to selected position
  1818.     length_2    = sqrt( (ex-x) * (ex-x) + (ey-y) * (ey-y) );
  1819.     // compute the bounding box of line
  1820.     min_x = MIN(sx,ex)-2;
  1821.     min_y = MIN(sy,ey)-2;
  1822.     max_x = MAX(sx,ex)+2;
  1823.     max_y = MAX(sy,ey)+2;
  1824.     // if the selection position is within bounding box then compute distance
  1825.     // errors and save this line as a possibility
  1826.     if (x >= min_x && x <= max_x && y >= min_y && y <= max_y)
  1827.        {
  1828.        // compute percent error of total length to length of lines
  1829.        // from endpoint to selected position
  1830.        test_error = (float)(100 * fabs( (length_1 + length_2) - length_line) ) / (float)length_line;
  1831.        // test if this line is a better selection than the last
  1832.        if (test_error < best_error)
  1833.           {
  1834.           // make this line the "best selection" so far
  1835.           best_error = test_error;
  1836.           best_line  = curr_line;
  1837.           } // end if
  1838.        } // end if in bounding box
  1839.     } // end for curr_line
  1840. // did we get a line to delete?
  1841. if (best_line != -1)
  1842.    {
  1843.    // delete the line from the line array by copying another line into
  1844.    // the position
  1845.    // test for deletion enable or just viewing
  1846.    if (delete_line)
  1847.       {
  1848.       // test for special cases
  1849.       if (total_lines == 1) // a single line
  1850.          total_lines = 0;
  1851.       else
  1852.       if (best_line == (total_lines-1))  // the line to delete is the last in array
  1853.          total_lines--;
  1854.       else
  1855.          {
  1856.          // the line to delete must be in the 0th to total_lines-1 position
  1857.          // so copy the last line into the deleted one and decrement the
  1858.          // number of lines in system
  1859.          lines[best_line] = lines[--total_lines];
  1860.          } // end else
  1861.       } // end if
  1862.    // return the line number that was deleted
  1863.    return(best_line);
  1864.    } // end if
  1865. else
  1866.     return(-1);
  1867. } // end Delete_Line
  1868. ///////////////////////////////////////////////////////////////////////////////
  1869. void Load_Gadgets(void)
  1870. {
  1871. // this function simply loads all the gadget images into the global image 
  1872. // array, additionally it sets up the pointers the images in the buttons
  1873. // array
  1874. // create the bob image to hold all the button images
  1875. Create_BOB(&button_img, 0,0,128,48,10, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  1876. // set visibility
  1877. button_img.attr |= BOB_ATTR_VISIBLE;
  1878. // load the bitmap to extract imagery
  1879. Load_Bitmap_File(&bitmap16bit, "bspguicon01.bmp");
  1880. // interate and extract both the off and on bitmaps for each animated button
  1881. for (int index = 0; index < 10; index++)
  1882.     {
  1883.     // load the frame left to right, row by row
  1884.     Load_Frame_BOB16(&button_img, &bitmap16bit,index,index%2,index/2,BITMAP_EXTRACT_MODE_CELL);
  1885.     } // end for index
  1886.     // fix pointers in gadget array
  1887.     buttons[GADGET_ID_SEGMENT_MODE_ID].bitmap  = &button_img;
  1888.     buttons[GADGET_ID_POLYLINE_MODE_ID].bitmap = &button_img;
  1889.     buttons[GADGET_ID_DELETE_MODE_ID].bitmap   = &button_img;
  1890.     buttons[GADGET_ID_CLEAR_ALL_ID].bitmap     = &button_img;
  1891.     buttons[GADGET_ID_FLOOR_MODE_ID].bitmap    = &button_img;
  1892. // unload the bitmap
  1893. Unload_Bitmap_File(&bitmap16bit);
  1894. } // end Load_Gadgets
  1895. //////////////////////////////////////////////////////////////////////////////
  1896. void Draw_Gadgets(LPDIRECTDRAWSURFACE7 lpdds)
  1897. {
  1898. // draws all the gadgets, note that buffer must be unlocked
  1899. // interate and draw all the buttons 
  1900. for (int index = 0; index < NUM_GADGETS; index++)
  1901.     {
  1902.     // get the current button
  1903.     GADGET_PTR curr_button = &buttons[index];
  1904.     // what type of button
  1905.     switch(curr_button->type)
  1906.           {
  1907.           case GADGET_TYPE_TOGGLE:    // toggles from off/on, on/off
  1908.                {
  1909.                // set the frame of the button
  1910.                button_img.curr_frame = curr_button->id + curr_button->state;
  1911.      
  1912.                // set position of the button
  1913.                button_img.x = curr_button->x0;
  1914.                button_img.y = curr_button->y0;
  1915.   
  1916.                // draw the button               
  1917.                Draw_BOB16(&button_img, lpdds);
  1918.                } break;
  1919.           case GADGET_TYPE_MOMENTARY: // lights up while you press it
  1920.                {
  1921.                // set the frame of the button
  1922.                button_img.curr_frame = curr_button->id + curr_button->state;
  1923.      
  1924.                // set position of the button
  1925.                button_img.x = curr_button->x0;
  1926.                button_img.y = curr_button->y0;
  1927.   
  1928.                // draw the button               
  1929.                Draw_BOB16(&button_img, lpdds);
  1930.                // increment counter
  1931.                if (curr_button->state == GADGET_ON)
  1932.                   {
  1933.                   if (++curr_button->count > 2)
  1934.                      {
  1935.                      curr_button->state = GADGET_OFF;
  1936.                      curr_button->count = 0;
  1937.                      } // end if
  1938.                   } // end if
  1939.                   
  1940.                } break;
  1941.           case GADGET_TYPE_STATIC:    // doesn't do anything visual    
  1942.                {
  1943.                // do nothing
  1944.                } break;
  1945.           default:break;
  1946.           
  1947.           } // end switch
  1948.     } // end for index
  1949. } // end Draw_Gadgets
  1950. //////////////////////////////////////////////////////////////////////////////
  1951. int Process_Gadgets(int mx, int my, UCHAR mbuttons[])
  1952. {
  1953. // this function processes the gadgets messages and changes their states
  1954. // based on clicks from the mouse
  1955. // iterate thru all the gadgets and determine if there has been a click in
  1956. // any of the clickable areas 
  1957. for (int index = 0; index < NUM_GADGETS; index++)
  1958.     {
  1959.     // get the current button
  1960.     GADGET_PTR curr_button = &buttons[index];
  1961.     // test for a button press
  1962.     if (mbuttons[0] | mbuttons[1] | mbuttons[2])
  1963.     {
  1964.     // determine if there has been a collision
  1965.     if ( (mx > curr_button->x0) && (mx < curr_button->x0+curr_button->width) && 
  1966.          (my > curr_button->y0) && (my < curr_button->y0+curr_button->height) )
  1967.     {
  1968.     // what type of button
  1969.     switch(curr_button->type)
  1970.           {
  1971.           case GADGET_TYPE_TOGGLE:    // toggles from off/on, on/off
  1972.                {
  1973.                // set the frame of the button
  1974.                if (curr_button->state == GADGET_OFF)
  1975.                   curr_button->state = GADGET_ON;
  1976.                // reset all other mutual exclusive toggles
  1977.                for (int index2 = 0; index2 < NUM_GADGETS; index2++)
  1978.                    if (index2!=index && buttons[index2].type == GADGET_TYPE_TOGGLE)
  1979.                        buttons[index2].state = GADGET_OFF;
  1980.                // return the id of the button pressed
  1981.                return(curr_button->id);
  1982.                } break;
  1983.           case GADGET_TYPE_MOMENTARY: // lights up while you press it
  1984.                {
  1985.                // set the frame of the button to onn
  1986.                curr_button->state = GADGET_ON;
  1987.                // return the id of the button pressed
  1988.                return(curr_button->id);
  1989.                } break;
  1990.           case GADGET_TYPE_STATIC:    // doesn't do anything visual    
  1991.                {
  1992.                // do nothing
  1993.                // return the id of the button pressed
  1994.                return(curr_button->id);
  1995.                } break;
  1996.           default:break;
  1997.           
  1998.           } // end switch
  1999.     } // end if collision detected
  2000.     } // end if button pressed
  2001.     else
  2002.     {
  2003.     // reset buttons, etc. do housekeeping
  2004.     } // end else   
  2005.     } // end for index
  2006. // nothing was pressed
  2007. return(-1);
  2008. } // end Process_Gadgets
  2009. //////////////////////////////////////////////////////////////////////////////
  2010. void Draw_Grid(UCHAR *video_buffer, 
  2011.                int mempitch,
  2012.                int rgbcolor, 
  2013.                int x0, int y0, 
  2014.                int xpitch, int ypitch,
  2015.                int xcells, int ycells)
  2016. {
  2017. // this function draws the grid
  2018. for (int xc=0; xc < xcells; xc++)
  2019.     {
  2020.     for (int yc=0; yc < ycells; yc++)
  2021.         {
  2022.         Draw_Pixel16(x0 + xc*xpitch, y0 + yc*ypitch, rgbcolor, video_buffer, mempitch);
  2023.         } // end for y
  2024.     } // end for x
  2025. } // end Draw_Grid
  2026. //////////////////////////////////////////////////////////////////////////////
  2027. /*
  2028. BSP .LEV file format version 1.0
  2029. d integer, f floating point value
  2030. Version: f    <-- the version, 1.0 in this case
  2031. NumSections: d  <-- number of sections, always 2 for now
  2032. Section: walls
  2033. NumWalls: n    <-- number of walls 
  2034. x0.f y0.f x1.f y1.f evel.f height.f text_id.d color.d attr.d <-- endpoints, elevation, and height of wall, texture id, color, attributes
  2035. .
  2036. .
  2037. .
  2038. x0.f y0.f x1.f y1.f elev.f height.f text_id.d color.d attr.d <-- endpoints, elevation, and height of wall, texture id, color, attributes
  2039. EndSection
  2040. Section: floors
  2041. NumFloorsX: d              < -- number of floor cells in X directions, or columns
  2042. NumFloorsY: d              < -- number of floor cells in Y direction, or rows
  2043. id0.d id1.d id2.d ..... id(NumFloorsX - 1).d    < -- a total of NumFloorsY rows, each idi is the texture id
  2044. .                                               < -- -1 means no floor tile there
  2045. .
  2046. .
  2047. .
  2048. id0.d id1.d id2.d ..... id(NumFloorsX - 1).d
  2049. EndSection
  2050. example*********
  2051. Version: 1.0
  2052. NumSections: 2
  2053. Section: walls
  2054. NumWalls: 4 
  2055. 10 10 20 10 0 10 0
  2056. 20 10 20 20 0 10 0
  2057. 20 20 10 20 0 10 0
  2058. 10 20 10 10 0 10 0
  2059. Ends
  2060. Section: floors
  2061. NumFloorsX: 6
  2062. NumFloorsY: 4
  2063. -1 0 0 -1 -1 -1
  2064. -1 0 0 -1 -1 -1
  2065. -1 -1 -1 -1 -1 -1
  2066. -1 -1 -1 -1 -1 -1
  2067. ends
  2068. */
  2069. int Load_BSP_File_LEV(char *filename)
  2070. {
  2071. // this function loads a bsp .LEV file, it uses very simple fscanf functions
  2072. // rather than our parser 
  2073. float version;     // holds the version number
  2074. int num_sections,  // number of sections
  2075.     num_walls,     // number of walls
  2076.     bsp_cells_x,   // number of cells on x,y axis
  2077.     bsp_cells_y;
  2078. FILE *fp; // file pointer
  2079. char token1[80], token2[80], token3[80]; // general string tokens
  2080. // try and open file for writing
  2081. if ((fp = fopen(filename, "r")) == NULL)
  2082.    {
  2083.    sprintf(buffer, "Error - File %s not found.",filename);
  2084.    MessageBox(main_window_handle, buffer, "BSP Level Generator",MB_OK);   
  2085.    return(0);
  2086.    } // end if
  2087. // read version
  2088. fscanf(fp, "%s %f", token1, &version);
  2089. if (version!=1.0f)
  2090.    {
  2091.    sprintf(buffer, "Error - Wrong Version.",filename);
  2092.    MessageBox(main_window_handle, buffer, "BSP Level Generator",MB_OK);   
  2093.    return(0);
  2094.    } // end if
  2095. // read number of sections
  2096. fscanf(fp, "%s %d", token1, &num_sections);
  2097. if (num_sections!=2)
  2098.    {
  2099.    sprintf(buffer, "Error - Wrong Number of Sections.",filename);
  2100.    MessageBox(main_window_handle, buffer, "BSP Level Generator",MB_OK);   
  2101.    return(0);
  2102.    } // end if
  2103. // read wall section
  2104. fscanf(fp,"%s %s", token1, token2);
  2105. // read number of walls
  2106. fscanf(fp,"%s %d", token1, &num_walls);
  2107. // read each wall
  2108. for (int w_index = 0; w_index < num_walls; w_index++)
  2109.     {
  2110.     // x0.f y0.f x1.f y1.f elev.f height.f text_id.d color.id attr.d
  2111.     fscanf(fp, "%f %f %f %f %d %d %d %d %d", &lines[w_index].p0.x, 
  2112.                                              &lines[w_index].p0.y,
  2113.                                              &lines[w_index].p1.x, 
  2114.                                              &lines[w_index].p1.y,
  2115.                                              &lines[w_index].elev, 
  2116.                                              &lines[w_index].height,
  2117.                                              &lines[w_index].texture_id,
  2118.                                              &lines[w_index].color,
  2119.                                              &lines[w_index].attr );
  2120.     } // end for w_index
  2121. // read the end section 
  2122. fscanf(fp,"%s", token1);
  2123. // read floor section
  2124. fscanf(fp,"%s %s", token1, token2);
  2125. // read number of x floors
  2126. fscanf(fp,"%s %d", token1, &bsp_cells_x);
  2127. // read number of y floors
  2128. fscanf(fp,"%s %d", token1, &bsp_cells_y);
  2129. // read in actual texture indices of floor tiles
  2130. for (int y_index = 0; y_index < BSP_CELLS_Y-1; y_index++)
  2131.     {
  2132.     // read in next row of indices
  2133.     for (int x_index = 0; x_index < BSP_CELLS_X-1; x_index++)
  2134.         {
  2135.         fscanf(fp, "%d", &floors[y_index][x_index]);
  2136.         } // end for x_index       
  2137.     } // end for
  2138. // read the end section 
  2139. fscanf(fp,"%s", token1);
  2140. // set globals
  2141. total_lines = num_walls;
  2142. // bsp_cells_x
  2143. // bsp_cells_y
  2144. // close the file
  2145. fclose(fp);
  2146. // return success
  2147. return(1);
  2148. } // end Load_BSP_File_LEV
  2149. //////////////////////////////////////////////////////////////////////////////
  2150. int Save_BSP_File_LEV(char *filename, int flags)
  2151. {
  2152. // this function loads a bsp .LEV file using fprint for simplicity
  2153. FILE *fp; // file pointer
  2154. // try and open file for writing
  2155. if ((fp = fopen(filename, "w")) == NULL)
  2156.    return(0);
  2157. // write version
  2158. fprintf(fp, "nVersion: 1.0");
  2159. // print out a newline
  2160. fprintf(fp, "n");
  2161. // write number of sections
  2162. fprintf(fp, "nNumSections: 2");
  2163. // print out a newline
  2164. fprintf(fp, "n");
  2165. // write wall section
  2166. fprintf(fp,"nSection: walls");
  2167. // print out a newline
  2168. fprintf(fp, "n");
  2169. // write number of walls
  2170. fprintf(fp,"nNumWalls: %d", total_lines);
  2171. // print out a newline
  2172. fprintf(fp, "n");
  2173. // write each wall
  2174. for (int w_index = 0; w_index < total_lines; w_index++)
  2175.     {
  2176.     // x0.f y0.f x1.f y1.f elev.f height.f text_id.d
  2177.     fprintf(fp, "n%d %d %d %d %d %d %d %d %d ", (int)lines[w_index].p0.x, 
  2178.                                                  (int)lines[w_index].p0.y,
  2179.                                                  (int)lines[w_index].p1.x, 
  2180.                                                  (int)lines[w_index].p1.y,
  2181.                                                  lines[w_index].elev, 
  2182.                                                  lines[w_index].height,
  2183.                                                  lines[w_index].texture_id,
  2184.                                                  lines[w_index].color,
  2185.                                                  lines[w_index].attr);
  2186.     } // end for w_index
  2187. // print out a newline
  2188. fprintf(fp, "n");
  2189. // write the end section 
  2190. fprintf(fp,"nEndSection");
  2191. // print out a newline
  2192. fprintf(fp, "n");
  2193. // write floor section
  2194. fprintf(fp,"nSection: floors");
  2195. // print out a newline
  2196. fprintf(fp, "n");
  2197. // write number of x floors
  2198. fprintf(fp,"nNumFloorsX: %d", BSP_CELLS_X-1);
  2199. // write number of y floors
  2200. fprintf(fp,"nNumFloorsY: %d", BSP_CELLS_Y-1);
  2201. // print out a newline
  2202. fprintf(fp, "n");
  2203. // write out actual texture indices of floor tiles
  2204. for (int y_index = 0; y_index < BSP_CELLS_Y-1; y_index++)
  2205.     {
  2206.     // print out a newline
  2207.     fprintf(fp, "n");
  2208.     // print out next row of indices
  2209.     for (int x_index = 0; x_index < BSP_CELLS_X-1; x_index++)
  2210.         {
  2211.         fprintf(fp, "%d ", floors[y_index][x_index]);
  2212.         } // end for x_index       
  2213.     } // end for
  2214. // print out a newline
  2215. fprintf(fp, "n");
  2216. // write the end section 
  2217. fprintf(fp,"nEndSection");
  2218. // close the file
  2219. fclose(fp);
  2220. // return success
  2221. return(1);
  2222. } // end Save_BSP_File_LEV
  2223. //////////////////////////////////////////////////////////////////////////////
  2224. void Convert_Lines_To_Walls(void)
  2225. {
  2226. // this function converts the list of 2-D lines into a linked list of 3-D
  2227. // walls, computes the normal of each wall and sets the pointers up
  2228. // also the function labels the lines on the screen so the user can see them
  2229. BSPNODEV1_PTR last_wall, // used to track the last wall processed
  2230.            temp_wall;    // used as a temporary to build a wall up
  2231. VECTOR4D u,v;            // working vectors
  2232. char buffer[256];        // text buffer
  2233. // process each 2-d line and convert it into a 3-d wall
  2234. for (int index=0; index < total_lines; index++)
  2235.     {
  2236.     // allocate the memory for the wall
  2237.     temp_wall = (BSPNODEV1_PTR)malloc(sizeof(BSPNODEV1));
  2238.     memset(temp_wall, 0, sizeof(BSPNODEV1));
  2239.     // set up links
  2240.     temp_wall->link  = NULL;
  2241.     temp_wall->front = NULL;
  2242.     temp_wall->back  = NULL;
  2243.     // assign points, note how y and z are transposed and the y's of the
  2244.     // walls are fixed, this is because we ae looking down on the universe
  2245.     // from an aerial view and the wall height is arbitrary; however, with
  2246.     // the constants we have selected the walls are WALL_CEILING units tall centered
  2247.     // about the x-z plane
  2248.     // vertex 0
  2249.     temp_wall->wall.vlist[0].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + lines[index].p0.x);
  2250.     temp_wall->wall.vlist[0].y = lines[index].elev + lines[index].height;
  2251.     temp_wall->wall.vlist[0].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + lines[index].p0.y);
  2252.     temp_wall->wall.vlist[0].w = 1;
  2253.     // vertex 1
  2254.     temp_wall->wall.vlist[1].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + lines[index].p1.x);
  2255.     temp_wall->wall.vlist[1].y = lines[index].elev + lines[index].height;
  2256.     temp_wall->wall.vlist[1].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + lines[index].p1.y);
  2257.     temp_wall->wall.vlist[1].w = 1;
  2258.     // vertex 2
  2259.     temp_wall->wall.vlist[2].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + lines[index].p1.x);
  2260.     temp_wall->wall.vlist[2].y = lines[index].elev;
  2261.     temp_wall->wall.vlist[2].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + lines[index].p1.y);
  2262.     temp_wall->wall.vlist[2].w = 1;
  2263.     // vertex 3
  2264.     temp_wall->wall.vlist[3].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + lines[index].p0.x);
  2265.     temp_wall->wall.vlist[3].y = lines[index].elev;
  2266.     temp_wall->wall.vlist[3].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + lines[index].p0.y);
  2267.     temp_wall->wall.vlist[3].w = 1;
  2268.     // compute normal to wall
  2269.     // find two vectors co-planer in the wall
  2270.     VECTOR4D_Build(&temp_wall->wall.vlist[0].v, &temp_wall->wall.vlist[1].v,&u);
  2271.     VECTOR4D_Build(&temp_wall->wall.vlist[0].v, &temp_wall->wall.vlist[3].v, &v);
  2272.     // use cross product to compute normal
  2273.     VECTOR4D_Cross(&u, &v, &temp_wall->wall.normal);
  2274.     // normalize the normal vector
  2275.     float length = VECTOR4D_Length(&temp_wall->wall.normal);
  2276.     temp_wall->wall.normal.x /= length;
  2277.     temp_wall->wall.normal.y /= length;
  2278.     temp_wall->wall.normal.z /= length; 
  2279.     temp_wall->wall.normal.w  = 1.0;
  2280.     temp_wall->wall.nlength   = length;
  2281.     // set id number for debugging
  2282.     temp_wall->id = index;
  2283.     // set attributes of polygon
  2284.     temp_wall->wall.attr = lines[index].attr;
  2285.     // set color of polygon, if texture then white
  2286.     // else whatever the color is
  2287.     temp_wall->wall.color = lines[index].color;
  2288.     // now based on attributes set vertex flags
  2289.     // every vertex has a point at least, set that in the flags attribute
  2290.     SET_BIT(temp_wall->wall.vlist[0].attr, VERTEX4DTV1_ATTR_POINT); 
  2291.     SET_BIT(temp_wall->wall.vlist[1].attr, VERTEX4DTV1_ATTR_POINT);
  2292.     SET_BIT(temp_wall->wall.vlist[2].attr, VERTEX4DTV1_ATTR_POINT);
  2293.     SET_BIT(temp_wall->wall.vlist[3].attr, VERTEX4DTV1_ATTR_POINT);
  2294.     // check for gouraud of phong shading, if so need normals
  2295.     if ( (temp_wall->wall.attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD) ||  
  2296.          (temp_wall->wall.attr & POLY4DV2_ATTR_SHADE_MODE_PHONG) )
  2297.        {
  2298.        // the vertices from this polygon all need normals, set that in the flags attribute
  2299.        SET_BIT(temp_wall->wall.vlist[0].attr, VERTEX4DTV1_ATTR_NORMAL); 
  2300.        SET_BIT(temp_wall->wall.vlist[1].attr, VERTEX4DTV1_ATTR_NORMAL);
  2301.        SET_BIT(temp_wall->wall.vlist[2].attr, VERTEX4DTV1_ATTR_NORMAL);
  2302.        SET_BIT(temp_wall->wall.vlist[3].attr, VERTEX4DTV1_ATTR_NORMAL);
  2303.        // ??? make sure to create vertex normal....
  2304.        } // end if
  2305.      
  2306.      // if texture in enabled the enable texture coordinates
  2307.      if (lines[index].texture_id >= 0)
  2308.         {
  2309.         // apply texture to this polygon
  2310.         SET_BIT(temp_wall->wall.attr, POLY4DV2_ATTR_SHADE_MODE_TEXTURE);
  2311.         temp_wall->wall.texture = &texturemaps[lines[index].texture_id];
  2312.         // assign the texture coordinates
  2313.         temp_wall->wall.vlist[0].u0 = 0;
  2314.         temp_wall->wall.vlist[0].v0 = 0;
  2315.         temp_wall->wall.vlist[1].u0 = TEXTURE_SIZE-1;
  2316.         temp_wall->wall.vlist[1].v0 = 0;
  2317.         temp_wall->wall.vlist[2].u0 = TEXTURE_SIZE-1;
  2318.         temp_wall->wall.vlist[2].v0 = TEXTURE_SIZE-1;
  2319.         temp_wall->wall.vlist[3].u0 = 0;
  2320.         temp_wall->wall.vlist[3].v0 = TEXTURE_SIZE-1;
  2321.         
  2322.         // set texture coordinate attributes
  2323.         SET_BIT(temp_wall->wall.vlist[0].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2324.         SET_BIT(temp_wall->wall.vlist[1].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2325.         SET_BIT(temp_wall->wall.vlist[2].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2326.         SET_BIT(temp_wall->wall.vlist[3].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2327.         } // end if
  2328. #if 0
  2329.     // check for alpha enable 
  2330.     if (temp_wall->wall.attr & POLY4DV2_ATTR_TRANSPARENT)
  2331.        {
  2332.           int ialpha = (int)( (float)alpha/255 * (float)(NUM_ALPHA_LEVELS-1) + (float)0.5);
  2333.           // set the alpha color in upper 8 bits of color
  2334.           temp_wall->wall.color += (ialpha << 24);
  2335.        } // end if 
  2336. #endif
  2337.     // finally set the polygon to active
  2338.     temp_wall->wall.state = POLY4DV2_STATE_ACTIVE;    
  2339.     
  2340.     // update ceiling height to max wall height
  2341.     if ((lines[index].elev + lines[index].height) > ceiling_height)
  2342.        ceiling_height = lines[index].elev + lines[index].height;
  2343.     Write_Error("nnConverting wall %d, v0=[%f,%f,%f]n v1=[%f,%f,%f]n v2=[%f,%f,%f]n v3=[%f,%f,%f] nnl=%f", index,
  2344.                  temp_wall->wall.vlist[0].x, temp_wall->wall.vlist[0].y, temp_wall->wall.vlist[0].z, 
  2345.                  temp_wall->wall.vlist[1].x, temp_wall->wall.vlist[1].y, temp_wall->wall.vlist[1].z, 
  2346.                  temp_wall->wall.vlist[2].x, temp_wall->wall.vlist[2].y, temp_wall->wall.vlist[2].z, 
  2347.                  temp_wall->wall.vlist[3].x, temp_wall->wall.vlist[3].y, temp_wall->wall.vlist[3].z, 
  2348.                  temp_wall->wall.nlength );
  2349.     // test if this is first wall
  2350.     if (index==0)
  2351.        {
  2352.        // set head of wall list pointer and last wall pointer
  2353.        wall_list = temp_wall;
  2354.        last_wall = temp_wall;
  2355.        } // end if first wall
  2356.     else
  2357.        {
  2358.        // the first wall has been taken care of
  2359.        // link the last wall to the next wall
  2360.        last_wall->link = temp_wall;
  2361.        // move the last wall to the next wall
  2362.        last_wall = temp_wall;
  2363.        } // end else
  2364.     } // end for index
  2365. } // end Convert_Lines_To_Walls
  2366. //////////////////////////////////////////////////////////////////////////////
  2367. int Generate_Floors_OBJECT4DV2(OBJECT4DV2_PTR obj, // pointer to object
  2368.                               int rgbcolor,        // color of floor if no texture        
  2369.                               VECTOR4D_PTR pos,    // initial position
  2370.                               VECTOR4D_PTR rot,    // initial rotations
  2371.                               int poly_attr)       // the shading attributes we would like
  2372. {
  2373. // this function uses the global floor and texture arrays to generate the
  2374. // floor mesh under the player, basically for each floor tile that is not -1
  2375. // there should be a floor tile at that position, hence the function uses
  2376. // this fact to create an object that is composed of triangles that makes
  2377. // up the floor mesh, also the texture pointers are assigned to the global
  2378. // texture bitmaps, the function only creates a single floor mesh, the 
  2379. // same mesh is used for the ceiling, but only raised during rendering...
  2380. char buffer[256];  // working buffer
  2381. BITMAP_FILE height_bitmap; // holds the height bitmap
  2382. // Step 1: clear out the object and initialize it a bit
  2383. memset(obj, 0, sizeof(OBJECT4DV2));
  2384. // set state of object to active and visible
  2385. obj->state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;
  2386. // set position of object
  2387. obj->world_pos.x = pos->x;
  2388. obj->world_pos.y = pos->y;
  2389. obj->world_pos.z = pos->z;
  2390. obj->world_pos.w = pos->w;
  2391. // set number of frames
  2392. obj->num_frames = 1;
  2393. obj->curr_frame = 0;
  2394. obj->attr       = OBJECT4DV2_ATTR_SINGLE_FRAME;
  2395. // store any outputs here..
  2396. obj->ivar1 = 0;
  2397. obj->ivar2 = 0;
  2398. obj->fvar1 = 0;
  2399. obj->fvar2 = 0;
  2400. int floor_tiles = 0;
  2401. // set number of vertices and polygons to zero
  2402. obj->num_vertices = 0;
  2403. obj->num_polys    = 0;
  2404. // count up floor tiles
  2405. for (int y_index = 0; y_index < BSP_CELLS_Y-1; y_index++)
  2406.     {
  2407.     // print out next row of indices
  2408.     for (int x_index = 0; x_index < BSP_CELLS_X-1; x_index++)
  2409.         {
  2410.         // is there an active tile here?
  2411.         if (floors[y_index][x_index] >=0 )
  2412.            {
  2413.            // 2 triangles per tile
  2414.            obj->num_polys+=2;     
  2415.            // 4 vertices per tile
  2416.            obj->num_vertices+=4;        
  2417.            } // end if 
  2418.         } // end for x_index       
  2419.     } // end for
  2420. // allocate the memory for the vertices and number of polys
  2421. // the call parameters are redundant in this case, but who cares
  2422. if (!Init_OBJECT4DV2(obj,   // object to allocate
  2423.                      obj->num_vertices, 
  2424.                      obj->num_polys, 
  2425.                      obj->num_frames))
  2426.     {
  2427.     Write_Error("nTerrain generator error (can't allocate memory).");
  2428.     } // end if
  2429.     // flag object as having textures
  2430.     SET_BIT(obj->attr, OBJECT4DV2_ATTR_TEXTURES);
  2431. // now generate the vertex list and polygon list at the same time
  2432. // 2 triangles per floor tile, 4 vertices per floor tile
  2433. // generate the data row by row
  2434. // initialize indices, we generate on the fly when we find an active tile
  2435. int curr_vertex = 0;
  2436. int curr_poly   = 0;
  2437. for (y_index = 0; y_index < BSP_CELLS_Y-1; y_index++)
  2438.     {
  2439.     for (int x_index = 0; x_index < BSP_CELLS_X-1; x_index++)
  2440.         {
  2441.         int texture_id = -1;
  2442.         // does this tile have a texture    
  2443.         if ((texture_id = floors[y_index][x_index]) >=0 )
  2444.         { 
  2445.         // compute the vertices
  2446.         // vertex 0
  2447.         obj->vlist_local[curr_vertex].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + (x_index+0)*BSP_GRID_SIZE);
  2448.         obj->vlist_local[curr_vertex].y = 0;
  2449.         obj->vlist_local[curr_vertex].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + (y_index+1)*BSP_GRID_SIZE);
  2450.         obj->vlist_local[curr_vertex].w = 1;  
  2451.         // we need texture coordinates
  2452.         obj->tlist[curr_vertex].x = 0;
  2453.         obj->tlist[curr_vertex].y = 0;
  2454.         // every vertex has a point at least, set that in the flags attribute
  2455.         SET_BIT(obj->vlist_local[curr_vertex].attr, VERTEX4DTV1_ATTR_POINT);
  2456.         // increment vertex index
  2457.         curr_vertex++;
  2458.         // vertex 1
  2459.         obj->vlist_local[curr_vertex].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + (x_index+0)*BSP_GRID_SIZE);
  2460.         obj->vlist_local[curr_vertex].y = 0;
  2461.         obj->vlist_local[curr_vertex].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + (y_index+0)*BSP_GRID_SIZE);
  2462.         obj->vlist_local[curr_vertex].w = 1;  
  2463.         // we need texture coordinates
  2464.         obj->tlist[curr_vertex].x = 0;
  2465.         obj->tlist[curr_vertex].y = TEXTURE_SIZE-1;
  2466.         // every vertex has a point at least, set that in the flags attribute
  2467.         SET_BIT(obj->vlist_local[curr_vertex].attr, VERTEX4DTV1_ATTR_POINT);
  2468.         // increment vertex index
  2469.         curr_vertex++;
  2470.         // vertex 2
  2471.         obj->vlist_local[curr_vertex].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + (x_index+1)*BSP_GRID_SIZE);
  2472.         obj->vlist_local[curr_vertex].y = 0;
  2473.         obj->vlist_local[curr_vertex].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + (y_index+0)*BSP_GRID_SIZE);
  2474.         obj->vlist_local[curr_vertex].w = 1;  
  2475.         // we need texture coordinates
  2476.         obj->tlist[curr_vertex].x = TEXTURE_SIZE-1;
  2477.         obj->tlist[curr_vertex].y = TEXTURE_SIZE-1;
  2478.         // every vertex has a point at least, set that in the flags attribute
  2479.         SET_BIT(obj->vlist_local[curr_vertex].attr, VERTEX4DTV1_ATTR_POINT);
  2480.         // increment vertex index
  2481.         curr_vertex++;
  2482.         // vertex 3
  2483.         obj->vlist_local[curr_vertex].x = WORLD_SCALE_X * (SCREEN_TO_WORLD_X + (x_index+1)*BSP_GRID_SIZE);
  2484.         obj->vlist_local[curr_vertex].y = 0;
  2485.         obj->vlist_local[curr_vertex].z = WORLD_SCALE_Z * (SCREEN_TO_WORLD_Z + (y_index+1)*BSP_GRID_SIZE);
  2486.         obj->vlist_local[curr_vertex].w = 1;  
  2487.         // we need texture coordinates
  2488.         obj->tlist[curr_vertex].x = TEXTURE_SIZE-1;
  2489.         obj->tlist[curr_vertex].y = 0;
  2490.         // every vertex has a point at least, set that in the flags attribute
  2491.         SET_BIT(obj->vlist_local[curr_vertex].attr, VERTEX4DTV1_ATTR_POINT);
  2492.         // increment vertex index
  2493.         curr_vertex++;
  2494.         // upper left poly vertex index
  2495.         obj->plist[curr_poly].vert[0] = curr_vertex-4; // 0
  2496.         obj->plist[curr_poly].vert[1] = curr_vertex-3; // 1
  2497.         obj->plist[curr_poly].vert[2] = curr_vertex-2; // 2
  2498.         // lower right poly vertex index
  2499.         obj->plist[curr_poly+1].vert[0] = curr_vertex-4; // 0
  2500.         obj->plist[curr_poly+1].vert[1] = curr_vertex-2; // 2
  2501.         obj->plist[curr_poly+1].vert[2] = curr_vertex-1; // 3
  2502.         // point polygon vertex list to object's vertex list
  2503.         // note that this is redundant since the polylist is contained
  2504.         // within the object in this case and its up to the user to select
  2505.         // whether the local or transformed vertex list is used when building up
  2506.         // polygon geometry, might be a better idea to set to NULL in the context
  2507.         // of polygons that are part of an object
  2508.         obj->plist[curr_poly].vlist   = obj->vlist_local; 
  2509.         obj->plist[curr_poly+1].vlist = obj->vlist_local; 
  2510.         // set attributes of polygon with sent attributes
  2511.         obj->plist[curr_poly].attr    = poly_attr;
  2512.         obj->plist[curr_poly+1].attr  = poly_attr;
  2513.         // set color of polygon 
  2514.         obj->plist[curr_poly].color   = rgbcolor;
  2515.         obj->plist[curr_poly+1].color = rgbcolor;
  2516.         // apply texture to this polygon
  2517.         obj->plist[curr_poly].texture   = &texturemaps[ floors[y_index][x_index] ];
  2518.         obj->plist[curr_poly+1].texture = &texturemaps[ floors[y_index][x_index] ];
  2519.         // assign the texture coordinate index
  2520.         // upper left poly
  2521.         obj->plist[curr_poly].text[0] = curr_vertex-4; // 0
  2522.         obj->plist[curr_poly].text[1] = curr_vertex-3; // 1
  2523.         obj->plist[curr_poly].text[2] = curr_vertex-2; // 2
  2524.         // lower right poly
  2525.         obj->plist[curr_poly+1].text[0] = curr_vertex-4; // 0
  2526.         obj->plist[curr_poly+1].text[1] = curr_vertex-2; // 2
  2527.         obj->plist[curr_poly+1].text[2] = curr_vertex-1; // 3
  2528.  
  2529.         // set texture coordinate attributes
  2530.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2531.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2532.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2533.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly+1].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2534.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly+1].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2535.         SET_BIT(obj->vlist_local[ obj->plist[curr_poly+1].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  2536.         // set the material mode to ver. 1.0 emulation
  2537.         SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
  2538.         SET_BIT(obj->plist[curr_poly+1].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
  2539.         // finally set the polygon to active
  2540.         obj->plist[curr_poly].state   = POLY4DV2_STATE_ACTIVE;    
  2541.         obj->plist[curr_poly+1].state = POLY4DV2_STATE_ACTIVE;  
  2542.         // point polygon vertex list to object's vertex list
  2543.         // note that this is redundant since the polylist is contained
  2544.         // within the object in this case and its up to the user to select
  2545.         // whether the local or transformed vertex list is used when building up
  2546.         // polygon geometry, might be a better idea to set to NULL in the context
  2547.         // of polygons that are part of an object
  2548.         obj->plist[curr_poly].vlist   = obj->vlist_local; 
  2549.         obj->plist[curr_poly+1].vlist = obj->vlist_local; 
  2550.         // set texture coordinate list, this is needed
  2551.         obj->plist[curr_poly].tlist   = obj->tlist;
  2552.         obj->plist[curr_poly+1].tlist = obj->tlist;
  2553.        
  2554.         // increase polygon count
  2555.         curr_poly+=2;
  2556.  
  2557.         } // end if there is a textured poly here
  2558.         
  2559.         } // end for x_index
  2560.      } // end for y_index
  2561. // compute average and max radius
  2562. Compute_OBJECT4DV2_Radius(obj);
  2563. // compute the polygon normal lengths
  2564. Compute_OBJECT4DV2_Poly_Normals(obj);
  2565. // compute vertex normals for any gouraud shaded polys
  2566. Compute_OBJECT4DV2_Vertex_Normals(obj);
  2567. // return success
  2568. return(1);
  2569. } // end Generate_Floors_OBJECT4DV2