home *** CD-ROM | disk | FTP | other *** search
- #include "ray.h"
- #include "rayrend.h"
- #include "rayvb.h"
- #include "bspmove.h"
- #include "globals.h"
-
- typedef long bsp_stack_node;
-
- #define BSP_STACK_LENGTH 1024
- #define STOP_TRACE -2
- #define NODE_MASK 0x8000
-
- #define BSP_LOW_HALF (0x0000FFFF)
- #define BSP_HIGH_HALF (0xFFFF0000)
-
- #define BSP_START_SECTION (0x00000000)
- #define BSP_DO_RIGHT_LEAF (0x00010000)
- #define BSP_DO_LEFT_LEAF (0x00020000)
- #define BSP_END_SECTION (0x00030000)
- #define BSP_NULL_SECTION (0x7fff)
-
- // There will be a stack used in the BSP drawing routine to simulate recursion,
- // because as we all know, real recursion is too slow to use in games
-
- short bsp_stack_size;
- bsp_stack_node bsp_stack[BSP_STACK_LENGTH];
-
- // Two routines to automate push and poping on BSP stack
-
- inline BOOL PushBSPStack(bsp_stack_node push_value) {
-
- if (bsp_stack_size>=BSP_STACK_LENGTH) {
- return TRUE;
- } else {
- bsp_stack[bsp_stack_size]=push_value;
- bsp_stack_size++;
- return FALSE;
- }
-
- }
-
- inline BOOL PopBSPStack(bsp_stack_node & pop_value) {
-
- if (bsp_stack_size<=0) {
- pop_value=STOP_TRACE;
- return TRUE;
- } else {
- bsp_stack_size--;
- pop_value=bsp_stack[bsp_stack_size];
- return FALSE;
- } /* endif */
-
- }
-
- inline BOOL On_Right(bsp_node * current_node)
- {
- long x1, y1, x2, y2;
- x1=current_node->x1;
- x2=current_node->x2;
- y1=current_node->y1;
- y2=current_node->y2;
- if ( fixedmult((x1-x2),(render_y-(y2<<SHIFT))) >= fixedmult((y1-y2),(render_x-(x2<<SHIFT))) ) {
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
-
- inline BOOL On_Right(bsp_node * current_node, long base_x, long base_y)
- {
- long x1, y1, x2, y2;
- x1=current_node->x1;
- x2=current_node->x2;
- y1=current_node->y1;
- y2=current_node->y2;
- if ( ((x1-x2)*(base_y-y2)) >= ((y1-y2)*(base_x-x2)) ) {
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
-
- /*
- Visible_Rect
- Tries to determine if a rectangle is in the view range
- May return TRUE on some rects that are out of the cone
- However, it is quick
- */
-
- inline BOOL Visible_Rect(prectl current_bound)
- {
- long left_angle=Get_Angle_Sum(render_view_angle, ANGLE_30);
- if (left_angle < ANGLE_90) {
- if (current_bound->right > (render_x>>SHIFT)) return TRUE;
- } else if (left_angle < ANGLE_180) {
- if (current_bound->top > (render_y>>SHIFT)) return TRUE;
- } else if (left_angle < ANGLE_270) {
- if (current_bound->left < (render_x>>SHIFT)) return TRUE;
- } else {
- if (current_bound->bottom < (render_y>>SHIFT)) return TRUE;
- } /* endif */
- return FALSE;
- }
-
- // This routine examines the fifthteenth bit of the child node to determine whether they
- // are another recursive division, or a drawable subsector
-
- inline BOOL IsChildSubSector(USHORT child_num) {
- return (((child_num & NODE_MASK) > 0) ? TRUE : FALSE);
- }
-
- inline USHORT GetSSIndex(long index) {
- return (USHORT)(index ^ NODE_MASK);
- }
-
- long Box_Smallest_Node(long x1, long x2, long y1, long y2)
- {
- long cur_node_index=bsp_start_node;
- BOOL cur_side, next_side, found_smallest;
- bsp_node * cur_node;
- found_smallest=FALSE;
- while (!IsChildSubSector(cur_node_index)) {
- cur_node=bsp_tree+cur_node_index;
- cur_side=On_Right(cur_node, x1, y1);
- next_side=On_Right(cur_node, x2, y1);
- if (cur_side!=next_side)
- found_smallest=TRUE;
- next_side=On_Right(cur_node, x2, y2);
- if (cur_side!=next_side)
- found_smallest=TRUE;
- next_side=On_Right(cur_node, x1, y2);
- if (cur_side!=next_side)
- found_smallest=TRUE;
- if (found_smallest)
- break;
- else {
- if (cur_side) {
- cur_node_index=cur_node->right_child;
- } else {
- cur_node_index=cur_node->left_child;
- } /* endif */
- }
- }
- return cur_node_index;
- }
-
- ssector * Get_Object_SSector(pobject find_obj, long starting_node_index)
- {
- long obj_x=find_obj->x;
- long obj_y=find_obj->y;
- long cur_node_index=starting_node_index;
- long x1, y1, x2, y2;
- bsp_node * cur_node;
- while (!IsChildSubSector(cur_node_index)) {
- cur_node=bsp_tree+cur_node_index;
- x1=cur_node->x1;
- x2=cur_node->x2;
- y1=cur_node->y1;
- y2=cur_node->y2;
- if ( fixedmult((x1-x2),(obj_y-(y2<<SHIFT))) >= fixedmult((y1-y2),(obj_x-(x2<<SHIFT))) ) {
- cur_node_index=cur_node->right_child;
- } else {
- cur_node_index=cur_node->left_child;
- } /* endif */
- } /* endwhile */
- return (SS_List+GetSSIndex(cur_node_index));
- }
-
- void BSP_Recursion_Draw()
- {
-
- /*
- This the primary draw routine of the engine. Here's how it works:
-
- Move down a recursive tree, which represents a series of divisions in the map.
- At each node (for our purposes "NODE X"), test first whether this division is even visible.
- If it is, test whether the part on the left side of the division is closer to you.
- If it is, then recurse down the left child tree. Other wise, recurse down the right.
- At the lowest level are subsectors, which are areas where no wall obscures another.
- If the child is one of these, draw and recurse back to NODE 1.
- Then recurse down the to child who side of the division was farther away from you.
- When you get back to NODE X again, recurse back up to its parent node.
- Stop when you've recursed the whole tree, or when there is no more room on the viewing window
-
- This allows for proper depth sorting, as well as efficient front to back drawing.
-
- Since true recursion is too slow, we will fake recursion by using a static stack.
- The stack nodes will be long numbers. The lower sixteen bits will save the node number.
- The upper sixteen bits will save what processing we need to do with that node.
-
- Phew! Everybody got that?
-
- Revision: It should be noted that the recursor attempts to check whether the children's
- bounding boxes are visible, and also no longer uses angles in calculating which
- side is in front of you
-
- */
-
- bsp_stack_size=0;
-
- long current_bsp_section=bsp_start_node;
- long next_bsp_section;
-
- unsigned short low_half; long high_half;
- bsp_node * current_node;
- prectl front_bound, back_bound;
- pssector cur_ss;
-
- while ( (current_bsp_section!=STOP_TRACE) && (!VB_EmptyList()) ) {
-
- low_half=(short)(current_bsp_section & BSP_LOW_HALF);
- high_half=current_bsp_section & BSP_HIGH_HALF;
- current_node=bsp_tree+low_half;
-
- switch (high_half) {
- case BSP_DO_RIGHT_LEAF:
-
- current_bsp_section=low_half + BSP_END_SECTION;
- next_bsp_section=(long)current_node->right_child;
-
- // Is child drawable subsector? If so, draw it. Otherwise, save current node on stack and
- // down to child node
-
- if (IsChildSubSector(next_bsp_section)) {
- cur_ss=SS_List+GetSSIndex(next_bsp_section);
- Draw_Sub_Sector(cur_ss);
- } else {
- PushBSPStack((long)current_bsp_section);
- current_bsp_section=next_bsp_section;
- } /* endif */
-
- break;
-
- case BSP_DO_LEFT_LEAF:
-
- current_bsp_section=low_half + BSP_END_SECTION;
- next_bsp_section=(long)current_node->left_child;
-
- // Is child drawable subsector? If so, draw it. Otherwise, save current node on stack and
- // down to child node
-
- if (IsChildSubSector(next_bsp_section)) {
- cur_ss=SS_List+GetSSIndex(next_bsp_section);
- Draw_Sub_Sector(cur_ss);
- } else {
- PushBSPStack((long)current_bsp_section);
- current_bsp_section=next_bsp_section;
- } /* endif */
-
- break;
-
- case BSP_START_SECTION:
-
- if (low_half==BSP_NULL_SECTION) {
- current_bsp_section=low_half + BSP_END_SECTION;
- continue;
- }
-
- if (On_Right(current_node)) {
- front_bound=&(current_node->right_bound);
- back_bound=&(current_node->left_bound);
- next_bsp_section=current_node->right_child;
- current_bsp_section=low_half+BSP_DO_LEFT_LEAF;
- } else {
- front_bound=&(current_node->left_bound);
- back_bound=&(current_node->right_bound);
- next_bsp_section=current_node->left_child;
- current_bsp_section=low_half+BSP_DO_RIGHT_LEAF;
- }
-
- if (!Visible_Rect(back_bound))
- current_bsp_section=low_half+BSP_END_SECTION;
-
- if (!Visible_Rect(front_bound))
- continue;
-
- // Is child drawable subsector? If so, draw it. Otherwise, save current node on stack and
- // down to child node
-
- if (IsChildSubSector(next_bsp_section)) {
- cur_ss=SS_List+GetSSIndex(next_bsp_section);
- Draw_Sub_Sector(cur_ss);
- } else {
- PushBSPStack((long)current_bsp_section);
- current_bsp_section=next_bsp_section;
- } /* endif */
-
- break;
-
- case BSP_END_SECTION:
- PopBSPStack(current_bsp_section);
- break;
-
- default:
- return;
- } /* end switch */
-
- } /* endwhile */
-
- }