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

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