/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * $Source: /cvsroot/dxx-rebirth/d1x-rebirth/editor/meddraw.c,v $ * $Revision: 1.1.1.1 $ * $Author: zicodxx $ * $Date: 2006/03/17 19:45:27 $ * * Med drawing functions. * * $Log: meddraw.c,v $ * Revision 1.1.1.1 2006/03/17 19:45:27 zicodxx * initial import * * Revision 1.1.1.1 1999/06/14 22:03:50 donut * Import of d1x 1.37 source. * * Revision 2.0 1995/02/27 11:34:42 john * Version 2.0! No anonymous unions, Watcom 10.0, with no need * for bitmaps.tbl. * * Revision 1.34 1994/11/09 11:46:30 matt * Don't draw non-existant special segments * * Revision 1.33 1994/10/27 10:06:38 mike * adapt to no inverse table. * * Revision 1.32 1994/10/17 18:06:23 john * Made net player objects draw in dark green. * * Revision 1.31 1994/09/26 16:44:33 yuan * Colored special segments. * * Revision 1.30 1994/09/01 17:02:41 matt * Redraw pointer after world draw * * Revision 1.29 1994/08/25 21:56:21 mike * IS_CHILD stuff. * * Revision 1.28 1994/08/11 18:59:46 mike * Adapt to new int (vs short) version of gameseg functions. * * Revision 1.27 1994/08/09 16:06:03 john * Added the ability to place players. Made old * Player variable be ConsoleObject. * * Revision 1.26 1994/07/25 00:03:05 matt * Various changes to accomodate new 3d, which no longer takes point numbers * as parms, and now only takes pointers to points. * * Revision 1.25 1994/07/09 17:38:13 mike * comment out mprintf(0, "\n"); * * Revision 1.24 1994/07/07 19:34:47 matt * These changes are mostly Mike's, but I fixed a little bug that caused * some edges to think they were never used. * * Revision 1.23 1994/07/06 16:36:18 mike * Optionally only draw segment lines which are in only one segment. * * Revision 1.22 1994/05/27 10:34:28 yuan * Added new Dialog boxes for Walls and Triggers. * * Revision 1.21 1994/05/14 18:00:56 matt * Got rid of externs in source (non-header) files * * Revision 1.20 1994/05/09 23:35:21 mike * Change order of drawing found and selected segments. * * Revision 1.19 1994/05/05 12:55:38 yuan * Fixed a bunch of group bugs. * * Revision 1.18 1994/05/04 13:07:52 matt * Made current edge draw in green in wire-frame window * Also, moved a bunch of color constants here from editor.h * */ #ifdef RCS static char rcsid[] = "$Id: meddraw.c,v 1.1.1.1 2006/03/17 19:45:27 zicodxx Exp $"; #endif #include #include #include #include #ifdef __MSDOS__ #include #endif #include "inferno.h" #include "segment.h" #include "segpoint.h" #include "gameseg.h" #include "gr.h" #include "ui.h" #include "editor/editor.h" #include "wall.h" #include "switch.h" #include "key.h" #include "mono.h" #include "error.h" #include "medlisp.h" #include "u_mem.h" #include "render.h" #include "game.h" //#include "slew.h" #include "kdefs.h" #include "func.h" #include "textures.h" #include "screens.h" #include "texmap.h" #include "object.h" #include "fuelcen.h" // Colors used in editor for indicating various kinds of segments. #define SELECT_COLOR BM_XRGB( 63/2 , 41/2 , 0/2) #define FOUND_COLOR BM_XRGB( 0/2 , 30/2 , 45/2) #define WARNING_COLOR BM_XRGB( 63/2 , 0/2 , 0/2) #define AXIS_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) #define PLAINSEG_COLOR BM_XRGB( 45/2 , 45/2 , 45/2) #define MARKEDSEG_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) #define MARKEDSIDE_COLOR BM_XRGB( 0/2 , 63/2 , 63/2) #define CURSEG_COLOR BM_XRGB( 63/2 , 63/2 , 63/2) #define CURSIDE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) #define CUREDGE_COLOR BM_XRGB( 0 , 63/2 , 0 ) #define GROUPSEG_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) #define GROUPSIDE_COLOR BM_XRGB( 63/2 , 0/2 , 45/2) #define GROUP_COLOR BM_XRGB( 0/2 , 45/2 , 0/2) #define ROBOT_COLOR BM_XRGB( 31 , 0 , 0 ) #define PLAYER_COLOR BM_XRGB( 0 , 0 , 31 ) #define DOUBLE_BUFFER 1 int Search_mode=0; //if true, searching for segments at given x,y int Search_x,Search_y; int Automap_test=0; // Set to 1 to show wireframe in automap mode. void draw_seg_objects(segment *seg) { int objnum; for (objnum=seg->objects;objnum!=-1;objnum=Objects[objnum].next) { object *obj = &Objects[objnum]; g3s_point sphere_point; if ((obj->type==OBJ_PLAYER) && (objnum > 0 )) gr_setcolor(BM_XRGB( 0, 25, 0 )); else gr_setcolor(obj==ConsoleObject?PLAYER_COLOR:ROBOT_COLOR); g3_rotate_point(&sphere_point,&obj->pos); g3_draw_sphere(&sphere_point,obj->size); } } void draw_line(int pnum0,int pnum1) { g3_draw_line(&Segment_points[pnum0],&Segment_points[pnum1]); } // ---------------------------------------------------------------------------- void draw_segment(segment *seg) { short *svp; int nv; g3s_codes cc; if (seg->segnum == -1) //this segment doesn't exitst return; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? int i; for (i=0;i<4;i++) draw_line(svp[i],svp[i+4]); for (i=0;i<3;i++) { draw_line(svp[i] ,svp[i+1]); draw_line(svp[i+4],svp[i+4+1]); } draw_line(svp[0],svp[3]); draw_line(svp[0+4],svp[3+4]); } } //for looking for segment under a mouse click void check_segment(segment *seg) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? int fn; gr_setcolor(0); gr_pixel(Search_x,Search_y); //set our search pixel to color zero gr_setcolor(1); //and render in color one for (fn=0;fn<6;fn++) { g3s_point *vert_list[4]; vert_list[0] = &Segment_points[seg->verts[Side_to_verts[fn][0]]]; vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][1]]]; vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; g3_check_and_draw_poly(3,vert_list,NULL,NULL); vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][3]]]; g3_check_and_draw_poly(3,vert_list,NULL,NULL); } if (gr_ugpixel(&grd_curcanv->cv_bitmap,Search_x,Search_y) == 1) { if (N_found_segs < MAX_FOUND_SEGS) Found_segs[N_found_segs++] = SEG_PTR_2_NUM(seg); else Warning("Found too many segs! (limit=%d)",MAX_FOUND_SEGS); } } } // ---------------------------------------------------------------------------- void draw_seg_side(segment *seg,int side) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? int i; for (i=0;i<3;i++) draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][i+1]]); draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][0]]); } } void draw_side_edge(segment *seg,int side,int edge) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) //on screen? draw_line(svp[Side_to_verts[side][edge]],svp[Side_to_verts[side][(edge+1)%4]]); } int Show_triangulations=0; //edge types - lower number types have precedence #define ET_FACING 0 //this edge on a facing face #define ET_NOTFACING 1 //this edge on a non-facing face #define ET_NOTUSED 2 //no face uses this edge #define ET_NOTEXTANT 3 //would exist if side were triangulated #define ET_EMPTY 255 //this entry in array is empty //colors for those types //int edge_colors[] = {BM_RGB(45/2,45/2,45/2), // BM_RGB(45/3,45/3,45/3), //BM_RGB(0,0,45), // // BM_RGB(45/4,45/4,45/4)}; //BM_RGB(0,45,0)}; // int edge_colors[] = { 54, 59, 64 }; typedef struct seg_edge { union { struct {short v0,v1;} __pack__ n; long vv; }v; ushort type; ubyte face_count, backface_count; } seg_edge; #define MAX_EDGES (MAX_VERTICES*4) seg_edge edge_list[MAX_EDGES]; short used_list[MAX_EDGES]; //which entries in edge_list have been used int n_used; int edge_list_size; //set each frame #define HASH(a,b) ((a*5+b) % edge_list_size) //define edge numberings short edges[] = { 0*8+1, // edge 0 0*8+3, // edge 1 0*8+4, // edge 2 1*8+2, // edge 3 1*8+5, // edge 4 2*8+3, // edge 5 2*8+6, // edge 6 3*8+7, // edge 7 4*8+5, // edge 8 4*8+7, // edge 9 5*8+6, // edge 10 6*8+7, // edge 11 0*8+5, // right cross 0*8+7, // top cross 1*8+3, // front cross 2*8+5, // bottom cross 2*8+7, // left cross 4*8+6, // back cross //crosses going the other way 1*8+4, // other right cross 3*8+4, // other top cross 0*8+2, // other front cross 1*8+6, // other bottom cross 3*8+6, // other left cross 5*8+7, // other back cross }; #define N_NORMAL_EDGES 12 //the normal edges of a box #define N_EXTRA_EDGES 12 //ones created by triangulation #define N_EDGES_PER_SEGMENT (N_NORMAL_EDGES+N_EXTRA_EDGES) #define swap(a,b) do {int t; t=(a); (a)=(b); (b)=t;} while (0) //given two vertex numbers on a segment (range 0..7), tell what edge number it is int find_edge_num(int v0,int v1) { int i; short vv; short *edgep = edges; if (v0 > v1) swap(v0,v1); vv = v0*8+v1; // for (i=0;i v1) swap(v0,v1); found = find_edge(v0,v1,&e); if (found == -1) { e->v.n.v0 = v0; e->v.n.v1 = v1; e->type = type; used_list[n_used] = e-edge_list; if (type == ET_FACING) edge_list[used_list[n_used]].face_count++; else if (type == ET_NOTFACING) edge_list[used_list[n_used]].backface_count++; //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); n_used++; } else { if (type < e->type) e->type = type; if (type == ET_FACING) edge_list[found].face_count++; else if (type == ET_NOTFACING) edge_list[found].backface_count++; //mprintf(0, "Facing count = %i, Not facing count = %i\n", edge_list[found].face_count, edge_list[found].backface_count); } } //adds a segment's edges to the edge list void add_edges(segment *seg) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? int i,sn,fn,vn; int flag; ubyte edge_flags[N_EDGES_PER_SEGMENT]; for (i=0;isides[sn]; int num_faces, num_vertices; int vertex_list[6]; create_all_vertex_lists(&num_faces, vertex_list, seg-Segments, sn); if (num_faces == 1) num_vertices = 4; else num_vertices = 3; for (fn=0; fnverts[vertex_list[fn*3]]],&sidep->normals[fn])) flag = ET_NOTFACING; else flag = ET_FACING; v0 = &vertex_list[fn*3]; for (vn=0; vnverts[edges[i]/8],seg->verts[edges[i]&7],edge_flags[i]); } } // ---------------------------------------------------------------------------- void draw_trigger_side(segment *seg,int side) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? // Draw diagonals draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); //g3_draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); } } // ---------------------------------------------------------------------------- void draw_wall_side(segment *seg,int side) { short *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.and) { //all off screen? // Draw diagonals draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); } } #define WALL_BLASTABLE_COLOR BM_XRGB( 31/2 , 0/2 , 0/2) // RED #define WALL_DOOR_COLOR BM_XRGB( 0/2 , 0/2 , 31/2) // DARK BLUE #define WALL_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) // BLUE #define WALL_AUTO_DOOR_COLOR BM_XRGB( 0/2 , 31/2 , 0/2) // DARK GREEN #define WALL_AUTO_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) // GREEN #define WALL_ILLUSION_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) // PURPLE #define TRIGGER_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW #define TRIGGER_DAMAGE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW // ---------------------------------------------------------------------------------------------------------------- // Draws special walls (for now these are just removable walls.) void draw_special_wall( segment *seg, int side ) { gr_setcolor(PLAINSEG_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_BLASTABLE) gr_setcolor(WALL_BLASTABLE_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_DOOR) gr_setcolor(WALL_DOOR_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_ILLUSION) gr_setcolor(GROUPSIDE_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) gr_setcolor(WALL_DOOR_LOCKED_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) gr_setcolor(WALL_AUTO_DOOR_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) gr_setcolor(WALL_AUTO_DOOR_LOCKED_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_OPEN) gr_setcolor(PLAINSEG_COLOR); draw_wall_side(seg,side); if (Walls[seg->sides[side].wall_num].trigger != -1) { int trigger_num; trigger_num = Walls[seg->sides[side].wall_num].trigger; gr_setcolor(TRIGGER_COLOR); draw_trigger_side(seg,side); } gr_setcolor(PLAINSEG_COLOR); } // ---------------------------------------------------------------------------------------------------------------- // Recursively parse mine structure, drawing segments. void draw_mine_sub(int segnum,int depth) { segment *mine_ptr; if (Been_visited[segnum]) return; // If segment already drawn, return. Been_visited[segnum] = 1; // Say that this segment has been drawn. mine_ptr = &Segments[segnum]; // If this segment is active, process it, else skip it. if (mine_ptr->segnum != -1) { int side; if (Search_mode) check_segment(mine_ptr); else add_edges(mine_ptr); //add this segments edges to list if (depth != 0) { for (side=0; sidechildren[side])) { if (mine_ptr->sides[side].wall_num != -1) draw_special_wall(mine_ptr, side); draw_mine_sub(mine_ptr->children[side],depth-1); } } } } } void draw_mine_edges(int automap_flag) { int i,type; seg_edge *e; for (type=ET_NOTUSED;type>=ET_FACING;type--) { gr_setcolor(edge_colors[type]); for (i=0;itype == type) if ((!automap_flag) || (e->face_count == 1)) draw_line(e->v.n.v0,e->v.n.v1); } } } //draws an entire mine void draw_mine(segment *mine_ptr,int depth) { int i; // clear visited list for (i=0; i<=Highest_segment_index; i++) Been_visited[i] = 0; edge_list_size = min(Num_vertices*4,MAX_EDGES); //make maybe smaller than max // clear edge list for (i=0; i -1) { gr_setcolor(GROUP_COLOR); for (s=0; scanvas ) { // CurrentBigCanvas ^= 1; // // gr_set_current_canvas( BigCanvas[CurrentBigCanvas] ); // // } else { gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0, screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h); gr_set_current_canvas(&temp_canvas); // } #else gr_set_current_canvas(screen_canvas); #endif //mprintf(0, "\n"); ui_mouse_hide(); //g3_set_points(Segment_points,Vertices); viewer_position = v->ev_matrix.fvec; vm_vec_scale(&viewer_position,-v->ev_dist); vm_vec_add2(&viewer_position,&Ed_view_target); gr_clear_canvas(0); g3_start_frame(); g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); render_start_frame(); gr_setcolor(PLAINSEG_COLOR); // Draw all segments or only connected segments. // We might want to draw all segments if we have broken the mine into pieces. if (Draw_all_segments) draw_mine_all(Segments, Automap_test); else draw_mine(mine_ptr,depth); // Draw the found segments if (!Automap_test) { draw_warning_segments(); draw_group_segments(); draw_found_segments(); draw_selected_segments(); draw_special_segments(); // Highlight group segment and side. if (current_group > -1) if (Groupsegp[current_group]) { gr_setcolor(GROUPSEG_COLOR); draw_segment(Groupsegp[current_group]); gr_setcolor(GROUPSIDE_COLOR); draw_seg_side(Groupsegp[current_group],Groupside[current_group]); } // Highlight marked segment and side. if (Markedsegp) { gr_setcolor(MARKEDSEG_COLOR); draw_segment(Markedsegp); gr_setcolor(MARKEDSIDE_COLOR); draw_seg_side(Markedsegp,Markedside); } // Highlight current segment and current side. gr_setcolor(CURSEG_COLOR); draw_segment(Cursegp); gr_setcolor(CURSIDE_COLOR); draw_seg_side(Cursegp,Curside); gr_setcolor(CUREDGE_COLOR); draw_side_edge(Cursegp,Curside,Curedge); // Draw coordinate axes if we are rendering the large view. if (Show_axes_flag) if (screen_canvas == LargeViewBox->canvas) draw_coordinate_axes(); // Label the window gr_set_fontcolor((v==current_view)?CRED:CWHITE, -1 ); if ( screen_canvas == LargeViewBox->canvas ) { gr_ustring( 5, 5, "USER VIEW" ); switch (Large_view_index) { case 0: gr_ustring( 85, 5, "-- TOP"); break; case 1: gr_ustring( 85, 5, "-- FRONT"); break; case 2: gr_ustring( 85, 5, "-- RIGHT"); break; } } else #if ORTHO_VIEWS else if ( screen_canvas == TopViewBox->canvas ) gr_ustring( 5, 5, "TOP" ); else if ( screen_canvas == FrontViewBox->canvas ) gr_ustring( 5, 5, "FRONT" ); else if ( screen_canvas == RightViewBox->canvas ) gr_ustring( 5, 5, "RIGHT" ); #else Error("Ortho views have been removed, what gives?\n"); #endif } g3_end_frame(); #if DOUBLE_BUFFER // if ( screen_canvas == LargeViewBox->canvas ) { // if (BigCanvasFirstTime) { // BigCanvasFirstTime = 0; // gr_set_current_canvas( screen_canvas ); // gr_ubitmap( 0, 0, &BigCanvas[CurrentBigCanvas]->cv_bitmap ); // } else { // gr_vesa_update( &BigCanvas[CurrentBigCanvas]->cv_bitmap, &screen_canvas->cv_bitmap, &BigCanvas[CurrentBigCanvas ^ 1]->cv_bitmap ); // } // } else { gr_set_current_canvas( screen_canvas ); gr_ubitmap( 0, 0, &temp_canvas.cv_bitmap ); // } #endif ui_mouse_show(); } //find the segments that render at a given screen x,y //parms other than x,y are like draw_world //fills in globals N_found_segs & Found_segs void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth) { vms_vector viewer_position; #if DOUBLE_BUFFER grs_canvas temp_canvas; gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0, screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h); gr_set_current_canvas(&temp_canvas); #else gr_set_current_canvas(screen_canvas); #endif ui_mouse_hide(); //g3_set_points(Segment_points,Vertices); viewer_position = v->ev_matrix.fvec; vm_vec_scale(&viewer_position,-v->ev_dist); vm_vec_add(&viewer_position,&viewer_position,&Ed_view_target); g3_start_frame(); g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); render_start_frame(); gr_setcolor(0); gr_pixel(x,y); gr_setcolor(1); Search_mode = -1; N_found_segs = 0; Search_x = x; Search_y = y; if (Draw_all_segments) draw_mine_all(Segments, 0); else draw_mine(mine_ptr,depth); g3_end_frame(); Search_mode = 0; } void meddraw_init_views( grs_canvas * canvas) { Views[0]->ev_canv = canvas; #if ORTHO_VIEWS Views[1]->ev_canv = TopViewBox->canvas; Views[2]->ev_canv = FrontViewBox->canvas; Views[3]->ev_canv = RightViewBox->canvas; #endif }