home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / meddraw.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  28KB  |  1,054 lines

  1. /*
  2.  * $Source: f:/miner/source/main/editor/rcs/meddraw.c $
  3.  * $Revision: 2.0 $
  4.  * $Author: john $
  5.  * $Date: 1995/02/27 11:34:42 $
  6.  * 
  7.  * Med drawing functions.
  8.  * 
  9.  * $Log: meddraw.c $
  10.  * Revision 2.0  1995/02/27  11:34:42  john
  11.  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
  12.  * for bitmaps.tbl.
  13.  * 
  14.  * Revision 1.34  1994/11/09  11:46:30  matt
  15.  * Don't draw non-existant special segments
  16.  * 
  17.  * Revision 1.33  1994/10/27  10:06:38  mike
  18.  * adapt to no inverse table.
  19.  * 
  20.  * Revision 1.32  1994/10/17  18:06:23  john
  21.  * Made net player objects draw in dark green.
  22.  * 
  23.  * Revision 1.31  1994/09/26  16:44:33  yuan
  24.  * Colored special segments.
  25.  * 
  26.  * Revision 1.30  1994/09/01  17:02:41  matt
  27.  * Redraw pointer after world draw
  28.  * 
  29.  * Revision 1.29  1994/08/25  21:56:21  mike
  30.  * IS_CHILD stuff.
  31.  * 
  32.  * Revision 1.28  1994/08/11  18:59:46  mike
  33.  * Adapt to new int (vs short) version of gameseg functions.
  34.  * 
  35.  * Revision 1.27  1994/08/09  16:06:03  john
  36.  * Added the ability to place players.  Made old
  37.  * Player variable be ConsoleObject.
  38.  * 
  39.  * Revision 1.26  1994/07/25  00:03:05  matt
  40.  * Various changes to accomodate new 3d, which no longer takes point numbers
  41.  * as parms, and now only takes pointers to points.
  42.  * 
  43.  * Revision 1.25  1994/07/09  17:38:13  mike
  44.  * comment out mprintf(0, "\n");
  45.  * 
  46.  * Revision 1.24  1994/07/07  19:34:47  matt
  47.  * These changes are mostly Mike's, but I fixed a little bug that caused
  48.  * some edges to think they were never used.
  49.  * 
  50.  * Revision 1.23  1994/07/06  16:36:18  mike
  51.  * Optionally only draw segment lines which are in only one segment.
  52.  * 
  53.  * Revision 1.22  1994/05/27  10:34:28  yuan
  54.  * Added new Dialog boxes for Walls and Triggers.
  55.  * 
  56.  * Revision 1.21  1994/05/14  18:00:56  matt
  57.  * Got rid of externs in source (non-header) files
  58.  * 
  59.  * Revision 1.20  1994/05/09  23:35:21  mike
  60.  * Change order of drawing found and selected segments.
  61.  * 
  62.  * Revision 1.19  1994/05/05  12:55:38  yuan
  63.  * Fixed a bunch of group bugs.
  64.  * 
  65.  * Revision 1.18  1994/05/04  13:07:52  matt
  66.  * Made current edge draw in green in wire-frame window
  67.  * Also, moved a bunch of color constants here from editor.h
  68.  * 
  69.  */
  70.  
  71.  
  72. #pragma off (unreferenced)
  73. static char rcsid[] = "$Id: meddraw.c 2.0 1995/02/27 11:34:42 john Exp $";
  74. #pragma on (unreferenced)
  75.  
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <stdarg.h>
  79. #include <string.h>
  80. #include <process.h>
  81.  
  82.  
  83. #include "inferno.h"
  84. #include "segment.h"
  85. #include "segpoint.h"
  86. #include "gameseg.h"
  87. #include "gr.h"
  88. #include "ui.h"
  89. #include "editor.h"
  90.  
  91. #include "wall.h"
  92. #include "switch.h"
  93.  
  94. #include "key.h"
  95. #include "mono.h"
  96. #include "error.h"
  97. #include "medlisp.h"
  98. #include "mem.h"
  99. #include "render.h"
  100. #include "game.h"
  101. //#include "slew.h"
  102. #include "kdefs.h"
  103. #include "func.h"
  104. #include "textures.h"
  105. #include "screens.h"
  106. #include "texmap.h"
  107. #include "object.h"
  108. #include "cflib.h"
  109. #include "fuelcen.h"
  110.  
  111. //    Colors used in editor for indicating various kinds of segments.
  112. #define    SELECT_COLOR        BM_XRGB( 63/2 , 41/2 ,  0/2)
  113. #define    FOUND_COLOR            BM_XRGB(  0/2 , 30/2 , 45/2)
  114. #define    WARNING_COLOR        BM_XRGB( 63/2 ,  0/2 ,  0/2)
  115. #define    AXIS_COLOR            BM_XRGB( 63/2 ,  0/2 , 63/2)
  116. #define    PLAINSEG_COLOR        BM_XRGB( 45/2 , 45/2 , 45/2)
  117. #define    MARKEDSEG_COLOR    BM_XRGB(  0/2 , 63/2 ,  0/2)
  118. #define    MARKEDSIDE_COLOR    BM_XRGB(  0/2 , 63/2 , 63/2)
  119. #define    CURSEG_COLOR        BM_XRGB( 63/2 , 63/2 , 63/2)
  120. #define    CURSIDE_COLOR        BM_XRGB( 63/2 , 63/2 ,  0/2)
  121. #define    CUREDGE_COLOR        BM_XRGB(  0   , 63/2 ,  0  )
  122. #define    GROUPSEG_COLOR        BM_XRGB(     0/2 ,  0/2 , 63/2)
  123. #define  GROUPSIDE_COLOR     BM_XRGB(    63/2 ,  0/2 , 45/2)
  124. #define     GROUP_COLOR            BM_XRGB(  0/2 , 45/2 ,  0/2)    
  125. #define    ROBOT_COLOR            BM_XRGB( 31   ,  0   ,  0  )
  126. #define    PLAYER_COLOR        BM_XRGB(  0   ,  0   , 31  )
  127.  
  128. #define DOUBLE_BUFFER 1
  129.  
  130. int     Search_mode=0;                      //if true, searching for segments at given x,y
  131. int Search_x,Search_y;
  132. int    Automap_test=0;        //    Set to 1 to show wireframe in automap mode.
  133.  
  134. draw_seg_objects(segment *seg)
  135. {
  136.     int objnum;
  137.  
  138.     for (objnum=seg->objects;objnum!=-1;objnum=Objects[objnum].next) {
  139.         object *obj = &Objects[objnum];
  140.         g3s_point sphere_point;
  141.  
  142.         if ((obj->type==OBJ_PLAYER) && (objnum > 0 ))
  143.             gr_setcolor(BM_XRGB( 0,  25, 0  ));
  144.         else
  145.             gr_setcolor(obj==ConsoleObject?PLAYER_COLOR:ROBOT_COLOR);
  146.  
  147.         g3_rotate_point(&sphere_point,&obj->pos);
  148.  
  149.         g3_draw_sphere(&sphere_point,obj->size);
  150.     }
  151.  
  152. }
  153.  
  154. draw_line(int pnum0,int pnum1)
  155. {
  156.     g3_draw_line(&Segment_points[pnum0],&Segment_points[pnum1]);
  157. }
  158.  
  159. // ----------------------------------------------------------------------------
  160. void draw_segment(segment *seg)
  161. {
  162.     short    *svp;
  163.     int    nv;
  164.     g3s_codes cc;
  165.  
  166.     if (seg->segnum == -1)        //this segment doesn't exitst
  167.         return;
  168.  
  169.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  170.     cc=rotate_list(nv,svp);
  171.  
  172.     if (! cc.and) {        //all off screen?
  173.         int i;
  174.  
  175.         for (i=0;i<4;i++) draw_line(svp[i],svp[i+4]);
  176.  
  177.         for (i=0;i<3;i++) {
  178.             draw_line(svp[i]  ,svp[i+1]);
  179.             draw_line(svp[i+4],svp[i+4+1]);
  180.         }
  181.  
  182.         draw_line(svp[0],svp[3]);
  183.         draw_line(svp[0+4],svp[3+4]);
  184.  
  185.     }
  186.  
  187. }
  188.  
  189. //for looking for segment under a mouse click
  190. void check_segment(segment *seg)
  191. {
  192.     short    *svp;
  193.     int    nv;
  194.     g3s_codes cc;
  195.  
  196.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  197.     cc=rotate_list(nv,svp);
  198.  
  199.     if (! cc.and) {        //all off screen?
  200.         int fn;
  201.  
  202.         gr_setcolor(0);
  203.         gr_pixel(Search_x,Search_y);    //set our search pixel to color zero
  204.         gr_setcolor(1);                    //and render in color one
  205.  
  206.         for (fn=0;fn<6;fn++) {
  207.             g3s_point *vert_list[4];
  208.             
  209.             vert_list[0] = &Segment_points[seg->verts[Side_to_verts[fn][0]]];
  210.             vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][1]]];
  211.             vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][2]]];
  212.             g3_check_and_draw_poly(3,vert_list,NULL,NULL);
  213.  
  214.             vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][2]]];
  215.             vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][3]]];
  216.             g3_check_and_draw_poly(3,vert_list,NULL,NULL);
  217.  
  218.         }
  219.  
  220.         if (gr_ugpixel(&grd_curcanv->cv_bitmap,Search_x,Search_y) == 1)
  221.             if (N_found_segs < MAX_FOUND_SEGS)
  222.                 Found_segs[N_found_segs++] = SEG_PTR_2_NUM(seg);
  223.             else
  224.                 Warning("Found too many segs! (limit=%d)",MAX_FOUND_SEGS);
  225.         
  226.     }
  227. }
  228.  
  229. // ----------------------------------------------------------------------------
  230. void draw_seg_side(segment *seg,int side)
  231. {
  232.     short    *svp;
  233.     int    nv;
  234.     g3s_codes cc;
  235.  
  236.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  237.     cc=rotate_list(nv,svp);
  238.  
  239.     if (! cc.and) {        //all off screen?
  240.         int i;
  241.  
  242.         for (i=0;i<3;i++)
  243.             draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][i+1]]);
  244.  
  245.         draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][0]]);
  246.  
  247.     }
  248. }
  249.  
  250. void draw_side_edge(segment *seg,int side,int edge)
  251. {
  252.     short    *svp;
  253.     int    nv;
  254.     g3s_codes cc;
  255.  
  256.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  257.     cc=rotate_list(nv,svp);
  258.  
  259.     if (! cc.and)        //on screen?
  260.         draw_line(svp[Side_to_verts[side][edge]],svp[Side_to_verts[side][(edge+1)%4]]);
  261. }
  262.  
  263. int Show_triangulations=0;
  264.  
  265. //edge types - lower number types have precedence
  266. #define ET_FACING        0    //this edge on a facing face
  267. #define ET_NOTFACING    1    //this edge on a non-facing face
  268. #define ET_NOTUSED    2    //no face uses this edge
  269. #define ET_NOTEXTANT    3    //would exist if side were triangulated 
  270.  
  271. #define ET_EMPTY        255    //this entry in array is empty
  272.  
  273. //colors for those types
  274. //int edge_colors[] = {BM_RGB(45/2,45/2,45/2),
  275. //                            BM_RGB(45/3,45/3,45/3),        //BM_RGB(0,0,45),    //
  276. //                            BM_RGB(45/4,45/4,45/4)};    //BM_RGB(0,45,0)};    //
  277.  
  278. int edge_colors[] = { 54, 59, 64 };
  279.                             
  280.  
  281. typedef struct seg_edge {
  282.     union {
  283.         struct {short v0,v1;};
  284.         long vv;
  285.     };
  286.     ushort    type;
  287.     ubyte        face_count, backface_count;
  288. } seg_edge;
  289.  
  290. #define MAX_EDGES (MAX_VERTICES*4)
  291.  
  292. seg_edge edge_list[MAX_EDGES];
  293.  
  294. short    used_list[MAX_EDGES];    //which entries in edge_list have been used
  295. int n_used;
  296.  
  297. int edge_list_size;        //set each frame
  298.  
  299. #define HASH(a,b)  ((a*5+b) % edge_list_size)
  300.  
  301. //define edge numberings
  302. short edges[] = {
  303.         0*8+1,    // edge  0
  304.         0*8+3,    // edge  1
  305.         0*8+4,    // edge  2
  306.         1*8+2,    // edge  3
  307.         1*8+5,    //    edge  4
  308.         2*8+3,    //    edge  5
  309.         2*8+6,    //    edge  6
  310.         3*8+7,    //    edge  7
  311.         4*8+5,    //    edge  8
  312.         4*8+7,    //    edge  9
  313.         5*8+6,    //    edge 10
  314.         6*8+7,    //    edge 11
  315.  
  316.         0*8+5,    //    right cross
  317.         0*8+7,    // top cross
  318.         1*8+3,    //    front  cross
  319.         2*8+5,    // bottom cross
  320.         2*8+7,    // left cross
  321.         4*8+6,    //    back cross
  322.  
  323. //crosses going the other way
  324.  
  325.         1*8+4,    //    other right cross
  326.         3*8+4,    // other top cross
  327.         0*8+2,    //    other front  cross
  328.         1*8+6,    // other bottom cross
  329.         3*8+6,    // other left cross
  330.         5*8+7,    //    other back cross
  331. };
  332.  
  333. #define N_NORMAL_EDGES            12        //the normal edges of a box
  334. #define N_EXTRA_EDGES            12        //ones created by triangulation
  335. #define N_EDGES_PER_SEGMENT (N_NORMAL_EDGES+N_EXTRA_EDGES)
  336.  
  337. #define swap(a,b) do {int t; t=(a); (a)=(b); (b)=t;} while (0)
  338.  
  339. //given two vertex numbers on a segment (range 0..7), tell what edge number it is
  340. int find_edge_num(int v0,int v1)
  341. {
  342.     int        i;
  343.     short        vv;
  344.     short        *edgep = edges;
  345.  
  346.     if (v0 > v1) swap(v0,v1);
  347.  
  348.     vv = v0*8+v1;
  349.  
  350. //    for (i=0;i<N_EDGES_PER_SEGMENT;i++)
  351. //        if (edges[i]==vv) return i;
  352.  
  353.     for (i=N_EDGES_PER_SEGMENT; i; i--)
  354.         if (*edgep++ == vv)
  355.             return (N_EDGES_PER_SEGMENT-i);
  356.  
  357.     Error("couldn't find edge for %d,%d",v0,v1);
  358.  
  359.     //return -1;
  360. }
  361.  
  362.  
  363. //finds edge, filling in edge_ptr. if found old edge, returns index, else return -1
  364. int find_edge(int v0,int v1,seg_edge **edge_ptr)
  365. {
  366.     long vv;
  367.     short hash,oldhash;
  368.     int ret;
  369.  
  370.     vv = (v1<<16) + v0;
  371.  
  372.     oldhash = hash = HASH(v0,v1);
  373.  
  374.     ret = -1;
  375.  
  376.     while (ret==-1) {
  377.  
  378.         if (edge_list[hash].type == ET_EMPTY) ret=0;
  379.         else if (edge_list[hash].vv == vv) ret=1;
  380.         else {
  381.             if (++hash==edge_list_size) hash=0;
  382.             if (hash==oldhash) Error("Edge list full!");
  383.         }
  384.     }
  385.  
  386.     *edge_ptr = &edge_list[hash];
  387.  
  388.     if (ret == 0)
  389.         return -1;
  390.     else
  391.         return hash;
  392.  
  393. }
  394.  
  395. //adds an edge to the edge list
  396. add_edge(int v0,int v1,ubyte type)
  397. {
  398.     int found;
  399.  
  400.     seg_edge *e;
  401.  
  402. //mprintf(0, "Verts = %2i %2i, type = %i ", v0, v1, type);
  403.     if (v0 > v1) swap(v0,v1);
  404.  
  405.     found = find_edge(v0,v1,&e);
  406.  
  407.     if (found == -1) {
  408.         e->v0 = v0;
  409.         e->v1 = v1;
  410.         e->type = type;
  411.         used_list[n_used] = e-edge_list;
  412.         if (type == ET_FACING)
  413.             edge_list[used_list[n_used]].face_count++;
  414.         else if (type == ET_NOTFACING)
  415.             edge_list[used_list[n_used]].backface_count++;
  416. //mprintf(0, "Facing count = %i, Not facing count = %i\n", edge_list[used_list[n_used]].face_count, edge_list[used_list[n_used]].backface_count);
  417.         n_used++;
  418.     } else {
  419.         if (type < e->type)
  420.             e->type = type;
  421.         if (type == ET_FACING)
  422.             edge_list[found].face_count++;
  423.         else if (type == ET_NOTFACING)
  424.             edge_list[found].backface_count++;
  425. //mprintf(0, "Facing count = %i, Not facing count = %i\n", edge_list[found].face_count, edge_list[found].backface_count);
  426.     }
  427. }
  428.  
  429. //adds a segment's edges to the edge list
  430. void add_edges(segment *seg)
  431. {
  432.     short    *svp;
  433.     int    nv;
  434.     g3s_codes cc;
  435.  
  436.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  437.     cc=rotate_list(nv,svp);
  438.  
  439.     if (! cc.and) {        //all off screen?
  440.         int    i,sn,fn,vn;
  441.         int    flag;
  442.         ubyte    edge_flags[N_EDGES_PER_SEGMENT];
  443.  
  444.         for (i=0;i<N_NORMAL_EDGES;i++) edge_flags[i]=ET_NOTUSED;
  445.         for (;i<N_EDGES_PER_SEGMENT;i++) edge_flags[i]=ET_NOTEXTANT;
  446.  
  447.         for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  448.             side    *sidep = &seg->sides[sn];
  449.             int    num_faces, num_vertices;
  450.             int    vertex_list[6];
  451.  
  452.             create_all_vertex_lists(&num_faces, vertex_list, seg-Segments, sn);
  453.             if (num_faces == 1)
  454.                 num_vertices = 4;
  455.             else
  456.                 num_vertices = 3;
  457.  
  458.             for (fn=0; fn<num_faces; fn++) {
  459.                 int    en;
  460.                 int    *v0;
  461.  
  462.                 //Note: normal check appears to be the wrong way since the normals points in, but we're looking from the outside
  463.                 if (g3_check_normal_facing(&Vertices[seg->verts[vertex_list[fn*3]]],&sidep->normals[fn]))
  464.                     flag = ET_NOTFACING;
  465.                 else
  466.                     flag = ET_FACING;
  467.  
  468.                 v0 = &vertex_list[fn*3];
  469.  
  470.                 for (vn=0; vn<num_vertices-1; vn++) {
  471.  
  472.                     // en = find_edge_num(vertex_list[fn*3 + vn], vertex_list[fn*3 + (vn+1)%num_vertices]);
  473.                     en = find_edge_num(*v0, *(v0+1));
  474.                     
  475.                     if (en!=-1)
  476.                         if (flag < edge_flags[en]) edge_flags[en] = flag;
  477.  
  478.                     v0++;
  479.                 }
  480.                 en = find_edge_num(*v0, vertex_list[fn*3]);
  481.                 if (en!=-1)
  482.                     if (flag < edge_flags[en]) edge_flags[en] = flag;
  483.             }
  484.         }
  485.  
  486.         for (i=0; i<N_EDGES_PER_SEGMENT; i++)
  487.             if (i<N_NORMAL_EDGES || (edge_flags[i]!=ET_NOTEXTANT && Show_triangulations))
  488.                 add_edge(seg->verts[edges[i]/8],seg->verts[edges[i]&7],edge_flags[i]);
  489.         
  490.  
  491.     }
  492. }
  493.  
  494. // ----------------------------------------------------------------------------
  495. void draw_trigger_side(segment *seg,int side)
  496. {
  497.     short    *svp;
  498.     int    nv;
  499.     g3s_codes cc;
  500.  
  501.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  502.     cc=rotate_list(nv,svp);
  503.  
  504.     if (! cc.and) {        //all off screen?
  505.         // Draw diagonals
  506.         draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]);
  507.         //g3_draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]);
  508.     }
  509. }
  510.  
  511. // ----------------------------------------------------------------------------
  512. void draw_wall_side(segment *seg,int side)
  513. {
  514.     short    *svp;
  515.     int    nv;
  516.     g3s_codes cc;
  517.  
  518.     med_get_vertex_list(seg,&nv,&svp);                // set nv = number of vertices, svp = pointer to vertex indices
  519.     cc=rotate_list(nv,svp);
  520.  
  521.     if (! cc.and) {        //all off screen?
  522.         // Draw diagonals
  523.         draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]);
  524.         draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]);
  525.  
  526.     }
  527. }
  528.  
  529. #define    WALL_BLASTABLE_COLOR                BM_XRGB( 31/2 ,  0/2 ,  0/2)  // RED
  530. #define    WALL_DOOR_COLOR                    BM_XRGB(  0/2 ,  0/2 , 31/2)    // DARK BLUE
  531. #define    WALL_DOOR_LOCKED_COLOR            BM_XRGB(  0/2 ,  0/2 , 63/2)    // BLUE
  532. #define    WALL_AUTO_DOOR_COLOR                BM_XRGB(  0/2 , 31/2 ,  0/2)    //    DARK GREEN
  533. #define    WALL_AUTO_DOOR_LOCKED_COLOR    BM_XRGB(  0/2 , 63/2 ,  0/2)    // GREEN
  534. #define    WALL_ILLUSION_COLOR                BM_XRGB( 63/2 ,  0/2 , 63/2)    // PURPLE
  535.  
  536. #define    TRIGGER_COLOR                        BM_XRGB( 63/2 , 63/2 ,  0/2)    // YELLOW
  537. #define    TRIGGER_DAMAGE_COLOR                BM_XRGB( 63/2 , 63/2 ,  0/2)    // YELLOW
  538.  
  539. // ----------------------------------------------------------------------------------------------------------------
  540. // Draws special walls (for now these are just removable walls.)
  541. void draw_special_wall( segment *seg, int side )
  542. {
  543.     gr_setcolor(PLAINSEG_COLOR);
  544.  
  545.     if (Walls[seg->sides[side].wall_num].type == WALL_BLASTABLE)
  546.         gr_setcolor(WALL_BLASTABLE_COLOR);    
  547.     if (Walls[seg->sides[side].wall_num].type == WALL_DOOR)
  548.         gr_setcolor(WALL_DOOR_COLOR);
  549.     if (Walls[seg->sides[side].wall_num].type == WALL_ILLUSION)
  550.         gr_setcolor(GROUPSIDE_COLOR);    
  551.     if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED)
  552.         gr_setcolor(WALL_DOOR_LOCKED_COLOR);
  553.     if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO)
  554.         gr_setcolor(WALL_AUTO_DOOR_COLOR);
  555.     if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED)
  556.     if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO)
  557.         gr_setcolor(WALL_AUTO_DOOR_LOCKED_COLOR);
  558.     if (Walls[seg->sides[side].wall_num].type == WALL_OPEN)
  559.         gr_setcolor(PLAINSEG_COLOR);
  560.     
  561.     draw_wall_side(seg,side);
  562.  
  563.     if (Walls[seg->sides[side].wall_num].trigger != -1) {
  564.         int trigger_num;
  565.  
  566.         trigger_num = Walls[seg->sides[side].wall_num].trigger;
  567.  
  568.         gr_setcolor(TRIGGER_COLOR);
  569.         draw_trigger_side(seg,side);
  570.         }
  571.  
  572.  
  573.     gr_setcolor(PLAINSEG_COLOR);
  574. }
  575.  
  576.  
  577. // ----------------------------------------------------------------------------------------------------------------
  578. // Recursively parse mine structure, drawing segments.
  579. void draw_mine_sub(int segnum,int depth)
  580. {
  581.     segment *mine_ptr;
  582.  
  583.     if (Been_visited[segnum]) return;        // If segment already drawn, return.
  584.  
  585.     Been_visited[segnum] = 1;        // Say that this segment has been drawn.
  586.  
  587.     mine_ptr = &Segments[segnum];
  588.  
  589.     // If this segment is active, process it, else skip it.
  590.  
  591.     if (mine_ptr->segnum != -1) {
  592.         int    side;
  593.  
  594.         if (Search_mode) check_segment(mine_ptr);
  595.         else add_edges(mine_ptr);    //add this segments edges to list
  596.  
  597.         if (depth != 0) {
  598.             for (side=0; side<MAX_SIDES_PER_SEGMENT; side++) {
  599.                 if (IS_CHILD(mine_ptr->children[side])) {
  600.                     if (mine_ptr->sides[side].wall_num != -1)
  601.                         draw_special_wall(mine_ptr, side);
  602.                     draw_mine_sub(mine_ptr->children[side],depth-1);
  603.                 }
  604.             }
  605.         }
  606.     }
  607. }
  608.  
  609. draw_edges(int automap_flag)
  610. {
  611.     int i,type;
  612.     seg_edge *e;
  613.  
  614.     for (type=ET_NOTUSED;type>=ET_FACING;type--) {
  615.         gr_setcolor(edge_colors[type]);
  616.         for (i=0;i<n_used;i++) {
  617.             e = &edge_list[used_list[i]];
  618.             if (e->type == type)
  619.                 if ((!automap_flag) || (e->face_count == 1))
  620.                     draw_line(e->v0,e->v1);
  621.         }
  622.     }
  623. }
  624.  
  625. //draws an entire mine
  626. void draw_mine(segment *mine_ptr,int depth)
  627. {
  628.     int    i;
  629.  
  630.     // clear visited list
  631.     for (i=0; i<=Highest_segment_index; i++)
  632.         Been_visited[i] = 0;
  633.  
  634.     edge_list_size = min(Num_vertices*4,MAX_EDGES);        //make maybe smaller than max
  635.  
  636.     // clear edge list
  637.     for (i=0; i<edge_list_size; i++) {
  638.         edge_list[i].type = ET_EMPTY;
  639.         edge_list[i].face_count = 0;
  640.         edge_list[i].backface_count = 0;
  641.     }
  642.  
  643.     n_used = 0;
  644.  
  645.     draw_mine_sub(SEG_PTR_2_NUM(mine_ptr),depth);
  646.  
  647.     draw_edges(0);
  648.  
  649. }
  650.  
  651. // -----------------------------------------------------------------------------
  652. //    Draw all segments, ignoring connectivity.
  653. //    A segment is drawn if its segnum != -1.
  654. void draw_mine_all(segment *sp, int automap_flag)
  655. {
  656.     int    s;
  657.     int    i;
  658.  
  659.     // clear visited list
  660.     for (i=0; i<=Highest_segment_index; i++)
  661.         Been_visited[i] = 0;
  662.  
  663.     edge_list_size = min(Num_vertices*4,MAX_EDGES);        //make maybe smaller than max
  664.  
  665.     // clear edge list
  666.     for (i=0; i<edge_list_size; i++) {
  667.         edge_list[i].type = ET_EMPTY;
  668.         edge_list[i].face_count = 0;
  669.         edge_list[i].backface_count = 0;
  670.     }
  671.  
  672.     n_used = 0;
  673.  
  674.     for (s=0; s<=Highest_segment_index; s++)
  675.         if (sp[s].segnum != -1) {
  676.             for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
  677.                 if (sp[s].sides[i].wall_num != -1)
  678.                     draw_special_wall(&sp[s], i);
  679.             if (Search_mode)
  680.                 check_segment(&sp[s]);
  681.             else {
  682.                 add_edges(&sp[s]);
  683.                 draw_seg_objects(&sp[s]);
  684.             }
  685.         }
  686.  
  687.     draw_edges(automap_flag);
  688.  
  689. }
  690.  
  691. void draw_selected_segments(void)
  692. {
  693.     int    s;
  694.  
  695.     gr_setcolor(SELECT_COLOR);
  696.     for (s=0; s<N_selected_segs; s++)
  697.         if (Segments[Selected_segs[s]].segnum != -1)
  698.             draw_segment(&Segments[Selected_segs[s]]);
  699. }
  700.  
  701. void draw_found_segments(void)
  702. {
  703.     int    s;
  704.  
  705.     gr_setcolor(FOUND_COLOR);
  706.     for (s=0; s<N_found_segs; s++)
  707.         if (Segments[Found_segs[s]].segnum != -1)
  708.             draw_segment(&Segments[Found_segs[s]]);
  709. }
  710.  
  711. void draw_warning_segments(void)
  712. {
  713.     int    s;
  714.  
  715.     gr_setcolor(WARNING_COLOR);
  716.     for (s=0; s<N_warning_segs; s++)
  717.         if (Segments[Warning_segs[s]].segnum != -1)
  718.             draw_segment(&Segments[Warning_segs[s]]);
  719. }
  720.  
  721. void draw_group_segments(void)
  722. {
  723.     int    s;
  724.  
  725.     if (current_group > -1) {
  726.         gr_setcolor(GROUP_COLOR);
  727.         for (s=0; s<GroupList[current_group].num_segments; s++)
  728.             if (Segments[GroupList[current_group].segments[s]].segnum != -1)
  729.                 draw_segment(&Segments[GroupList[current_group].segments[s]]);
  730.         }
  731. }
  732.  
  733.  
  734. void draw_special_segments(void)
  735. {
  736.     short seg;
  737.     ubyte color;
  738.  
  739.     // Highlight matcens, fuelcens, etc.
  740.     for (seg=0;seg<=Highest_segment_index;seg++)
  741.         if (Segments[seg].segnum != -1)
  742.             switch( Segments[seg].special )    {
  743.             case SEGMENT_IS_FUELCEN:
  744.                 color = BM_XRGB( 29, 27, 13 );
  745.                 gr_setcolor(color);
  746.                 draw_segment(&Segments[seg]);
  747.                 break;
  748.             case SEGMENT_IS_CONTROLCEN:
  749.                 color = BM_XRGB( 29, 0, 0 );
  750.                 gr_setcolor(color);
  751.                 draw_segment(&Segments[seg]);
  752.                 break;
  753.             case SEGMENT_IS_ROBOTMAKER:
  754.                 color = BM_XRGB( 29, 0, 31 );
  755.                 gr_setcolor(color);
  756.                 draw_segment(&Segments[seg]);
  757.                 break;
  758.             }
  759. }
  760.         
  761.  
  762. //find a free vertex. returns the vertex number
  763. int alloc_vert()
  764. {
  765.     int vn;
  766.  
  767.     Assert(Num_vertices < MAX_SEGMENT_VERTICES);
  768.  
  769.     for (vn=0; (vn < Num_vertices) && Vertex_active[vn]; vn++) ;
  770.  
  771.     Vertex_active[vn] = 1;
  772.  
  773.     Num_vertices++;
  774.  
  775.     return vn;
  776. }
  777.  
  778. //frees a vertex
  779. void free_vert(int vert_num)
  780. {
  781.     Vertex_active[vert_num] = 0;
  782.     Num_vertices--;
  783. }
  784.  
  785. // -----------------------------------------------------------------------------
  786. void draw_coordinate_axes(void)
  787. {
  788.     int            i;
  789.     short            Axes_verts[16];
  790.     vms_vector    tvec,xvec,yvec,zvec;
  791.  
  792.     for (i=0; i<16; i++)
  793.         Axes_verts[i] = alloc_vert();
  794.  
  795.     create_coordinate_axes_from_segment(Cursegp,Axes_verts);
  796.  
  797.     vm_vec_sub(&xvec,&Vertices[Axes_verts[1]],&Vertices[Axes_verts[0]]);
  798.     vm_vec_sub(&yvec,&Vertices[Axes_verts[2]],&Vertices[Axes_verts[0]]);
  799.     vm_vec_sub(&zvec,&Vertices[Axes_verts[3]],&Vertices[Axes_verts[0]]);
  800.  
  801.     // Create the letter X
  802.     tvec = xvec;
  803.     vm_vec_add(&Vertices[Axes_verts[4]],&Vertices[Axes_verts[1]],vm_vec_scale(&tvec,F1_0/16));
  804.     tvec = yvec;
  805.     vm_vec_add2(&Vertices[Axes_verts[4]],vm_vec_scale(&tvec,F1_0/8));
  806.     vm_vec_sub(&Vertices[Axes_verts[6]],&Vertices[Axes_verts[4]],vm_vec_scale(&tvec,F2_0));
  807.     tvec = xvec;    vm_vec_scale(&tvec,F1_0/8);
  808.     vm_vec_add(&Vertices[Axes_verts[7]],&Vertices[Axes_verts[4]],&tvec);
  809.     vm_vec_add(&Vertices[Axes_verts[5]],&Vertices[Axes_verts[6]],&tvec);
  810.  
  811.     //    Create the letter Y
  812.     tvec = yvec;
  813.     vm_vec_add(&Vertices[Axes_verts[11]],&Vertices[Axes_verts[2]],vm_vec_scale(&tvec,F1_0/16));
  814.     vm_vec_add(&Vertices[Axes_verts[8]],&Vertices[Axes_verts[11]],&tvec);
  815.     vm_vec_add(&Vertices[Axes_verts[9]],&Vertices[Axes_verts[11]],vm_vec_scale(&tvec,F1_0*2));
  816.     vm_vec_add(&Vertices[Axes_verts[10]],&Vertices[Axes_verts[11]],&tvec);
  817.     tvec = xvec;    vm_vec_scale(&tvec,F1_0/16);
  818.     vm_vec_sub2(&Vertices[Axes_verts[9]],&tvec);
  819.     vm_vec_add2(&Vertices[Axes_verts[10]],&tvec);
  820.  
  821.     // Create the letter Z
  822.     tvec = zvec;
  823.     vm_vec_add(&Vertices[Axes_verts[12]],&Vertices[Axes_verts[3]],vm_vec_scale(&tvec,F1_0/16));
  824.     tvec = yvec;
  825.     vm_vec_add2(&Vertices[Axes_verts[12]],vm_vec_scale(&tvec,F1_0/8));
  826.     vm_vec_sub(&Vertices[Axes_verts[14]],&Vertices[Axes_verts[12]],vm_vec_scale(&tvec,F2_0));
  827.     tvec = zvec;    vm_vec_scale(&tvec,F1_0/8);
  828.     vm_vec_add(&Vertices[Axes_verts[13]],&Vertices[Axes_verts[12]],&tvec);
  829.     vm_vec_add(&Vertices[Axes_verts[15]],&Vertices[Axes_verts[14]],&tvec);
  830.  
  831.     rotate_list(16,Axes_verts);
  832.  
  833.     gr_setcolor(AXIS_COLOR);
  834.  
  835.     draw_line(Axes_verts[0],Axes_verts[1]);
  836.     draw_line(Axes_verts[0],Axes_verts[2]);
  837.     draw_line(Axes_verts[0],Axes_verts[3]);
  838.  
  839.     // draw the letter X
  840.     draw_line(Axes_verts[4],Axes_verts[5]);
  841.     draw_line(Axes_verts[6],Axes_verts[7]);
  842.  
  843.     // draw the letter Y
  844.     draw_line(Axes_verts[8],Axes_verts[9]);
  845.     draw_line(Axes_verts[8],Axes_verts[10]);
  846.     draw_line(Axes_verts[8],Axes_verts[11]);
  847.  
  848.     // draw the letter Z
  849.     draw_line(Axes_verts[12],Axes_verts[13]);
  850.     draw_line(Axes_verts[13],Axes_verts[14]);
  851.     draw_line(Axes_verts[14],Axes_verts[15]);
  852.  
  853.     for (i=0; i<16; i++)
  854.         free_vert(Axes_verts[i]);
  855. }
  856.  
  857. void draw_world(grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth)
  858. {
  859.     vms_vector viewer_position;
  860.  
  861. #if DOUBLE_BUFFER
  862.     grs_canvas temp_canvas;
  863.  
  864. //    mprintf(0, "\n");
  865.  
  866. //    if ( screen_canvas == LargeViewBox->canvas ) {
  867. //        CurrentBigCanvas ^= 1;
  868. //
  869. //        gr_set_current_canvas( BigCanvas[CurrentBigCanvas] );
  870. //
  871. //    } else {
  872.         gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0,
  873.             screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h);
  874.  
  875.         gr_set_current_canvas(&temp_canvas);
  876. //    }
  877. #else
  878.     gr_set_current_canvas(screen_canvas);
  879. #endif
  880.  
  881.     //mprintf(0, "\n");
  882.  
  883.     ui_mouse_hide();
  884.  
  885.     //g3_set_points(Segment_points,Vertices);
  886.  
  887.     viewer_position = v->ev_matrix.fvec;
  888.     vm_vec_scale(&viewer_position,-v->ev_dist);
  889.  
  890.     vm_vec_add2(&viewer_position,&Ed_view_target);
  891.  
  892.     gr_clear_canvas(0);
  893.     g3_start_frame();
  894.     g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom);
  895.  
  896.     render_start_frame();
  897.  
  898.     gr_setcolor(PLAINSEG_COLOR);
  899.  
  900.     // Draw all segments or only connected segments.
  901.     // We might want to draw all segments if we have broken the mine into pieces.
  902.     if (Draw_all_segments)
  903.         draw_mine_all(Segments, Automap_test);
  904.     else
  905.         draw_mine(mine_ptr,depth);
  906.  
  907.     // Draw the found segments
  908.     if (!Automap_test) {
  909.         draw_warning_segments();
  910.         draw_group_segments();
  911.         draw_found_segments();
  912.         draw_selected_segments();
  913.         draw_special_segments();
  914.  
  915.         // Highlight group segment and side.
  916.         if (current_group > -1)
  917.         if (Groupsegp[current_group]) {
  918.             gr_setcolor(GROUPSEG_COLOR);
  919.             draw_segment(Groupsegp[current_group]);
  920.  
  921.             gr_setcolor(GROUPSIDE_COLOR);
  922.             draw_seg_side(Groupsegp[current_group],Groupside[current_group]);
  923.         }
  924.  
  925.         // Highlight marked segment and side.
  926.         if (Markedsegp) {
  927.             gr_setcolor(MARKEDSEG_COLOR);
  928.             draw_segment(Markedsegp);
  929.  
  930.             gr_setcolor(MARKEDSIDE_COLOR);
  931.             draw_seg_side(Markedsegp,Markedside);
  932.         }
  933.  
  934.         // Highlight current segment and current side.
  935.         gr_setcolor(CURSEG_COLOR);
  936.         draw_segment(Cursegp);
  937.  
  938.         gr_setcolor(CURSIDE_COLOR);
  939.         draw_seg_side(Cursegp,Curside);
  940.  
  941.         gr_setcolor(CUREDGE_COLOR);
  942.         draw_side_edge(Cursegp,Curside,Curedge);
  943.  
  944.         // Draw coordinate axes if we are rendering the large view.
  945.         if (Show_axes_flag)
  946.             if (screen_canvas == LargeViewBox->canvas)
  947.                 draw_coordinate_axes();
  948.  
  949.         // Label the window
  950.         gr_set_fontcolor((v==current_view)?CRED:CWHITE, -1 );
  951.         if ( screen_canvas == LargeViewBox->canvas ) {
  952.             gr_ustring( 5, 5, "USER VIEW" );
  953.             switch (Large_view_index) {
  954.                 case 0: gr_ustring( 85, 5, "-- TOP");    break;
  955.                 case 1: gr_ustring( 85, 5, "-- FRONT");    break;
  956.                 case 2: gr_ustring( 85, 5, "-- RIGHT");    break;
  957.             }            
  958.         } else
  959. #if ORTHO_VIEWS
  960.          else if ( screen_canvas == TopViewBox->canvas )
  961.             gr_ustring( 5, 5, "TOP" );
  962.         else if ( screen_canvas == FrontViewBox->canvas )
  963.             gr_ustring( 5, 5, "FRONT" );
  964.         else if ( screen_canvas == RightViewBox->canvas )
  965.             gr_ustring( 5, 5, "RIGHT" );
  966. #else
  967.             Error("Ortho views have been removed, what gives?\n");
  968. #endif
  969.  
  970.     }
  971.  
  972.     g3_end_frame();
  973.  
  974. #if DOUBLE_BUFFER
  975. //    if ( screen_canvas == LargeViewBox->canvas ) {
  976. //        if (BigCanvasFirstTime)    {
  977. //            BigCanvasFirstTime = 0;
  978. //            gr_set_current_canvas( screen_canvas );
  979. //            gr_ubitmap( 0, 0, &BigCanvas[CurrentBigCanvas]->cv_bitmap );
  980. //        } else {
  981. //            gr_vesa_update( &BigCanvas[CurrentBigCanvas]->cv_bitmap, &screen_canvas->cv_bitmap, &BigCanvas[CurrentBigCanvas ^ 1]->cv_bitmap );
  982. //        }
  983. //    } else {
  984.         gr_set_current_canvas( screen_canvas );
  985.         gr_ubitmap( 0, 0, &temp_canvas.cv_bitmap );
  986. //    }
  987.  
  988. #endif
  989.  
  990.     ui_mouse_show();
  991.  
  992. }
  993.  
  994. //find the segments that render at a given screen x,y
  995. //parms other than x,y are like draw_world
  996. //fills in globals N_found_segs & Found_segs
  997. void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth)
  998. {
  999.     vms_vector viewer_position;
  1000.  
  1001. #if DOUBLE_BUFFER
  1002.     grs_canvas temp_canvas;
  1003.  
  1004.     gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0,
  1005.             screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h);
  1006.  
  1007.     gr_set_current_canvas(&temp_canvas);
  1008. #else
  1009.     gr_set_current_canvas(screen_canvas);
  1010. #endif
  1011.  
  1012.     ui_mouse_hide();
  1013.  
  1014.     //g3_set_points(Segment_points,Vertices);
  1015.  
  1016.     viewer_position = v->ev_matrix.fvec;
  1017.     vm_vec_scale(&viewer_position,-v->ev_dist);
  1018.  
  1019.     vm_vec_add(&viewer_position,&viewer_position,&Ed_view_target);
  1020.  
  1021.     g3_start_frame();
  1022.     g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom);
  1023.  
  1024.     render_start_frame();
  1025.  
  1026.     gr_setcolor(0);
  1027.     gr_pixel(x,y);
  1028.     gr_setcolor(1);
  1029.  
  1030.     Search_mode = -1;
  1031.     N_found_segs = 0;
  1032.     Search_x = x; Search_y = y;
  1033.  
  1034.     if (Draw_all_segments)
  1035.         draw_mine_all(Segments, 0);
  1036.     else
  1037.         draw_mine(mine_ptr,depth);
  1038.  
  1039.     g3_end_frame();
  1040.  
  1041.     Search_mode = 0;
  1042.  
  1043. }
  1044.  
  1045. void meddraw_init_views( grs_canvas * canvas)
  1046. {
  1047.     Views[0]->ev_canv = canvas;
  1048. #if ORTHO_VIEWS
  1049.     Views[1]->ev_canv = TopViewBox->canvas;
  1050.     Views[2]->ev_canv = FrontViewBox->canvas;
  1051.     Views[3]->ev_canv = RightViewBox->canvas;
  1052. #endif
  1053. }
  1054.