2006-03-20 17:12:09 +00:00
|
|
|
/*
|
2014-06-01 17:55:23 +00:00
|
|
|
* Portions of this file are copyright Rebirth contributors and licensed as
|
|
|
|
* described in COPYING.txt.
|
|
|
|
* Portions of this file are copyright Parallax Software and licensed
|
|
|
|
* according to the Parallax license below.
|
|
|
|
* See COPYING.txt for license details.
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Med drawing functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-11-17 06:14:09 +00:00
|
|
|
#include <algorithm>
|
2006-03-20 17:12:09 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "inferno.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "segpoint.h"
|
|
|
|
#include "gameseg.h"
|
|
|
|
#include "gr.h"
|
|
|
|
#include "ui.h"
|
|
|
|
#include "editor/editor.h"
|
2013-03-16 03:10:55 +00:00
|
|
|
#include "editor/esegment.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "wall.h"
|
|
|
|
#include "switch.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "u_mem.h"
|
|
|
|
#include "render.h"
|
|
|
|
#include "func.h"
|
|
|
|
#include "textures.h"
|
|
|
|
#include "object.h"
|
2012-11-17 06:14:09 +00:00
|
|
|
#include "meddraw.h"
|
2016-12-11 01:56:44 +00:00
|
|
|
#include "d_enumerate.h"
|
2020-08-10 03:45:14 +00:00
|
|
|
#include "d_levelstate.h"
|
2019-05-04 18:27:36 +00:00
|
|
|
#include "d_range.h"
|
2013-12-21 05:12:38 +00:00
|
|
|
#include "compiler-range_for.h"
|
2014-08-02 16:41:31 +00:00
|
|
|
#include "segiter.h"
|
2019-05-04 18:27:36 +00:00
|
|
|
#include "d_zip.h"
|
2012-11-17 06:14:09 +00:00
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGL
|
2015-10-09 02:46:10 +00:00
|
|
|
#include "ogl_init.h"
|
|
|
|
#endif
|
|
|
|
|
2012-11-17 06:14:09 +00:00
|
|
|
using std::min;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// 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 )
|
|
|
|
|
2017-10-14 17:10:30 +00:00
|
|
|
constexpr std::integral_constant<unsigned, MAX_VERTICES * 4> MAX_EDGES{};
|
2016-08-19 03:41:41 +00:00
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
namespace {
|
|
|
|
|
2021-11-01 03:37:20 +00:00
|
|
|
enum class packed_edge : uint8_t
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
2013-06-30 20:59:51 +00:00
|
|
|
static int Search_mode=0; //if true, searching for segments at given x,y
|
|
|
|
static int Search_x,Search_y;
|
|
|
|
static int Automap_test=0; // Set to 1 to show wireframe in automap mode.
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-06-24 05:06:14 +00:00
|
|
|
static void draw_seg_objects(grs_canvas &canvas, const unique_segment &seg)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2019-03-03 00:31:08 +00:00
|
|
|
auto &Objects = LevelUniqueObjectState.Objects;
|
|
|
|
auto &vcobjptridx = Objects.vcptridx;
|
2018-06-24 05:06:14 +00:00
|
|
|
range_for (const auto obj, objects_in(seg, vcobjptridx, vcsegptr))
|
2014-08-02 16:41:31 +00:00
|
|
|
{
|
2014-11-13 03:41:29 +00:00
|
|
|
auto sphere_point = g3_rotate_point(obj->pos);
|
2018-05-05 22:33:56 +00:00
|
|
|
const uint8_t color = (obj->type == OBJ_PLAYER && static_cast<icobjptridx_t::index_type>(obj) > 0)
|
2016-02-12 04:02:28 +00:00
|
|
|
? BM_XRGB(0, 25, 0)
|
|
|
|
: (obj == ConsoleObject
|
|
|
|
? PLAYER_COLOR
|
|
|
|
: ROBOT_COLOR
|
|
|
|
);
|
2018-06-24 05:06:14 +00:00
|
|
|
g3_draw_sphere(canvas, sphere_point, obj->size, color);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-05 17:44:52 +00:00
|
|
|
static void draw_line(const g3_draw_line_context &context, const vertnum_t pnum0, const vertnum_t pnum1)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line(context, Segment_points[pnum0], Segment_points[pnum1]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2022-06-05 17:44:52 +00:00
|
|
|
static void draw_segment(const g3_draw_line_context &context, const shared_segment &seg)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
2018-09-19 02:13:29 +00:00
|
|
|
if (seg.segnum == segment_none) //this segment doesn't exitst
|
2006-03-20 17:12:09 +00:00
|
|
|
return;
|
|
|
|
|
2018-09-19 02:13:29 +00:00
|
|
|
auto &svp = seg.verts;
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2022-01-09 15:25:42 +00:00
|
|
|
for (const uint8_t i : xrange(4u))
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, svp[(segment_relative_vertnum{i})], svp[(segment_relative_vertnum{static_cast<uint8_t>(i + 4)})]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2022-01-09 15:25:42 +00:00
|
|
|
for (const uint8_t i : xrange(3u))
|
2016-05-21 17:24:51 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, svp[(segment_relative_vertnum{i})], svp[(segment_relative_vertnum{static_cast<uint8_t>(i + 1)})]);
|
|
|
|
draw_line(context, svp[(segment_relative_vertnum{static_cast<uint8_t>(i + 4)})], svp[(segment_relative_vertnum{static_cast<uint8_t>(i + 4 + 1)})]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, svp[segment_relative_vertnum::_0], svp[segment_relative_vertnum::_3]);
|
|
|
|
draw_line(context, svp[segment_relative_vertnum::_4], svp[segment_relative_vertnum::_7]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//for looking for segment under a mouse click
|
2017-06-10 03:31:02 +00:00
|
|
|
static void check_segment(const vmsegptridx_t seg)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-08-12 03:01:14 +00:00
|
|
|
auto &svp = seg->verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGL
|
2012-04-15 05:45:45 +00:00
|
|
|
g3_end_frame();
|
|
|
|
#endif
|
2016-05-21 17:24:51 +00:00
|
|
|
{
|
2016-02-12 04:02:28 +00:00
|
|
|
uint8_t color = 0;
|
2017-03-11 19:56:23 +00:00
|
|
|
gr_pixel(grd_curcanv->cv_bitmap, Search_x, Search_y, color); //set our search pixel to color zero
|
2016-05-21 17:24:51 +00:00
|
|
|
}
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGL
|
2017-02-11 21:42:34 +00:00
|
|
|
g3_start_frame(*grd_curcanv);
|
2012-04-15 05:45:45 +00:00
|
|
|
#endif
|
2016-02-12 04:02:28 +00:00
|
|
|
{
|
|
|
|
const uint8_t color = 1;
|
2016-02-12 04:02:28 +00:00
|
|
|
//and render in color one
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-02-14 22:48:27 +00:00
|
|
|
range_for (auto &fn, Side_to_verts)
|
|
|
|
{
|
2020-05-02 21:18:42 +00:00
|
|
|
std::array<cg3s_point *, 3> vert_list;
|
2022-01-15 20:39:10 +00:00
|
|
|
vert_list[0] = &Segment_points[seg->verts[fn[side_relative_vertnum::_0]]];
|
|
|
|
vert_list[1] = &Segment_points[seg->verts[fn[side_relative_vertnum::_1]]];
|
|
|
|
vert_list[2] = &Segment_points[seg->verts[fn[side_relative_vertnum::_2]]];
|
2017-02-11 21:42:42 +00:00
|
|
|
g3_check_and_draw_poly(*grd_curcanv, vert_list, color);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2022-01-15 20:39:10 +00:00
|
|
|
vert_list[1] = &Segment_points[seg->verts[fn[side_relative_vertnum::_2]]];
|
|
|
|
vert_list[2] = &Segment_points[seg->verts[fn[side_relative_vertnum::_3]]];
|
2017-02-11 21:42:42 +00:00
|
|
|
g3_check_and_draw_poly(*grd_curcanv, vert_list, color);
|
2016-02-12 04:02:28 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2014-11-30 22:09:18 +00:00
|
|
|
if (gr_ugpixel(grd_curcanv->cv_bitmap,Search_x,Search_y) == 1)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-10-02 03:02:34 +00:00
|
|
|
Found_segs.emplace_back(seg);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2022-01-09 15:25:42 +00:00
|
|
|
static void draw_seg_side(const shared_segment &seg, const sidenum_t side, const color_palette_index color)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &svp = seg.verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2016-02-12 04:02:28 +00:00
|
|
|
auto &stv = Side_to_verts[side];
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, color};
|
2022-01-15 20:39:10 +00:00
|
|
|
for (const auto i : MAX_VERTICES_PER_SIDE)
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, svp[stv[i]], svp[stv[next_side_vertex(i)]]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-15 20:39:10 +00:00
|
|
|
static void draw_side_edge(const shared_segment &seg, const sidenum_t side, const side_relative_vertnum edge, const color_palette_index color)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &svp = seg.verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand) //on screen?
|
2016-02-12 04:02:28 +00:00
|
|
|
{
|
|
|
|
auto &stv = Side_to_verts[side];
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(g3_draw_line_context{*grd_curcanv, color}, svp[stv[edge]], svp[stv[next_side_vertex(edge)]]);
|
2016-02-12 04:02:28 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
__attribute__((used))
|
2006-03-20 17:12:09 +00:00
|
|
|
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
|
|
|
|
|
2013-11-28 00:23:55 +00:00
|
|
|
static
|
|
|
|
#if defined(DXX_BUILD_DESCENT_I)
|
2021-11-01 03:37:20 +00:00
|
|
|
constexpr
|
2013-11-28 00:23:55 +00:00
|
|
|
#endif
|
2020-07-16 02:31:04 +00:00
|
|
|
std::array<color_palette_index, 3> edge_colors{{54, 59, 64}};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2013-12-22 22:03:07 +00:00
|
|
|
struct seg_edge
|
|
|
|
{
|
2020-12-26 21:17:29 +00:00
|
|
|
vertnum_t v0, v1;
|
2006-03-20 17:12:09 +00:00
|
|
|
ushort type;
|
|
|
|
ubyte face_count, backface_count;
|
2013-12-22 22:03:07 +00:00
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2020-05-02 21:18:42 +00:00
|
|
|
static std::array<seg_edge, MAX_EDGES> edge_list;
|
|
|
|
static std::array<int, MAX_EDGES> used_list; //which entries in edge_list have been used
|
2017-08-26 19:47:51 +00:00
|
|
|
static int n_used;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-12-11 01:56:44 +00:00
|
|
|
static unsigned edge_list_size; //set each frame
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2021-11-01 03:37:20 +00:00
|
|
|
static constexpr packed_edge pack_edge(const unsigned a, const unsigned b)
|
|
|
|
{
|
|
|
|
return static_cast<packed_edge>((a << 3) | b);
|
|
|
|
}
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
//define edge numberings
|
2021-11-01 03:37:20 +00:00
|
|
|
constexpr std::array<packed_edge, 24> edges = {{
|
|
|
|
pack_edge(0, 1), // edge 0
|
|
|
|
pack_edge(0, 3), // edge 1
|
|
|
|
pack_edge(0, 4), // edge 2
|
|
|
|
pack_edge(1, 2), // edge 3
|
|
|
|
pack_edge(1, 5), // edge 4
|
|
|
|
pack_edge(2, 3), // edge 5
|
|
|
|
pack_edge(2, 6), // edge 6
|
|
|
|
pack_edge(3, 7), // edge 7
|
|
|
|
pack_edge(4, 5), // edge 8
|
|
|
|
pack_edge(4, 7), // edge 9
|
|
|
|
pack_edge(5, 6), // edge 10
|
|
|
|
pack_edge(6, 7), // edge 11
|
|
|
|
|
|
|
|
pack_edge(0, 5), // right cross
|
|
|
|
pack_edge(0, 7), // top cross
|
|
|
|
pack_edge(1, 3), // front cross
|
|
|
|
pack_edge(2, 5), // bottom cross
|
|
|
|
pack_edge(2, 7), // left cross
|
|
|
|
pack_edge(4, 6), // back cross
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//crosses going the other way
|
|
|
|
|
2021-11-01 03:37:20 +00:00
|
|
|
pack_edge(1, 4), // other right cross
|
|
|
|
pack_edge(3, 4), // other top cross
|
|
|
|
pack_edge(0, 2), // other front cross
|
|
|
|
pack_edge(1, 6), // other bottom cross
|
|
|
|
pack_edge(3, 6), // other left cross
|
|
|
|
pack_edge(5, 7), // other back cross
|
|
|
|
}};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
#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)
|
|
|
|
|
|
|
|
//given two vertex numbers on a segment (range 0..7), tell what edge number it is
|
2022-01-09 15:25:42 +00:00
|
|
|
static std::size_t find_edge_num(const segment_relative_vertnum ev0, const segment_relative_vertnum ev1)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-12-26 21:17:29 +00:00
|
|
|
const auto &&[v0, v1] = std::minmax(ev0, ev1);
|
2022-01-09 15:25:42 +00:00
|
|
|
const auto vv = pack_edge(static_cast<uint8_t>(v0), static_cast<uint8_t>(v1));
|
2021-11-01 03:37:20 +00:00
|
|
|
const auto iter = std::find(edges.begin(), edges.end(), vv);
|
|
|
|
return std::distance(edges.begin(), iter);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//finds edge, filling in edge_ptr. if found old edge, returns index, else return -1
|
2020-12-26 21:17:29 +00:00
|
|
|
static std::pair<seg_edge &, std::size_t> find_edge(const vertnum_t v0, const vertnum_t v1)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-12-26 21:17:29 +00:00
|
|
|
const auto &&hash_object = std::hash<vertnum_t>{};
|
|
|
|
const auto initial_hash_slot = (hash_object(v0) ^ (hash_object(v1) << 10)) % edge_list_size;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
for (auto current_hash_slot = initial_hash_slot;;)
|
|
|
|
{
|
|
|
|
auto &e = edge_list[current_hash_slot];
|
|
|
|
if (e.type == ET_EMPTY)
|
|
|
|
return {e, UINT32_MAX};
|
|
|
|
else if (e.v0 == v0 && e.v1 == v1)
|
|
|
|
return {e, current_hash_slot};
|
2006-03-20 17:12:09 +00:00
|
|
|
else {
|
2020-12-26 21:17:29 +00:00
|
|
|
if (++ current_hash_slot == edge_list_size)
|
|
|
|
current_hash_slot = 0;
|
|
|
|
if (current_hash_slot == initial_hash_slot)
|
|
|
|
throw std::runtime_error("edge list full: search wrapped without finding a free slot");
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//adds an edge to the edge list
|
2020-12-26 21:17:29 +00:00
|
|
|
static void add_edge(const vertnum_t ev0, const vertnum_t ev1, const uint8_t type)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-12-26 21:17:29 +00:00
|
|
|
const auto &&[v0, v1] = std::minmax(ev0, ev1);
|
|
|
|
auto &&[e, current_hash_slot] = find_edge(v0, v1);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
if (current_hash_slot == UINT32_MAX)
|
|
|
|
{
|
|
|
|
e.v0 = v0;
|
|
|
|
e.v1 = v1;
|
|
|
|
e.type = type;
|
|
|
|
used_list[n_used] = &e - edge_list.begin();
|
2006-03-20 17:12:09 +00:00
|
|
|
if (type == ET_FACING)
|
2020-12-26 21:17:29 +00:00
|
|
|
e.face_count++;
|
2006-03-20 17:12:09 +00:00
|
|
|
else if (type == ET_NOTFACING)
|
2020-12-26 21:17:29 +00:00
|
|
|
e.backface_count++;
|
2006-03-20 17:12:09 +00:00
|
|
|
n_used++;
|
|
|
|
} else {
|
2020-12-26 21:17:29 +00:00
|
|
|
if (e.type > type)
|
|
|
|
e.type = type;
|
2006-03-20 17:12:09 +00:00
|
|
|
if (type == ET_FACING)
|
2020-12-26 21:17:29 +00:00
|
|
|
e.face_count++;
|
2006-03-20 17:12:09 +00:00
|
|
|
else if (type == ET_NOTFACING)
|
2020-12-26 21:17:29 +00:00
|
|
|
e.backface_count++;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//adds a segment's edges to the edge list
|
2018-12-13 02:31:38 +00:00
|
|
|
static void add_edges(const shared_segment &seg)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-13 02:31:38 +00:00
|
|
|
auto &svp = seg.verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2016-12-11 01:56:44 +00:00
|
|
|
int i,fn,vn;
|
2006-03-20 17:12:09 +00:00
|
|
|
int flag;
|
2021-11-01 03:37:20 +00:00
|
|
|
std::array<uint8_t, std::size(edges)> edge_flags;
|
2006-03-20 17:12:09 +00:00
|
|
|
for (i=0;i<N_NORMAL_EDGES;i++) edge_flags[i]=ET_NOTUSED;
|
|
|
|
for (;i<N_EDGES_PER_SEGMENT;i++) edge_flags[i]=ET_NOTEXTANT;
|
|
|
|
|
2021-06-28 03:37:50 +00:00
|
|
|
for (auto &&[idx, sidep] : enumerate(seg.sides))
|
2016-12-11 01:56:44 +00:00
|
|
|
{
|
2014-12-14 05:23:00 +00:00
|
|
|
int num_vertices;
|
2022-01-15 20:39:10 +00:00
|
|
|
const auto &&[num_faces, vertex_list] = create_all_vertex_lists(seg, sidep, idx);
|
2006-03-20 17:12:09 +00:00
|
|
|
if (num_faces == 1)
|
|
|
|
num_vertices = 4;
|
|
|
|
else
|
|
|
|
num_vertices = 3;
|
|
|
|
|
|
|
|
for (fn=0; fn<num_faces; fn++) {
|
|
|
|
//Note: normal check appears to be the wrong way since the normals points in, but we're looking from the outside
|
2018-12-13 02:31:38 +00:00
|
|
|
if (g3_check_normal_facing(vcvertptr(seg.verts[vertex_list[fn*3]]), sidep.normals[fn]))
|
2006-03-20 17:12:09 +00:00
|
|
|
flag = ET_NOTFACING;
|
|
|
|
else
|
|
|
|
flag = ET_FACING;
|
|
|
|
|
2014-12-14 05:23:00 +00:00
|
|
|
auto v0 = &vertex_list[fn*3];
|
2006-03-20 17:12:09 +00:00
|
|
|
for (vn=0; vn<num_vertices-1; vn++) {
|
2021-11-01 03:37:20 +00:00
|
|
|
if (const auto en = find_edge_num(*v0, *(v0 + 1)); en != edges.size())
|
2006-03-20 17:12:09 +00:00
|
|
|
if (flag < edge_flags[en]) edge_flags[en] = flag;
|
|
|
|
|
|
|
|
v0++;
|
|
|
|
}
|
2021-11-01 03:37:20 +00:00
|
|
|
if (const auto en = find_edge_num(*v0, vertex_list[fn * 3]); en != edges.size())
|
2006-03-20 17:12:09 +00:00
|
|
|
if (flag < edge_flags[en]) edge_flags[en] = flag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<N_EDGES_PER_SEGMENT; i++)
|
|
|
|
if (i<N_NORMAL_EDGES || (edge_flags[i]!=ET_NOTEXTANT && Show_triangulations))
|
2022-01-09 15:25:42 +00:00
|
|
|
{
|
|
|
|
const uint8_t e0 = static_cast<uint8_t>(edges[i]) >> 3;
|
|
|
|
const uint8_t e1 = static_cast<uint8_t>(edges[i]) & 7;
|
|
|
|
add_edge(seg.verts[(segment_relative_vertnum{e0})], seg.verts[(segment_relative_vertnum{e1})], edge_flags[i]);
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2022-01-09 15:25:42 +00:00
|
|
|
static void draw_trigger_side(const shared_segment &seg, const sidenum_t side, const color_palette_index color)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-13 02:31:38 +00:00
|
|
|
auto &svp = seg.verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2006-03-20 17:12:09 +00:00
|
|
|
// Draw diagonals
|
2016-02-12 04:02:28 +00:00
|
|
|
auto &stv = Side_to_verts[side];
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(g3_draw_line_context{*grd_curcanv, color}, svp[stv[side_relative_vertnum::_0]], svp[stv[side_relative_vertnum::_2]]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2022-01-09 15:25:42 +00:00
|
|
|
static void draw_wall_side(const shared_segment &seg, const sidenum_t side, const color_palette_index color)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-13 02:31:38 +00:00
|
|
|
auto &svp = seg.verts;
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
2018-12-30 00:43:57 +00:00
|
|
|
if (!rotate_list(vcvertptr, svp).uand)
|
2015-10-18 21:01:18 +00:00
|
|
|
{ //all off screen?
|
2006-03-20 17:12:09 +00:00
|
|
|
// Draw diagonals
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, color};
|
2016-02-12 04:02:28 +00:00
|
|
|
auto &stv = Side_to_verts[side];
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, svp[stv[side_relative_vertnum::_0]], svp[stv[side_relative_vertnum::_2]]);
|
|
|
|
draw_line(context, svp[stv[side_relative_vertnum::_1]], svp[stv[side_relative_vertnum::_3]]);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-26 03:45:07 +00:00
|
|
|
#define WALL_BLASTABLE_COLOR rgb_t{31, 0, 0} // RED
|
|
|
|
#define WALL_DOOR_COLOR rgb_t{0, 0, 31} // DARK BLUE
|
|
|
|
#define WALL_DOOR_LOCKED_COLOR rgb_t{0, 0, 63} // BLUE
|
|
|
|
#define WALL_AUTO_DOOR_COLOR rgb_t{0, 31, 0} // DARK GREEN
|
|
|
|
#define WALL_AUTO_DOOR_LOCKED_COLOR rgb_t{0, 63, 0} // GREEN
|
|
|
|
#define WALL_ILLUSION_COLOR rgb_t{63, 0, 63} // PURPLE
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
#define TRIGGER_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------
|
|
|
|
// Draws special walls (for now these are just removable walls.)
|
2022-01-09 15:25:42 +00:00
|
|
|
static void draw_special_wall(const shared_segment &seg, const sidenum_t side)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-12-30 00:43:58 +00:00
|
|
|
auto &Walls = LevelUniqueWallSubsystemState.Walls;
|
|
|
|
auto &vcwallptr = Walls.vcptr;
|
2018-12-13 02:31:38 +00:00
|
|
|
auto &w = *vcwallptr(seg.sides[side].wall_num);
|
2016-01-26 03:45:07 +00:00
|
|
|
const auto get_color = [=]() {
|
2016-02-12 04:02:28 +00:00
|
|
|
const auto type = w.type;
|
2016-01-26 03:45:07 +00:00
|
|
|
if (type != WALL_OPEN)
|
|
|
|
{
|
2016-02-12 04:02:28 +00:00
|
|
|
const auto flags = w.flags;
|
2021-11-01 03:37:19 +00:00
|
|
|
if (flags & wall_flag::door_locked)
|
|
|
|
return (flags & wall_flag::door_auto) ? WALL_AUTO_DOOR_LOCKED_COLOR : WALL_DOOR_LOCKED_COLOR;
|
|
|
|
if (flags & wall_flag::door_auto)
|
2016-01-26 03:45:07 +00:00
|
|
|
return WALL_AUTO_DOOR_COLOR;
|
|
|
|
if (type == WALL_BLASTABLE)
|
|
|
|
return WALL_BLASTABLE_COLOR;
|
|
|
|
if (type == WALL_DOOR)
|
|
|
|
return WALL_DOOR_COLOR;
|
|
|
|
if (type == WALL_ILLUSION)
|
|
|
|
return WALL_ILLUSION_COLOR;
|
|
|
|
}
|
2016-01-26 03:45:07 +00:00
|
|
|
return rgb_t{45, 45, 45};
|
2016-01-26 03:45:07 +00:00
|
|
|
};
|
|
|
|
const auto color = get_color();
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_wall_side(seg,side, gr_find_closest_color(color.r, color.g, color.b));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-02-12 04:02:28 +00:00
|
|
|
if (w.trigger != trigger_none)
|
|
|
|
{
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_trigger_side(seg,side, TRIGGER_COLOR);
|
2011-09-26 23:31:19 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------
|
|
|
|
// Recursively parse mine structure, drawing segments.
|
2017-06-10 03:31:02 +00:00
|
|
|
static void draw_mine_sub(const vmsegptridx_t segnum,int depth, visited_segment_bitarray_t &visited)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2013-12-18 23:38:05 +00:00
|
|
|
if (visited[segnum]) return; // If segment already drawn, return.
|
|
|
|
visited[segnum] = true; // Say that this segment has been drawn.
|
2014-10-02 03:02:34 +00:00
|
|
|
auto mine_ptr = segnum;
|
2006-03-20 17:12:09 +00:00
|
|
|
// If this segment is active, process it, else skip it.
|
|
|
|
|
2013-12-26 22:21:16 +00:00
|
|
|
if (mine_ptr->segnum != segment_none) {
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
if (Search_mode) check_segment(mine_ptr);
|
|
|
|
else add_edges(mine_ptr); //add this segments edges to list
|
|
|
|
|
|
|
|
if (depth != 0) {
|
2019-05-04 18:27:36 +00:00
|
|
|
const shared_segment &sseg = *mine_ptr;
|
2020-05-02 21:18:43 +00:00
|
|
|
for (const auto &&[idx, child_segnum, sside] : enumerate(zip(sseg.children, sseg.sides)))
|
2019-05-04 18:27:36 +00:00
|
|
|
{
|
2015-12-22 04:18:51 +00:00
|
|
|
if (IS_CHILD(child_segnum))
|
|
|
|
{
|
2019-05-04 18:27:36 +00:00
|
|
|
if (sside.wall_num != wall_none)
|
2022-01-09 15:25:42 +00:00
|
|
|
draw_special_wall(mine_ptr, static_cast<sidenum_t>(idx));
|
2015-12-22 04:18:51 +00:00
|
|
|
draw_mine_sub(segnum.absolute_sibling(child_segnum), depth-1, visited);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_mine_edges(int automap_flag)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
int i,type;
|
|
|
|
seg_edge *e;
|
|
|
|
|
|
|
|
for (type=ET_NOTUSED;type>=ET_FACING;type--) {
|
2016-02-12 04:02:28 +00:00
|
|
|
const auto color = edge_colors[type];
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, color};
|
2006-03-20 17:12:09 +00:00
|
|
|
for (i=0;i<n_used;i++) {
|
|
|
|
e = &edge_list[used_list[i]];
|
|
|
|
if (e->type == type)
|
|
|
|
if ((!automap_flag) || (e->face_count == 1))
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, e->v0, e->v1);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-11 01:56:44 +00:00
|
|
|
static void clear_edge_list()
|
|
|
|
{
|
|
|
|
range_for (auto &i, partial_range(edge_list, edge_list_size))
|
|
|
|
{
|
|
|
|
i.type = ET_EMPTY;
|
|
|
|
i.face_count = 0;
|
|
|
|
i.backface_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
//draws an entire mine
|
2017-06-10 03:31:02 +00:00
|
|
|
static void draw_mine(const vmsegptridx_t mine_ptr,int depth)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2013-12-18 23:38:05 +00:00
|
|
|
visited_segment_bitarray_t visited;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-09-19 02:13:29 +00:00
|
|
|
edge_list_size = min(LevelSharedSegmentState.Num_segments * 12, MAX_EDGES.value); //make maybe smaller than max
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// clear edge list
|
2016-12-11 01:56:44 +00:00
|
|
|
clear_edge_list();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
n_used = 0;
|
|
|
|
|
2014-10-02 03:02:34 +00:00
|
|
|
draw_mine_sub(mine_ptr,depth, visited);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
draw_mine_edges(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Draw all segments, ignoring connectivity.
|
|
|
|
// A segment is drawn if its segnum != -1.
|
2015-07-13 01:09:36 +00:00
|
|
|
static void draw_mine_all(int automap_flag)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2018-09-19 02:13:29 +00:00
|
|
|
edge_list_size = min(LevelSharedSegmentState.Num_segments * 12, MAX_EDGES.value); //make maybe smaller than max
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// clear edge list
|
2016-12-11 01:56:44 +00:00
|
|
|
clear_edge_list();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
n_used = 0;
|
|
|
|
|
2017-06-10 03:31:02 +00:00
|
|
|
range_for (const auto &&segp, vmsegptridx)
|
2015-07-13 01:09:37 +00:00
|
|
|
{
|
|
|
|
if (segp->segnum != segment_none)
|
|
|
|
{
|
2021-06-28 03:37:50 +00:00
|
|
|
for (auto &&[idx, value] : enumerate(segp->shared_segment::sides))
|
|
|
|
if (value.wall_num != wall_none)
|
2022-01-15 20:39:10 +00:00
|
|
|
draw_special_wall(segp, idx);
|
2006-03-20 17:12:09 +00:00
|
|
|
if (Search_mode)
|
2015-07-13 01:09:37 +00:00
|
|
|
check_segment(segp);
|
2006-03-20 17:12:09 +00:00
|
|
|
else {
|
2015-07-13 01:09:37 +00:00
|
|
|
add_edges(segp);
|
2018-06-24 05:06:14 +00:00
|
|
|
draw_seg_objects(*grd_curcanv, segp);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-13 01:09:37 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
draw_mine_edges(automap_flag);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-05 17:44:52 +00:00
|
|
|
static void draw_listed_segments(g3_draw_line_context &context, count_segment_array_t &s)
|
2016-01-09 16:38:12 +00:00
|
|
|
{
|
|
|
|
range_for (const auto &ss, s)
|
|
|
|
{
|
|
|
|
const auto &&segp = vcsegptr(ss);
|
|
|
|
if (segp->segnum != segment_none)
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_segment(context, segp);
|
2016-01-09 16:38:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_selected_segments(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, SELECT_COLOR};
|
|
|
|
draw_listed_segments(context, Selected_segs);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_found_segments(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, FOUND_COLOR};
|
|
|
|
draw_listed_segments(context, Found_segs);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_warning_segments(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, WARNING_COLOR};
|
|
|
|
draw_listed_segments(context, Warning_segs);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_group_segments(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2022-06-05 17:44:52 +00:00
|
|
|
if (current_group > -1)
|
|
|
|
{
|
|
|
|
g3_draw_line_context context{*grd_curcanv, GROUP_COLOR};
|
|
|
|
draw_listed_segments(context, GroupList[current_group].segments);
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_special_segments(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
// Highlight matcens, fuelcens, etc.
|
2016-02-12 04:02:28 +00:00
|
|
|
range_for (const auto &&segp, vcsegptr)
|
2015-06-13 22:42:18 +00:00
|
|
|
{
|
|
|
|
if (segp->segnum != segment_none)
|
2016-02-11 03:25:52 +00:00
|
|
|
{
|
|
|
|
unsigned r, g, b;
|
2015-06-13 22:42:18 +00:00
|
|
|
switch(segp->special)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2021-11-01 03:37:19 +00:00
|
|
|
case segment_special::fuelcen:
|
2016-02-11 03:25:52 +00:00
|
|
|
r = 29 * 2, g = 27 * 2, b = 13 * 2;
|
2006-03-20 17:12:09 +00:00
|
|
|
break;
|
2021-11-01 03:37:19 +00:00
|
|
|
case segment_special::controlcen:
|
2016-02-11 03:25:52 +00:00
|
|
|
r = 29 * 2, g = 0, b = 0;
|
2006-03-20 17:12:09 +00:00
|
|
|
break;
|
2021-11-01 03:37:19 +00:00
|
|
|
case segment_special::robotmaker:
|
2016-02-11 03:25:52 +00:00
|
|
|
r = 29 * 2, g = 0, b = 31 * 2;
|
2006-03-20 17:12:09 +00:00
|
|
|
break;
|
2016-02-11 03:25:52 +00:00
|
|
|
default:
|
|
|
|
continue;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2016-02-11 03:25:52 +00:00
|
|
|
const auto color = gr_find_closest_color(r, g, b);
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, color};
|
|
|
|
draw_segment(context, segp);
|
2016-02-11 03:25:52 +00:00
|
|
|
}
|
2015-06-13 22:42:18 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//find a free vertex. returns the vertex number
|
2020-12-26 21:17:29 +00:00
|
|
|
static vertnum_t alloc_vert()
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-12-30 00:43:57 +00:00
|
|
|
const auto Num_vertices = LevelSharedVertexState.Num_vertices;
|
|
|
|
assert(Num_vertices < MAX_SEGMENT_VERTICES);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertex_active = LevelSharedVertexState.get_vertex_active();
|
2020-12-26 21:17:29 +00:00
|
|
|
vertnum_t vn{};
|
|
|
|
for (; static_cast<unsigned>(vn) < Num_vertices && Vertex_active[vn]; ++vn)
|
|
|
|
{
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
Vertex_active[vn] = 1;
|
|
|
|
|
2018-12-30 00:43:57 +00:00
|
|
|
++LevelSharedVertexState.Num_vertices;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
return vn;
|
|
|
|
}
|
|
|
|
|
|
|
|
//frees a vertex
|
2020-12-26 21:17:29 +00:00
|
|
|
static void free_vert(vertnum_t vert_num)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &Vertex_active = LevelSharedVertexState.get_vertex_active();
|
2006-03-20 17:12:09 +00:00
|
|
|
Vertex_active[vert_num] = 0;
|
2018-12-30 00:43:57 +00:00
|
|
|
--LevelSharedVertexState.Num_vertices;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
2013-10-27 22:00:14 +00:00
|
|
|
static void draw_coordinate_axes(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2020-05-17 23:35:25 +00:00
|
|
|
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
|
|
|
auto &Vertices = LevelSharedVertexState.get_vertices();
|
2020-12-26 21:17:29 +00:00
|
|
|
std::array<vertnum_t, 16> Axes_verts;
|
2014-10-29 03:24:31 +00:00
|
|
|
vms_vector tvec;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-12-11 01:56:44 +00:00
|
|
|
range_for (auto &i, Axes_verts)
|
|
|
|
i = alloc_vert();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
create_coordinate_axes_from_segment(Cursegp,Axes_verts);
|
|
|
|
|
2018-12-30 00:43:57 +00:00
|
|
|
auto &vcvertptr = Vertices.vcptr;
|
|
|
|
auto &vmvertptr = Vertices.vmptr;
|
2017-08-11 23:43:54 +00:00
|
|
|
const auto &&av0 = vcvertptr(Axes_verts[0]);
|
|
|
|
const auto &&av1 = vcvertptr(Axes_verts[1]);
|
|
|
|
const auto &&av2 = vcvertptr(Axes_verts[2]);
|
|
|
|
const auto &&av3 = vcvertptr(Axes_verts[3]);
|
|
|
|
const auto &&av4 = vmvertptr(Axes_verts[4]);
|
|
|
|
const auto &&av6 = vmvertptr(Axes_verts[6]);
|
|
|
|
const auto &&av9 = vmvertptr(Axes_verts[9]);
|
|
|
|
const auto &&av10 = vmvertptr(Axes_verts[10]);
|
|
|
|
const auto &&av11 = vmvertptr(Axes_verts[11]);
|
|
|
|
const auto &&av12 = vmvertptr(Axes_verts[12]);
|
|
|
|
const auto &&av14 = vmvertptr(Axes_verts[14]);
|
|
|
|
const auto &&xvec = vm_vec_sub(av1, av0);
|
|
|
|
const auto &&yvec = vm_vec_sub(av2, av0);
|
|
|
|
const auto &&zvec = vm_vec_sub(av3, av0);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// Create the letter X
|
|
|
|
tvec = xvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_add(av4, av1, vm_vec_scale(tvec, F1_0 / 16));
|
2006-03-20 17:12:09 +00:00
|
|
|
tvec = yvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_add2(av4, vm_vec_scale(tvec, F1_0 / 8));
|
|
|
|
vm_vec_sub(av6, av4, vm_vec_scale(tvec, F2_0));
|
2014-09-28 21:11:05 +00:00
|
|
|
tvec = xvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_scale(tvec, F1_0 / 8);
|
|
|
|
vm_vec_add(vmvertptr(Axes_verts[7]), av4, tvec);
|
|
|
|
vm_vec_add(vmvertptr(Axes_verts[5]), av6, tvec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// Create the letter Y
|
|
|
|
tvec = yvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_add(av11, av2, vm_vec_scale(tvec, F1_0 / 16));
|
|
|
|
vm_vec_add(vmvertptr(Axes_verts[8]), av11, tvec);
|
|
|
|
vm_vec_add(av9, av11, vm_vec_scale(tvec, F1_0 * 2));
|
|
|
|
vm_vec_add(av10, av11, tvec);
|
2014-09-28 21:11:05 +00:00
|
|
|
tvec = xvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_scale(tvec, F1_0 / 16);
|
|
|
|
vm_vec_sub2(av9, tvec);
|
|
|
|
vm_vec_add2(av10, tvec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// Create the letter Z
|
|
|
|
tvec = zvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_add(av12, av3, vm_vec_scale(tvec, F1_0 / 16));
|
2006-03-20 17:12:09 +00:00
|
|
|
tvec = yvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_add2(av12, vm_vec_scale(tvec, F1_0 / 8));
|
|
|
|
vm_vec_sub(av14, av12, vm_vec_scale(tvec, F2_0));
|
2014-09-28 21:11:05 +00:00
|
|
|
tvec = zvec;
|
2017-08-11 23:43:54 +00:00
|
|
|
vm_vec_scale(tvec, F1_0 / 8);
|
|
|
|
vm_vec_add(vmvertptr(Axes_verts[13]), av12, tvec);
|
|
|
|
vm_vec_add(vmvertptr(Axes_verts[15]), av14, tvec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-12-30 00:43:57 +00:00
|
|
|
rotate_list(vcvertptr, Axes_verts);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2020-07-16 02:31:04 +00:00
|
|
|
const color_palette_index color = AXIS_COLOR;
|
2022-06-05 17:44:52 +00:00
|
|
|
g3_draw_line_context context{*grd_curcanv, color};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, Axes_verts[0], Axes_verts[1]);
|
|
|
|
draw_line(context, Axes_verts[0], Axes_verts[2]);
|
|
|
|
draw_line(context, Axes_verts[0], Axes_verts[3]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// draw the letter X
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, Axes_verts[4], Axes_verts[5]);
|
|
|
|
draw_line(context, Axes_verts[6], Axes_verts[7]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// draw the letter Y
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, Axes_verts[8], Axes_verts[9]);
|
|
|
|
draw_line(context, Axes_verts[8], Axes_verts[10]);
|
|
|
|
draw_line(context, Axes_verts[8], Axes_verts[11]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// draw the letter Z
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_line(context, Axes_verts[12], Axes_verts[13]);
|
|
|
|
draw_line(context, Axes_verts[13], Axes_verts[14]);
|
|
|
|
draw_line(context, Axes_verts[14], Axes_verts[15]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-12-11 01:56:44 +00:00
|
|
|
range_for (auto &i, Axes_verts)
|
|
|
|
free_vert(i);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
}
|
|
|
|
|
2017-06-10 03:31:02 +00:00
|
|
|
void draw_world(grs_canvas *screen_canvas,editor_view *v,const vmsegptridx_t mine_ptr,int depth)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
vms_vector viewer_position;
|
|
|
|
|
|
|
|
gr_set_current_canvas(screen_canvas);
|
|
|
|
|
|
|
|
viewer_position = v->ev_matrix.fvec;
|
2014-09-28 21:11:05 +00:00
|
|
|
vm_vec_scale(viewer_position,-v->ev_dist);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-28 21:43:00 +00:00
|
|
|
vm_vec_add2(viewer_position,Ed_view_target);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-01-01 00:45:45 +00:00
|
|
|
gr_clear_canvas(*grd_curcanv, 0);
|
2017-02-11 21:42:34 +00:00
|
|
|
g3_start_frame(*grd_curcanv);
|
2014-10-26 22:01:00 +00:00
|
|
|
g3_set_view_matrix(viewer_position,v->ev_matrix,v->ev_zoom);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
render_start_frame();
|
|
|
|
|
|
|
|
// 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)
|
2015-07-13 01:09:36 +00:00
|
|
|
draw_mine_all(Automap_test);
|
2006-03-20 17:12:09 +00:00
|
|
|
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]) {
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_segment(g3_draw_line_context{*grd_curcanv, GROUPSEG_COLOR}, vcsegptr(Groupsegp[current_group]));
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_seg_side(vcsegptr(Groupsegp[current_group]), Groupside[current_group], GROUPSIDE_COLOR);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Highlight marked segment and side.
|
|
|
|
if (Markedsegp) {
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_segment(g3_draw_line_context{*grd_curcanv, MARKEDSEG_COLOR}, Markedsegp);
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_seg_side(Markedsegp,Markedside, MARKEDSIDE_COLOR);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Highlight current segment and current side.
|
2022-06-05 17:44:52 +00:00
|
|
|
draw_segment(g3_draw_line_context{*grd_curcanv, CURSEG_COLOR}, Cursegp);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_seg_side(Cursegp,Curside, CURSIDE_COLOR);
|
2016-02-12 04:02:28 +00:00
|
|
|
draw_side_edge(Cursegp,Curside,Curedge, CUREDGE_COLOR);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// Draw coordinate axes if we are rendering the large view.
|
|
|
|
if (Show_axes_flag)
|
2014-09-06 23:55:43 +00:00
|
|
|
if (screen_canvas == LargeViewBox->canvas.get())
|
2006-03-20 17:12:09 +00:00
|
|
|
draw_coordinate_axes();
|
|
|
|
|
|
|
|
// Label the window
|
2017-02-11 21:42:32 +00:00
|
|
|
gr_set_fontcolor(*grd_curcanv, (v==current_view)?CRED:CWHITE, -1);
|
2014-09-06 23:55:43 +00:00
|
|
|
if ( screen_canvas == LargeViewBox->canvas.get() ) {
|
2018-05-19 23:21:42 +00:00
|
|
|
gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 5, 5, "USER VIEW");
|
2006-03-20 17:12:09 +00:00
|
|
|
switch (Large_view_index) {
|
2018-05-19 23:21:42 +00:00
|
|
|
case 0: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- TOP"); break;
|
|
|
|
case 1: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- FRONT"); break;
|
|
|
|
case 2: gr_ustring(*grd_curcanv, *grd_curcanv->cv_font, 85, 5, "-- RIGHT"); break;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
Error("Ortho views have been removed, what gives?\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
g3_end_frame();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//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
|
2017-06-10 03:31:02 +00:00
|
|
|
void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,const vmsegptridx_t mine_ptr,int depth)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
vms_vector viewer_position;
|
|
|
|
|
|
|
|
gr_set_current_canvas(screen_canvas);
|
|
|
|
|
|
|
|
viewer_position = v->ev_matrix.fvec;
|
2014-09-28 21:11:05 +00:00
|
|
|
vm_vec_scale(viewer_position,-v->ev_dist);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-10-30 03:11:06 +00:00
|
|
|
vm_vec_add2(viewer_position,Ed_view_target);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-02-11 21:42:34 +00:00
|
|
|
g3_start_frame(*grd_curcanv);
|
2014-10-26 22:01:00 +00:00
|
|
|
g3_set_view_matrix(viewer_position,v->ev_matrix,v->ev_zoom);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
render_start_frame();
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGL
|
2012-04-15 05:45:45 +00:00
|
|
|
g3_end_frame();
|
|
|
|
#endif
|
2016-02-12 04:02:28 +00:00
|
|
|
uint8_t color = 0;
|
2017-03-11 19:56:23 +00:00
|
|
|
gr_pixel(grd_curcanv->cv_bitmap, x, y, color); //set our search pixel to color zero
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGL
|
2017-02-11 21:42:34 +00:00
|
|
|
g3_start_frame(*grd_curcanv);
|
2012-04-15 05:45:45 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
Search_mode = -1;
|
2013-12-11 23:59:36 +00:00
|
|
|
Found_segs.clear();
|
2006-03-20 17:12:09 +00:00
|
|
|
Search_x = x; Search_y = y;
|
|
|
|
|
|
|
|
if (Draw_all_segments)
|
2015-07-13 01:09:36 +00:00
|
|
|
draw_mine_all(0);
|
2006-03-20 17:12:09 +00:00
|
|
|
else
|
|
|
|
draw_mine(mine_ptr,depth);
|
|
|
|
|
|
|
|
g3_end_frame();
|
|
|
|
|
|
|
|
Search_mode = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-08-25 04:05:32 +00:00
|
|
|
namespace dsx {
|
2006-03-20 17:12:09 +00:00
|
|
|
void meddraw_init_views( grs_canvas * canvas)
|
|
|
|
{
|
2013-03-03 01:03:33 +00:00
|
|
|
#if defined(DXX_BUILD_DESCENT_II)
|
2012-04-14 10:52:06 +00:00
|
|
|
// sticking these here so the correct D2 colors are used
|
|
|
|
edge_colors[0] = BM_XRGB(45/2,45/2,45/2);
|
|
|
|
edge_colors[1] = BM_XRGB(45/3,45/3,45/3); //BM_RGB(0,0,45), //
|
|
|
|
edge_colors[2] = BM_XRGB(45/4,45/4,45/4); //BM_RGB(0,45,0)}; //
|
2013-03-03 01:03:33 +00:00
|
|
|
#endif
|
2012-04-14 10:52:06 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
Views[0]->ev_canv = canvas;
|
|
|
|
}
|
2016-08-25 04:05:32 +00:00
|
|
|
}
|