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

游戏

开发平台:

Visual C++

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