Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1 | pmbaty | 1 | /* |
| 2 | * Portions of this file are copyright Rebirth contributors and licensed as |
||
| 3 | * described in COPYING.txt. |
||
| 4 | * Portions of this file are copyright Parallax Software and licensed |
||
| 5 | * according to the Parallax license below. |
||
| 6 | * See COPYING.txt for license details. |
||
| 7 | |||
| 8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX |
||
| 9 | SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO |
||
| 10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A |
||
| 11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS |
||
| 12 | IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS |
||
| 13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE |
||
| 14 | FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE |
||
| 15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS |
||
| 16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. |
||
| 17 | COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. |
||
| 18 | */ |
||
| 19 | |||
| 20 | /* |
||
| 21 | * |
||
| 22 | * Med drawing functions. |
||
| 23 | * |
||
| 24 | */ |
||
| 25 | |||
| 26 | #include <algorithm> |
||
| 27 | #include <stdio.h> |
||
| 28 | #include <stdlib.h> |
||
| 29 | #include <stdarg.h> |
||
| 30 | #include <string.h> |
||
| 31 | #include "inferno.h" |
||
| 32 | #include "segment.h" |
||
| 33 | #include "segpoint.h" |
||
| 34 | #include "gameseg.h" |
||
| 35 | #include "gr.h" |
||
| 36 | #include "ui.h" |
||
| 37 | #include "editor/editor.h" |
||
| 38 | #include "editor/esegment.h" |
||
| 39 | #include "wall.h" |
||
| 40 | #include "switch.h" |
||
| 41 | #include "key.h" |
||
| 42 | #include "mouse.h" |
||
| 43 | #include "dxxerror.h" |
||
| 44 | #include "medlisp.h" |
||
| 45 | #include "u_mem.h" |
||
| 46 | #include "render.h" |
||
| 47 | #include "game.h" |
||
| 48 | #include "kdefs.h" |
||
| 49 | #include "func.h" |
||
| 50 | #include "textures.h" |
||
| 51 | #include "screens.h" |
||
| 52 | #include "texmap.h" |
||
| 53 | #include "object.h" |
||
| 54 | #include "fuelcen.h" |
||
| 55 | #include "meddraw.h" |
||
| 56 | #include "d_enumerate.h" |
||
| 57 | #include "d_range.h" |
||
| 58 | #include "compiler-range_for.h" |
||
| 59 | #include "segiter.h" |
||
| 60 | #include "d_range.h" |
||
| 61 | #include "d_zip.h" |
||
| 62 | |||
| 63 | #if DXX_USE_OGL |
||
| 64 | #include "ogl_init.h" |
||
| 65 | #endif |
||
| 66 | |||
| 67 | using std::min; |
||
| 68 | |||
| 69 | // Colors used in editor for indicating various kinds of segments. |
||
| 70 | #define SELECT_COLOR BM_XRGB( 63/2 , 41/2 , 0/2) |
||
| 71 | #define FOUND_COLOR BM_XRGB( 0/2 , 30/2 , 45/2) |
||
| 72 | #define WARNING_COLOR BM_XRGB( 63/2 , 0/2 , 0/2) |
||
| 73 | #define AXIS_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) |
||
| 74 | #define PLAINSEG_COLOR BM_XRGB( 45/2 , 45/2 , 45/2) |
||
| 75 | #define MARKEDSEG_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) |
||
| 76 | #define MARKEDSIDE_COLOR BM_XRGB( 0/2 , 63/2 , 63/2) |
||
| 77 | #define CURSEG_COLOR BM_XRGB( 63/2 , 63/2 , 63/2) |
||
| 78 | #define CURSIDE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) |
||
| 79 | #define CUREDGE_COLOR BM_XRGB( 0 , 63/2 , 0 ) |
||
| 80 | #define GROUPSEG_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) |
||
| 81 | #define GROUPSIDE_COLOR BM_XRGB( 63/2 , 0/2 , 45/2) |
||
| 82 | #define GROUP_COLOR BM_XRGB( 0/2 , 45/2 , 0/2) |
||
| 83 | #define ROBOT_COLOR BM_XRGB( 31 , 0 , 0 ) |
||
| 84 | #define PLAYER_COLOR BM_XRGB( 0 , 0 , 31 ) |
||
| 85 | |||
| 86 | constexpr std::integral_constant<unsigned, MAX_VERTICES * 4> MAX_EDGES{}; |
||
| 87 | |||
| 88 | static int Search_mode=0; //if true, searching for segments at given x,y |
||
| 89 | static int Search_x,Search_y; |
||
| 90 | static int Automap_test=0; // Set to 1 to show wireframe in automap mode. |
||
| 91 | |||
| 92 | static void draw_seg_objects(grs_canvas &canvas, const unique_segment &seg) |
||
| 93 | { |
||
| 94 | auto &Objects = LevelUniqueObjectState.Objects; |
||
| 95 | auto &vcobjptridx = Objects.vcptridx; |
||
| 96 | range_for (const auto obj, objects_in(seg, vcobjptridx, vcsegptr)) |
||
| 97 | { |
||
| 98 | auto sphere_point = g3_rotate_point(obj->pos); |
||
| 99 | const uint8_t color = (obj->type == OBJ_PLAYER && static_cast<icobjptridx_t::index_type>(obj) > 0) |
||
| 100 | ? BM_XRGB(0, 25, 0) |
||
| 101 | : (obj == ConsoleObject |
||
| 102 | ? PLAYER_COLOR |
||
| 103 | : ROBOT_COLOR |
||
| 104 | ); |
||
| 105 | g3_draw_sphere(canvas, sphere_point, obj->size, color); |
||
| 106 | } |
||
| 107 | } |
||
| 108 | |||
| 109 | #if DXX_USE_OGL |
||
| 110 | #define draw_line(C,P0,P1,c) draw_line(P0,P1,c) |
||
| 111 | #define draw_segment(C,S,c) draw_segment(S,c) |
||
| 112 | #define draw_listed_segments(C,S,c) draw_listed_segments(S,c) |
||
| 113 | #endif |
||
| 114 | static void draw_line(grs_canvas &canvas, const unsigned pnum0, const unsigned pnum1, const color_palette_index color) |
||
| 115 | { |
||
| 116 | g3_draw_line(canvas, Segment_points[pnum0], Segment_points[pnum1], color); |
||
| 117 | } |
||
| 118 | |||
| 119 | // ---------------------------------------------------------------------------- |
||
| 120 | static void draw_segment(grs_canvas &canvas, const shared_segment &seg, const color_palette_index color) |
||
| 121 | { |
||
| 122 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 123 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 124 | if (seg.segnum == segment_none) //this segment doesn't exitst |
||
| 125 | return; |
||
| 126 | |||
| 127 | auto &svp = seg.verts; |
||
| 128 | auto &vcvertptr = Vertices.vcptr; |
||
| 129 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 130 | { //all off screen? |
||
| 131 | range_for (const unsigned i, xrange(4u)) |
||
| 132 | draw_line(canvas, svp[i], svp[i+4], color); |
||
| 133 | |||
| 134 | range_for (const unsigned i, xrange(3u)) |
||
| 135 | { |
||
| 136 | draw_line(canvas, svp[i], svp[i+1], color); |
||
| 137 | draw_line(canvas, svp[i+4], svp[i+4+1], color); |
||
| 138 | } |
||
| 139 | |||
| 140 | draw_line(canvas, svp[0], svp[3], color); |
||
| 141 | draw_line(canvas, svp[4], svp[3+4], color); |
||
| 142 | } |
||
| 143 | } |
||
| 144 | |||
| 145 | //for looking for segment under a mouse click |
||
| 146 | static void check_segment(const vmsegptridx_t seg) |
||
| 147 | { |
||
| 148 | auto &svp = seg->verts; |
||
| 149 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 150 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 151 | auto &vcvertptr = Vertices.vcptr; |
||
| 152 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 153 | { //all off screen? |
||
| 154 | #if DXX_USE_OGL |
||
| 155 | g3_end_frame(); |
||
| 156 | #endif |
||
| 157 | { |
||
| 158 | uint8_t color = 0; |
||
| 159 | gr_pixel(grd_curcanv->cv_bitmap, Search_x, Search_y, color); //set our search pixel to color zero |
||
| 160 | } |
||
| 161 | #if DXX_USE_OGL |
||
| 162 | g3_start_frame(*grd_curcanv); |
||
| 163 | #endif |
||
| 164 | { |
||
| 165 | const uint8_t color = 1; |
||
| 166 | //and render in color one |
||
| 167 | |||
| 168 | range_for (auto &fn, Side_to_verts) |
||
| 169 | { |
||
| 170 | std::array<cg3s_point *, 3> vert_list; |
||
| 171 | vert_list[0] = &Segment_points[seg->verts[fn[0]]]; |
||
| 172 | vert_list[1] = &Segment_points[seg->verts[fn[1]]]; |
||
| 173 | vert_list[2] = &Segment_points[seg->verts[fn[2]]]; |
||
| 174 | g3_check_and_draw_poly(*grd_curcanv, vert_list, color); |
||
| 175 | |||
| 176 | vert_list[1] = &Segment_points[seg->verts[fn[2]]]; |
||
| 177 | vert_list[2] = &Segment_points[seg->verts[fn[3]]]; |
||
| 178 | g3_check_and_draw_poly(*grd_curcanv, vert_list, color); |
||
| 179 | } |
||
| 180 | } |
||
| 181 | |||
| 182 | if (gr_ugpixel(grd_curcanv->cv_bitmap,Search_x,Search_y) == 1) |
||
| 183 | { |
||
| 184 | Found_segs.emplace_back(seg); |
||
| 185 | } |
||
| 186 | } |
||
| 187 | } |
||
| 188 | |||
| 189 | // ---------------------------------------------------------------------------- |
||
| 190 | static void draw_seg_side(const shared_segment &seg, const unsigned side, const color_palette_index color) |
||
| 191 | { |
||
| 192 | auto &svp = seg.verts; |
||
| 193 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 194 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 195 | auto &vcvertptr = Vertices.vcptr; |
||
| 196 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 197 | { //all off screen? |
||
| 198 | int i; |
||
| 199 | |||
| 200 | auto &stv = Side_to_verts[side]; |
||
| 201 | for (i=0;i<3;i++) |
||
| 202 | draw_line(*grd_curcanv, svp[stv[i]], svp[stv[i+1]], color); |
||
| 203 | |||
| 204 | draw_line(*grd_curcanv, svp[stv[i]], svp[stv[0]], color); |
||
| 205 | } |
||
| 206 | } |
||
| 207 | |||
| 208 | static void draw_side_edge(const shared_segment &seg, const unsigned side, const unsigned edge, const color_palette_index color) |
||
| 209 | { |
||
| 210 | auto &svp = seg.verts; |
||
| 211 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 212 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 213 | auto &vcvertptr = Vertices.vcptr; |
||
| 214 | if (!rotate_list(vcvertptr, svp).uand) //on screen? |
||
| 215 | { |
||
| 216 | auto &stv = Side_to_verts[side]; |
||
| 217 | draw_line(*grd_curcanv, svp[stv[edge]], svp[stv[(edge + 1) % 4]], color); |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | int Show_triangulations=0; |
||
| 222 | |||
| 223 | //edge types - lower number types have precedence |
||
| 224 | #define ET_FACING 0 //this edge on a facing face |
||
| 225 | #define ET_NOTFACING 1 //this edge on a non-facing face |
||
| 226 | #define ET_NOTUSED 2 //no face uses this edge |
||
| 227 | #define ET_NOTEXTANT 3 //would exist if side were triangulated |
||
| 228 | |||
| 229 | #define ET_EMPTY 255 //this entry in array is empty |
||
| 230 | |||
| 231 | //colors for those types |
||
| 232 | //int edge_colors[] = {BM_RGB(45/2,45/2,45/2), |
||
| 233 | // BM_RGB(45/3,45/3,45/3), //BM_RGB(0,0,45), // |
||
| 234 | // BM_RGB(45/4,45/4,45/4)}; //BM_RGB(0,45,0)}; // |
||
| 235 | |||
| 236 | static |
||
| 237 | #if defined(DXX_BUILD_DESCENT_I) |
||
| 238 | const |
||
| 239 | #endif |
||
| 240 | std::array<color_palette_index, 3> edge_colors{{54, 59, 64}}; |
||
| 241 | |||
| 242 | namespace { |
||
| 243 | |||
| 244 | struct seg_edge |
||
| 245 | { |
||
| 246 | union { |
||
| 247 | struct {int v0,v1;} __pack__ n; |
||
| 248 | long vv; |
||
| 249 | }v; |
||
| 250 | ushort type; |
||
| 251 | ubyte face_count, backface_count; |
||
| 252 | }; |
||
| 253 | |||
| 254 | } |
||
| 255 | |||
| 256 | static std::array<seg_edge, MAX_EDGES> edge_list; |
||
| 257 | static std::array<int, MAX_EDGES> used_list; //which entries in edge_list have been used |
||
| 258 | static int n_used; |
||
| 259 | |||
| 260 | static unsigned edge_list_size; //set each frame |
||
| 261 | |||
| 262 | #define HASH(a,b) ((a*5+b) % edge_list_size) |
||
| 263 | |||
| 264 | //define edge numberings |
||
| 265 | constexpr int edges[] = { |
||
| 266 | 0*8+1, // edge 0 |
||
| 267 | 0*8+3, // edge 1 |
||
| 268 | 0*8+4, // edge 2 |
||
| 269 | 1*8+2, // edge 3 |
||
| 270 | 1*8+5, // edge 4 |
||
| 271 | 2*8+3, // edge 5 |
||
| 272 | 2*8+6, // edge 6 |
||
| 273 | 3*8+7, // edge 7 |
||
| 274 | 4*8+5, // edge 8 |
||
| 275 | 4*8+7, // edge 9 |
||
| 276 | 5*8+6, // edge 10 |
||
| 277 | 6*8+7, // edge 11 |
||
| 278 | |||
| 279 | 0*8+5, // right cross |
||
| 280 | 0*8+7, // top cross |
||
| 281 | 1*8+3, // front cross |
||
| 282 | 2*8+5, // bottom cross |
||
| 283 | 2*8+7, // left cross |
||
| 284 | 4*8+6, // back cross |
||
| 285 | |||
| 286 | //crosses going the other way |
||
| 287 | |||
| 288 | 1*8+4, // other right cross |
||
| 289 | 3*8+4, // other top cross |
||
| 290 | 0*8+2, // other front cross |
||
| 291 | 1*8+6, // other bottom cross |
||
| 292 | 3*8+6, // other left cross |
||
| 293 | 5*8+7, // other back cross |
||
| 294 | }; |
||
| 295 | |||
| 296 | #define N_NORMAL_EDGES 12 //the normal edges of a box |
||
| 297 | #define N_EXTRA_EDGES 12 //ones created by triangulation |
||
| 298 | #define N_EDGES_PER_SEGMENT (N_NORMAL_EDGES+N_EXTRA_EDGES) |
||
| 299 | |||
| 300 | using std::swap; |
||
| 301 | |||
| 302 | //given two vertex numbers on a segment (range 0..7), tell what edge number it is |
||
| 303 | static int find_edge_num(int v0,int v1) |
||
| 304 | { |
||
| 305 | int i; |
||
| 306 | int vv; |
||
| 307 | const int *edgep = edges; |
||
| 308 | |||
| 309 | if (v0 > v1) swap(v0,v1); |
||
| 310 | |||
| 311 | vv = v0*8+v1; |
||
| 312 | |||
| 313 | // for (i=0;i<N_EDGES_PER_SEGMENT;i++) |
||
| 314 | // if (edges[i]==vv) return i; |
||
| 315 | |||
| 316 | for (i=N_EDGES_PER_SEGMENT; i; i--) |
||
| 317 | if (*edgep++ == vv) |
||
| 318 | return (N_EDGES_PER_SEGMENT-i); |
||
| 319 | |||
| 320 | Error("Could not find edge for %d,%d",v0,v1); |
||
| 321 | |||
| 322 | //return -1; |
||
| 323 | } |
||
| 324 | |||
| 325 | |||
| 326 | //finds edge, filling in edge_ptr. if found old edge, returns index, else return -1 |
||
| 327 | static int find_edge(int v0,int v1,seg_edge **edge_ptr) |
||
| 328 | { |
||
| 329 | long vv; |
||
| 330 | int hash,oldhash; |
||
| 331 | int ret; |
||
| 332 | |||
| 333 | vv = (v1<<16) + v0; |
||
| 334 | |||
| 335 | oldhash = hash = HASH(v0,v1); |
||
| 336 | |||
| 337 | ret = -1; |
||
| 338 | |||
| 339 | while (ret==-1) { |
||
| 340 | |||
| 341 | if (edge_list[hash].type == ET_EMPTY) ret=0; |
||
| 342 | else if (edge_list[hash].v.vv == vv) ret=1; |
||
| 343 | else { |
||
| 344 | if (++hash==edge_list_size) hash=0; |
||
| 345 | if (hash==oldhash) Error("Edge list full!"); |
||
| 346 | } |
||
| 347 | } |
||
| 348 | |||
| 349 | *edge_ptr = &edge_list[hash]; |
||
| 350 | |||
| 351 | if (ret == 0) |
||
| 352 | return -1; |
||
| 353 | else |
||
| 354 | return hash; |
||
| 355 | |||
| 356 | } |
||
| 357 | |||
| 358 | //adds an edge to the edge list |
||
| 359 | static void add_edge(int v0,int v1,ubyte type) |
||
| 360 | { |
||
| 361 | int found; |
||
| 362 | |||
| 363 | seg_edge *e; |
||
| 364 | |||
| 365 | if (v0 > v1) swap(v0,v1); |
||
| 366 | |||
| 367 | found = find_edge(v0,v1,&e); |
||
| 368 | |||
| 369 | if (found == -1) { |
||
| 370 | e->v.n.v0 = v0; |
||
| 371 | e->v.n.v1 = v1; |
||
| 372 | e->type = type; |
||
| 373 | used_list[n_used] = e - edge_list.begin(); |
||
| 374 | if (type == ET_FACING) |
||
| 375 | edge_list[used_list[n_used]].face_count++; |
||
| 376 | else if (type == ET_NOTFACING) |
||
| 377 | edge_list[used_list[n_used]].backface_count++; |
||
| 378 | n_used++; |
||
| 379 | } else { |
||
| 380 | if (type < e->type) |
||
| 381 | e->type = type; |
||
| 382 | if (type == ET_FACING) |
||
| 383 | edge_list[found].face_count++; |
||
| 384 | else if (type == ET_NOTFACING) |
||
| 385 | edge_list[found].backface_count++; |
||
| 386 | } |
||
| 387 | } |
||
| 388 | |||
| 389 | //adds a segment's edges to the edge list |
||
| 390 | static void add_edges(const shared_segment &seg) |
||
| 391 | { |
||
| 392 | auto &svp = seg.verts; |
||
| 393 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 394 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 395 | auto &vcvertptr = Vertices.vcptr; |
||
| 396 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 397 | { //all off screen? |
||
| 398 | int i,fn,vn; |
||
| 399 | int flag; |
||
| 400 | ubyte edge_flags[N_EDGES_PER_SEGMENT]; |
||
| 401 | |||
| 402 | for (i=0;i<N_NORMAL_EDGES;i++) edge_flags[i]=ET_NOTUSED; |
||
| 403 | for (;i<N_EDGES_PER_SEGMENT;i++) edge_flags[i]=ET_NOTEXTANT; |
||
| 404 | |||
| 405 | range_for (auto &&e, enumerate(seg.sides)) |
||
| 406 | { |
||
| 407 | auto &sidep = e.value; |
||
| 408 | int num_vertices; |
||
| 409 | const auto v = create_all_vertex_lists(seg, sidep, e.idx); |
||
| 410 | const auto &num_faces = v.first; |
||
| 411 | const auto &vertex_list = v.second; |
||
| 412 | if (num_faces == 1) |
||
| 413 | num_vertices = 4; |
||
| 414 | else |
||
| 415 | num_vertices = 3; |
||
| 416 | |||
| 417 | for (fn=0; fn<num_faces; fn++) { |
||
| 418 | int en; |
||
| 419 | |||
| 420 | //Note: normal check appears to be the wrong way since the normals points in, but we're looking from the outside |
||
| 421 | if (g3_check_normal_facing(vcvertptr(seg.verts[vertex_list[fn*3]]), sidep.normals[fn])) |
||
| 422 | flag = ET_NOTFACING; |
||
| 423 | else |
||
| 424 | flag = ET_FACING; |
||
| 425 | |||
| 426 | auto v0 = &vertex_list[fn*3]; |
||
| 427 | for (vn=0; vn<num_vertices-1; vn++) { |
||
| 428 | |||
| 429 | // en = find_edge_num(vertex_list[fn*3 + vn], vertex_list[fn*3 + (vn+1)%num_vertices]); |
||
| 430 | en = find_edge_num(*v0, *(v0+1)); |
||
| 431 | |||
| 432 | if (en!=edge_none) |
||
| 433 | if (flag < edge_flags[en]) edge_flags[en] = flag; |
||
| 434 | |||
| 435 | v0++; |
||
| 436 | } |
||
| 437 | en = find_edge_num(*v0, vertex_list[fn*3]); |
||
| 438 | if (en!=edge_none) |
||
| 439 | if (flag < edge_flags[en]) edge_flags[en] = flag; |
||
| 440 | } |
||
| 441 | } |
||
| 442 | |||
| 443 | for (i=0; i<N_EDGES_PER_SEGMENT; i++) |
||
| 444 | if (i<N_NORMAL_EDGES || (edge_flags[i]!=ET_NOTEXTANT && Show_triangulations)) |
||
| 445 | add_edge(seg.verts[edges[i] / 8], seg.verts[edges[i] & 7], edge_flags[i]); |
||
| 446 | } |
||
| 447 | } |
||
| 448 | |||
| 449 | // ---------------------------------------------------------------------------- |
||
| 450 | static void draw_trigger_side(const shared_segment &seg, const unsigned side, const color_palette_index color) |
||
| 451 | { |
||
| 452 | auto &svp = seg.verts; |
||
| 453 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 454 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 455 | auto &vcvertptr = Vertices.vcptr; |
||
| 456 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 457 | { //all off screen? |
||
| 458 | // Draw diagonals |
||
| 459 | auto &stv = Side_to_verts[side]; |
||
| 460 | draw_line(*grd_curcanv, svp[stv[0]], svp[stv[2]], color); |
||
| 461 | } |
||
| 462 | } |
||
| 463 | |||
| 464 | // ---------------------------------------------------------------------------- |
||
| 465 | static void draw_wall_side(const shared_segment &seg, const unsigned side, const color_palette_index color) |
||
| 466 | { |
||
| 467 | auto &svp = seg.verts; |
||
| 468 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 469 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 470 | auto &vcvertptr = Vertices.vcptr; |
||
| 471 | if (!rotate_list(vcvertptr, svp).uand) |
||
| 472 | { //all off screen? |
||
| 473 | // Draw diagonals |
||
| 474 | auto &stv = Side_to_verts[side]; |
||
| 475 | draw_line(*grd_curcanv, svp[stv[0]], svp[stv[2]], color); |
||
| 476 | draw_line(*grd_curcanv, svp[stv[1]], svp[stv[3]], color); |
||
| 477 | } |
||
| 478 | } |
||
| 479 | |||
| 480 | #define WALL_BLASTABLE_COLOR rgb_t{31, 0, 0} // RED |
||
| 481 | #define WALL_DOOR_COLOR rgb_t{0, 0, 31} // DARK BLUE |
||
| 482 | #define WALL_DOOR_LOCKED_COLOR rgb_t{0, 0, 63} // BLUE |
||
| 483 | #define WALL_AUTO_DOOR_COLOR rgb_t{0, 31, 0} // DARK GREEN |
||
| 484 | #define WALL_AUTO_DOOR_LOCKED_COLOR rgb_t{0, 63, 0} // GREEN |
||
| 485 | #define WALL_ILLUSION_COLOR rgb_t{63, 0, 63} // PURPLE |
||
| 486 | |||
| 487 | #define TRIGGER_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW |
||
| 488 | |||
| 489 | // ---------------------------------------------------------------------------------------------------------------- |
||
| 490 | // Draws special walls (for now these are just removable walls.) |
||
| 491 | static void draw_special_wall(const shared_segment &seg, const unsigned side) |
||
| 492 | { |
||
| 493 | auto &Walls = LevelUniqueWallSubsystemState.Walls; |
||
| 494 | auto &vcwallptr = Walls.vcptr; |
||
| 495 | auto &w = *vcwallptr(seg.sides[side].wall_num); |
||
| 496 | const auto get_color = [=]() { |
||
| 497 | const auto type = w.type; |
||
| 498 | if (type != WALL_OPEN) |
||
| 499 | { |
||
| 500 | const auto flags = w.flags; |
||
| 501 | if (flags & WALL_DOOR_LOCKED) |
||
| 502 | return (flags & WALL_DOOR_AUTO) ? WALL_AUTO_DOOR_LOCKED_COLOR : WALL_DOOR_LOCKED_COLOR; |
||
| 503 | if (flags & WALL_DOOR_AUTO) |
||
| 504 | return WALL_AUTO_DOOR_COLOR; |
||
| 505 | if (type == WALL_BLASTABLE) |
||
| 506 | return WALL_BLASTABLE_COLOR; |
||
| 507 | if (type == WALL_DOOR) |
||
| 508 | return WALL_DOOR_COLOR; |
||
| 509 | if (type == WALL_ILLUSION) |
||
| 510 | return WALL_ILLUSION_COLOR; |
||
| 511 | } |
||
| 512 | return rgb_t{45, 45, 45}; |
||
| 513 | }; |
||
| 514 | const auto color = get_color(); |
||
| 515 | draw_wall_side(seg,side, gr_find_closest_color(color.r, color.g, color.b)); |
||
| 516 | |||
| 517 | if (w.trigger != trigger_none) |
||
| 518 | { |
||
| 519 | draw_trigger_side(seg,side, TRIGGER_COLOR); |
||
| 520 | } |
||
| 521 | } |
||
| 522 | |||
| 523 | |||
| 524 | // ---------------------------------------------------------------------------------------------------------------- |
||
| 525 | // Recursively parse mine structure, drawing segments. |
||
| 526 | static void draw_mine_sub(const vmsegptridx_t segnum,int depth, visited_segment_bitarray_t &visited) |
||
| 527 | { |
||
| 528 | if (visited[segnum]) return; // If segment already drawn, return. |
||
| 529 | visited[segnum] = true; // Say that this segment has been drawn. |
||
| 530 | auto mine_ptr = segnum; |
||
| 531 | // If this segment is active, process it, else skip it. |
||
| 532 | |||
| 533 | if (mine_ptr->segnum != segment_none) { |
||
| 534 | |||
| 535 | if (Search_mode) check_segment(mine_ptr); |
||
| 536 | else add_edges(mine_ptr); //add this segments edges to list |
||
| 537 | |||
| 538 | if (depth != 0) { |
||
| 539 | const shared_segment &sseg = *mine_ptr; |
||
| 540 | for (const auto &&[idx, child_segnum, sside] : enumerate(zip(sseg.children, sseg.sides))) |
||
| 541 | { |
||
| 542 | if (IS_CHILD(child_segnum)) |
||
| 543 | { |
||
| 544 | if (sside.wall_num != wall_none) |
||
| 545 | draw_special_wall(mine_ptr, idx); |
||
| 546 | draw_mine_sub(segnum.absolute_sibling(child_segnum), depth-1, visited); |
||
| 547 | } |
||
| 548 | } |
||
| 549 | } |
||
| 550 | } |
||
| 551 | } |
||
| 552 | |||
| 553 | static void draw_mine_edges(int automap_flag) |
||
| 554 | { |
||
| 555 | int i,type; |
||
| 556 | seg_edge *e; |
||
| 557 | |||
| 558 | for (type=ET_NOTUSED;type>=ET_FACING;type--) { |
||
| 559 | const auto color = edge_colors[type]; |
||
| 560 | for (i=0;i<n_used;i++) { |
||
| 561 | e = &edge_list[used_list[i]]; |
||
| 562 | if (e->type == type) |
||
| 563 | if ((!automap_flag) || (e->face_count == 1)) |
||
| 564 | draw_line(*grd_curcanv, e->v.n.v0, e->v.n.v1, color); |
||
| 565 | } |
||
| 566 | } |
||
| 567 | } |
||
| 568 | |||
| 569 | static void clear_edge_list() |
||
| 570 | { |
||
| 571 | range_for (auto &i, partial_range(edge_list, edge_list_size)) |
||
| 572 | { |
||
| 573 | i.type = ET_EMPTY; |
||
| 574 | i.face_count = 0; |
||
| 575 | i.backface_count = 0; |
||
| 576 | } |
||
| 577 | } |
||
| 578 | |||
| 579 | //draws an entire mine |
||
| 580 | static void draw_mine(const vmsegptridx_t mine_ptr,int depth) |
||
| 581 | { |
||
| 582 | visited_segment_bitarray_t visited; |
||
| 583 | |||
| 584 | edge_list_size = min(LevelSharedSegmentState.Num_segments * 12, MAX_EDGES.value); //make maybe smaller than max |
||
| 585 | |||
| 586 | // clear edge list |
||
| 587 | clear_edge_list(); |
||
| 588 | |||
| 589 | n_used = 0; |
||
| 590 | |||
| 591 | draw_mine_sub(mine_ptr,depth, visited); |
||
| 592 | |||
| 593 | draw_mine_edges(0); |
||
| 594 | |||
| 595 | } |
||
| 596 | |||
| 597 | // ----------------------------------------------------------------------------- |
||
| 598 | // Draw all segments, ignoring connectivity. |
||
| 599 | // A segment is drawn if its segnum != -1. |
||
| 600 | static void draw_mine_all(int automap_flag) |
||
| 601 | { |
||
| 602 | edge_list_size = min(LevelSharedSegmentState.Num_segments * 12, MAX_EDGES.value); //make maybe smaller than max |
||
| 603 | |||
| 604 | // clear edge list |
||
| 605 | clear_edge_list(); |
||
| 606 | |||
| 607 | n_used = 0; |
||
| 608 | |||
| 609 | range_for (const auto &&segp, vmsegptridx) |
||
| 610 | { |
||
| 611 | if (segp->segnum != segment_none) |
||
| 612 | { |
||
| 613 | range_for (auto &&e, enumerate(segp->shared_segment::sides)) |
||
| 614 | if (e.value.wall_num != wall_none) |
||
| 615 | draw_special_wall(segp, e.idx); |
||
| 616 | if (Search_mode) |
||
| 617 | check_segment(segp); |
||
| 618 | else { |
||
| 619 | add_edges(segp); |
||
| 620 | draw_seg_objects(*grd_curcanv, segp); |
||
| 621 | } |
||
| 622 | } |
||
| 623 | } |
||
| 624 | |||
| 625 | draw_mine_edges(automap_flag); |
||
| 626 | |||
| 627 | } |
||
| 628 | |||
| 629 | static void draw_listed_segments(grs_canvas &canvas, count_segment_array_t &s, const uint8_t color) |
||
| 630 | { |
||
| 631 | range_for (const auto &ss, s) |
||
| 632 | { |
||
| 633 | const auto &&segp = vcsegptr(ss); |
||
| 634 | if (segp->segnum != segment_none) |
||
| 635 | draw_segment(canvas, segp, color); |
||
| 636 | } |
||
| 637 | } |
||
| 638 | |||
| 639 | static void draw_selected_segments(void) |
||
| 640 | { |
||
| 641 | draw_listed_segments(*grd_curcanv, Selected_segs, SELECT_COLOR); |
||
| 642 | } |
||
| 643 | |||
| 644 | static void draw_found_segments(void) |
||
| 645 | { |
||
| 646 | draw_listed_segments(*grd_curcanv, Found_segs, FOUND_COLOR); |
||
| 647 | } |
||
| 648 | |||
| 649 | static void draw_warning_segments(void) |
||
| 650 | { |
||
| 651 | draw_listed_segments(*grd_curcanv, Warning_segs, WARNING_COLOR); |
||
| 652 | } |
||
| 653 | |||
| 654 | static void draw_group_segments(void) |
||
| 655 | { |
||
| 656 | if (current_group > -1) { |
||
| 657 | draw_listed_segments(*grd_curcanv, GroupList[current_group].segments, GROUP_COLOR); |
||
| 658 | } |
||
| 659 | } |
||
| 660 | |||
| 661 | |||
| 662 | static void draw_special_segments(void) |
||
| 663 | { |
||
| 664 | // Highlight matcens, fuelcens, etc. |
||
| 665 | range_for (const auto &&segp, vcsegptr) |
||
| 666 | { |
||
| 667 | if (segp->segnum != segment_none) |
||
| 668 | { |
||
| 669 | unsigned r, g, b; |
||
| 670 | switch(segp->special) |
||
| 671 | { |
||
| 672 | case SEGMENT_IS_FUELCEN: |
||
| 673 | r = 29 * 2, g = 27 * 2, b = 13 * 2; |
||
| 674 | break; |
||
| 675 | case SEGMENT_IS_CONTROLCEN: |
||
| 676 | r = 29 * 2, g = 0, b = 0; |
||
| 677 | break; |
||
| 678 | case SEGMENT_IS_ROBOTMAKER: |
||
| 679 | r = 29 * 2, g = 0, b = 31 * 2; |
||
| 680 | break; |
||
| 681 | default: |
||
| 682 | continue; |
||
| 683 | } |
||
| 684 | const auto color = gr_find_closest_color(r, g, b); |
||
| 685 | draw_segment(*grd_curcanv, segp, color); |
||
| 686 | } |
||
| 687 | } |
||
| 688 | } |
||
| 689 | |||
| 690 | |||
| 691 | //find a free vertex. returns the vertex number |
||
| 692 | static int alloc_vert() |
||
| 693 | { |
||
| 694 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 695 | int vn; |
||
| 696 | |||
| 697 | const auto Num_vertices = LevelSharedVertexState.Num_vertices; |
||
| 698 | assert(Num_vertices < MAX_SEGMENT_VERTICES); |
||
| 699 | |||
| 700 | auto &Vertex_active = LevelSharedVertexState.get_vertex_active(); |
||
| 701 | for (vn=0; (vn < Num_vertices) && Vertex_active[vn]; vn++) ; |
||
| 702 | |||
| 703 | Vertex_active[vn] = 1; |
||
| 704 | |||
| 705 | ++LevelSharedVertexState.Num_vertices; |
||
| 706 | |||
| 707 | return vn; |
||
| 708 | } |
||
| 709 | |||
| 710 | //frees a vertex |
||
| 711 | static void free_vert(int vert_num) |
||
| 712 | { |
||
| 713 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 714 | auto &Vertex_active = LevelSharedVertexState.get_vertex_active(); |
||
| 715 | Vertex_active[vert_num] = 0; |
||
| 716 | --LevelSharedVertexState.Num_vertices; |
||
| 717 | } |
||
| 718 | |||
| 719 | // ----------------------------------------------------------------------------- |
||
| 720 | static void draw_coordinate_axes(void) |
||
| 721 | { |
||
| 722 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
| 723 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
| 724 | std::array<unsigned, 16> Axes_verts; |
||
| 725 | vms_vector tvec; |
||
| 726 | |||
| 727 | range_for (auto &i, Axes_verts) |
||
| 728 | i = alloc_vert(); |
||
| 729 | |||
| 730 | create_coordinate_axes_from_segment(Cursegp,Axes_verts); |
||
| 731 | |||
| 732 | auto &vcvertptr = Vertices.vcptr; |
||
| 733 | auto &vmvertptr = Vertices.vmptr; |
||
| 734 | const auto &&av0 = vcvertptr(Axes_verts[0]); |
||
| 735 | const auto &&av1 = vcvertptr(Axes_verts[1]); |
||
| 736 | const auto &&av2 = vcvertptr(Axes_verts[2]); |
||
| 737 | const auto &&av3 = vcvertptr(Axes_verts[3]); |
||
| 738 | const auto &&av4 = vmvertptr(Axes_verts[4]); |
||
| 739 | const auto &&av6 = vmvertptr(Axes_verts[6]); |
||
| 740 | const auto &&av9 = vmvertptr(Axes_verts[9]); |
||
| 741 | const auto &&av10 = vmvertptr(Axes_verts[10]); |
||
| 742 | const auto &&av11 = vmvertptr(Axes_verts[11]); |
||
| 743 | const auto &&av12 = vmvertptr(Axes_verts[12]); |
||
| 744 | const auto &&av14 = vmvertptr(Axes_verts[14]); |
||
| 745 | const auto &&xvec = vm_vec_sub(av1, av0); |
||
| 746 | const auto &&yvec = vm_vec_sub(av2, av0); |
||
| 747 | const auto &&zvec = vm_vec_sub(av3, av0); |
||
| 748 | |||
| 749 | // Create the letter X |
||
| 750 | tvec = xvec; |
||
| 751 | vm_vec_add(av4, av1, vm_vec_scale(tvec, F1_0 / 16)); |
||
| 752 | tvec = yvec; |
||
| 753 | vm_vec_add2(av4, vm_vec_scale(tvec, F1_0 / 8)); |
||
| 754 | vm_vec_sub(av6, av4, vm_vec_scale(tvec, F2_0)); |
||
| 755 | tvec = xvec; |
||
| 756 | vm_vec_scale(tvec, F1_0 / 8); |
||
| 757 | vm_vec_add(vmvertptr(Axes_verts[7]), av4, tvec); |
||
| 758 | vm_vec_add(vmvertptr(Axes_verts[5]), av6, tvec); |
||
| 759 | |||
| 760 | // Create the letter Y |
||
| 761 | tvec = yvec; |
||
| 762 | vm_vec_add(av11, av2, vm_vec_scale(tvec, F1_0 / 16)); |
||
| 763 | vm_vec_add(vmvertptr(Axes_verts[8]), av11, tvec); |
||
| 764 | vm_vec_add(av9, av11, vm_vec_scale(tvec, F1_0 * 2)); |
||
| 765 | vm_vec_add(av10, av11, tvec); |
||
| 766 | tvec = xvec; |
||
| 767 | vm_vec_scale(tvec, F1_0 / 16); |
||
| 768 | vm_vec_sub2(av9, tvec); |
||
| 769 | vm_vec_add2(av10, tvec); |
||
| 770 | |||
| 771 | // Create the letter Z |
||
| 772 | tvec = zvec; |
||
| 773 | vm_vec_add(av12, av3, vm_vec_scale(tvec, F1_0 / 16)); |
||
| 774 | tvec = yvec; |
||
| 775 | vm_vec_add2(av12, vm_vec_scale(tvec, F1_0 / 8)); |
||
| 776 | vm_vec_sub(av14, av12, vm_vec_scale(tvec, F2_0)); |
||
| 777 | tvec = zvec; |
||
| 778 | vm_vec_scale(tvec, F1_0 / 8); |
||
| 779 | vm_vec_add(vmvertptr(Axes_verts[13]), av12, tvec); |
||
| 780 | vm_vec_add(vmvertptr(Axes_verts[15]), av14, tvec); |
||
| 781 | |||
| 782 | rotate_list(vcvertptr, Axes_verts); |
||
| 783 | |||
| 784 | const color_palette_index color = AXIS_COLOR; |
||
| 785 | |||
| 786 | draw_line(*grd_curcanv, Axes_verts[0], Axes_verts[1], color); |
||
| 787 | draw_line(*grd_curcanv, Axes_verts[0], Axes_verts[2], color); |
||
| 788 | draw_line(*grd_curcanv, Axes_verts[0], Axes_verts[3], color); |
||
| 789 | |||
| 790 | // draw the letter X |
||
| 791 | draw_line(*grd_curcanv, Axes_verts[4], Axes_verts[5], color); |
||
| 792 | draw_line(*grd_curcanv, Axes_verts[6], Axes_verts[7], color); |
||
| 793 | |||
| 794 | // draw the letter Y |
||
| 795 | draw_line(*grd_curcanv, Axes_verts[8], Axes_verts[9], color); |
||
| 796 | draw_line(*grd_curcanv, Axes_verts[8], Axes_verts[10], color); |
||
| 797 | draw_line(*grd_curcanv, Axes_verts[8], Axes_verts[11], color); |
||
| 798 | |||
| 799 | // draw the letter Z |
||
| 800 | draw_line(*grd_curcanv, Axes_verts[12], Axes_verts[13], color); |
||
| 801 | draw_line(*grd_curcanv, Axes_verts[13], Axes_verts[14], color); |
||
| 802 | draw_line(*grd_curcanv, Axes_verts[14], Axes_verts[15], color); |
||
| 803 | |||
| 804 | range_for (auto &i, Axes_verts) |
||
| 805 | free_vert(i); |
||
| 806 | } |
||
| 807 | |||
| 808 | void draw_world(grs_canvas *screen_canvas,editor_view *v,const vmsegptridx_t mine_ptr,int depth) |
||
| 809 | { |
||
| 810 | vms_vector viewer_position; |
||
| 811 | |||
| 812 | gr_set_current_canvas(screen_canvas); |
||
| 813 | |||
| 814 | viewer_position = v->ev_matrix.fvec; |
||
| 815 | vm_vec_scale(viewer_position,-v->ev_dist); |
||
| 816 | |||
| 817 | vm_vec_add2(viewer_position,Ed_view_target); |
||
| 818 | |||
| 819 | gr_clear_canvas(*grd_curcanv, 0); |
||
| 820 | g3_start_frame(*grd_curcanv); |
||
| 821 | g3_set_view_matrix(viewer_position,v->ev_matrix,v->ev_zoom); |
||
| 822 | |||
| 823 | render_start_frame(); |
||
| 824 | |||
| 825 | // Draw all segments or only connected segments. |
||
| 826 | // We might want to draw all segments if we have broken the mine into pieces. |
||
| 827 | if (Draw_all_segments) |
||
| 828 | draw_mine_all(Automap_test); |
||
| 829 | else |
||
| 830 | draw_mine(mine_ptr,depth); |
||
| 831 | |||
| 832 | // Draw the found segments |
||
| 833 | if (!Automap_test) { |
||
| 834 | draw_warning_segments(); |
||
| 835 | draw_group_segments(); |
||
| 836 | draw_found_segments(); |
||
| 837 | draw_selected_segments(); |
||
| 838 | draw_special_segments(); |
||
| 839 | |||
| 840 | // Highlight group segment and side. |
||
| 841 | if (current_group > -1) |
||
| 842 | if (Groupsegp[current_group]) { |
||
| 843 | draw_segment(*grd_curcanv, vcsegptr(Groupsegp[current_group]), GROUPSEG_COLOR); |
||
| 844 | draw_seg_side(vcsegptr(Groupsegp[current_group]), Groupside[current_group], GROUPSIDE_COLOR); |
||
| 845 | } |
||
| 846 | |||
| 847 | // Highlight marked segment and side. |
||
| 848 | if (Markedsegp) { |
||
| 849 | draw_segment(*grd_curcanv, Markedsegp, MARKEDSEG_COLOR); |
||
| 850 | draw_seg_side(Markedsegp,Markedside, MARKEDSIDE_COLOR); |
||
| 851 | } |
||
| 852 | |||
| 853 | // Highlight current segment and current side. |
||
| 854 | draw_segment(*grd_curcanv, Cursegp, CURSEG_COLOR); |
||
| 855 | |||
| 856 | draw_seg_side(Cursegp,Curside, CURSIDE_COLOR); |
||
| 857 | draw_side_edge(Cursegp,Curside,Curedge, CUREDGE_COLOR); |
||
| 858 | |||
| 859 | // Draw coordinate axes if we are rendering the large view. |
||
| 860 | if (Show_axes_flag) |
||
| 861 | if (screen_canvas == LargeViewBox->canvas.get()) |
||
| 862 | draw_coordinate_axes(); |
||
| 863 | |||
| 864 | // Label the window |
||
| 865 | gr_set_fontcolor(*grd_curcanv, (v==current_view)?CRED:CWHITE, -1); |
||
| 866 | if ( screen_canvas == LargeViewBox->canvas.get() ) { |
||
| 867 | gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 5, 5, "USER VIEW"); |
||
| 868 | switch (Large_view_index) { |
||
| 869 | case 0: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- TOP"); break; |
||
| 870 | case 1: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- FRONT"); break; |
||
| 871 | case 2: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- RIGHT"); break; |
||
| 872 | } |
||
| 873 | } else |
||
| 874 | #if ORTHO_VIEWS |
||
| 875 | else if ( screen_canvas == TopViewBox->canvas ) |
||
| 876 | gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 5, 5, "TOP"); |
||
| 877 | else if ( screen_canvas == FrontViewBox->canvas ) |
||
| 878 | gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 5, 5, "FRONT"); |
||
| 879 | else if ( screen_canvas == RightViewBox->canvas ) |
||
| 880 | gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 5, 5, "RIGHT"); |
||
| 881 | #else |
||
| 882 | Error("Ortho views have been removed, what gives?\n"); |
||
| 883 | #endif |
||
| 884 | |||
| 885 | } |
||
| 886 | |||
| 887 | g3_end_frame(); |
||
| 888 | |||
| 889 | } |
||
| 890 | |||
| 891 | //find the segments that render at a given screen x,y |
||
| 892 | //parms other than x,y are like draw_world |
||
| 893 | //fills in globals N_found_segs & Found_segs |
||
| 894 | void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,const vmsegptridx_t mine_ptr,int depth) |
||
| 895 | { |
||
| 896 | vms_vector viewer_position; |
||
| 897 | |||
| 898 | gr_set_current_canvas(screen_canvas); |
||
| 899 | |||
| 900 | viewer_position = v->ev_matrix.fvec; |
||
| 901 | vm_vec_scale(viewer_position,-v->ev_dist); |
||
| 902 | |||
| 903 | vm_vec_add2(viewer_position,Ed_view_target); |
||
| 904 | |||
| 905 | g3_start_frame(*grd_curcanv); |
||
| 906 | g3_set_view_matrix(viewer_position,v->ev_matrix,v->ev_zoom); |
||
| 907 | |||
| 908 | render_start_frame(); |
||
| 909 | |||
| 910 | #if DXX_USE_OGL |
||
| 911 | g3_end_frame(); |
||
| 912 | #endif |
||
| 913 | uint8_t color = 0; |
||
| 914 | gr_pixel(grd_curcanv->cv_bitmap, x, y, color); //set our search pixel to color zero |
||
| 915 | #if DXX_USE_OGL |
||
| 916 | g3_start_frame(*grd_curcanv); |
||
| 917 | #endif |
||
| 918 | |||
| 919 | Search_mode = -1; |
||
| 920 | Found_segs.clear(); |
||
| 921 | Search_x = x; Search_y = y; |
||
| 922 | |||
| 923 | if (Draw_all_segments) |
||
| 924 | draw_mine_all(0); |
||
| 925 | else |
||
| 926 | draw_mine(mine_ptr,depth); |
||
| 927 | |||
| 928 | g3_end_frame(); |
||
| 929 | |||
| 930 | Search_mode = 0; |
||
| 931 | |||
| 932 | } |
||
| 933 | |||
| 934 | namespace dsx { |
||
| 935 | void meddraw_init_views( grs_canvas * canvas) |
||
| 936 | { |
||
| 937 | #if defined(DXX_BUILD_DESCENT_II) |
||
| 938 | // sticking these here so the correct D2 colors are used |
||
| 939 | edge_colors[0] = BM_XRGB(45/2,45/2,45/2); |
||
| 940 | edge_colors[1] = BM_XRGB(45/3,45/3,45/3); //BM_RGB(0,0,45), // |
||
| 941 | edge_colors[2] = BM_XRGB(45/4,45/4,45/4); //BM_RGB(0,45,0)}; // |
||
| 942 | #endif |
||
| 943 | |||
| 944 | Views[0]->ev_canv = canvas; |
||
| 945 | #if ORTHO_VIEWS |
||
| 946 | Views[1]->ev_canv = TopViewBox->canvas; |
||
| 947 | Views[2]->ev_canv = FrontViewBox->canvas; |
||
| 948 | Views[3]->ev_canv = RightViewBox->canvas; |
||
| 949 | #endif |
||
| 950 | } |
||
| 951 | } |