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

游戏

开发平台:

Visual C++

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