add history to guides

This commit is contained in:
2019-06-19 17:55:35 +02:00
parent 6058f05d3f
commit 9ad3c351ce
7 changed files with 395 additions and 11 deletions

View File

@@ -433,7 +433,33 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
glm::vec2 fb_pos;
if (Canvas::I->point_trace(loc, ro, rd, hit_o, fb_pos, hit_d, m_plane_id))
{
m_lines.push_back({ hit_o, hit_d });
m_action = std::make_unique<ActionModeGrid>();
m_action->m_mode = this;
m_action->m_highlight = m_highlight;
m_action->m_selected_index = m_selected_index;
m_action->m_lines = m_lines;
int select = -1;
for (int i = 0; i < m_lines.size(); i++)
{
auto const& l = m_lines[i];
float d = lines_distance(ro, ro+rd*10.f, l.o-l.d*10.f, l.o+l.d*10.f);
if (d < 0.03f)
select = i;
}
if (select == -1)
{
m_lines.push_back({ hit_o, hit_d });
m_selected_index = (int)m_lines.size() - 1;
m_highlight = false;
m_added = true;
}
else
{
m_selected_index = select;
m_highlight = true;
m_added = false;
}
origin = hit_o;
dir = hit_d;
m_dragging = true;
@@ -443,6 +469,7 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
case kEventType::MouseUpL:
node->mouse_release();
m_dragging = false;
ActionManager::add(m_action.release());
//commit();
break;
case kEventType::MouseMove:
@@ -451,7 +478,7 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
glm::vec2 hit_fb;
if (m_dragging && Canvas::I->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, m_plane_id))
{
m_lines.back() = { hit_o, hit_d };
m_lines[m_selected_index] = { hit_o, hit_d };
origin = hit_o;
dir = hit_d;
m_dragging = true;
@@ -459,7 +486,7 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
break;
}
case kEventType::MouseCancel:
if (m_dragging)
if (m_dragging && m_selected_index == m_lines.size() - 1)
m_lines.pop_back();
m_dragging = false;
node->mouse_release();
@@ -471,14 +498,16 @@ void CanvasModeGrid::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
void CanvasModeGrid::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
{
//if (m_dragging)
for (auto l : m_lines)
const glm::vec4 blue(0, 0, 1, 1);
const glm::vec4 red(1, 0, 0, 1);
for (int i = 0; i < m_lines.size(); i++)
{
auto const& l = m_lines[i];
auto origin = l.o;
auto dir = l.d;
ShaderManager::use(kShader::Color);
ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera);
ShaderManager::u_vec4(kShaderUniform::Col, {1, 0, 0, 1});
ShaderManager::u_vec4(kShaderUniform::Col, m_highlight && i == m_selected_index ? blue : red);
static glm::vec4 AB[2];
AB[0] = {origin - dir * 10.f, 1};
AB[1] = {origin + dir * 10.f, 1 };
@@ -512,6 +541,41 @@ void CanvasModeGrid::clear()
m_lines.clear();
}
void CanvasModeGrid::on_KeyEvent(KeyEvent* ke)
{
if ((ke->m_key == kKey::KeyBackspace || ke->m_key == kKey::KeyDel)
&& ke->m_type == kEventType::KeyUp)
{
if (m_highlight)
{
auto a = new ActionModeGrid;
a->m_mode = this;
a->m_highlight = m_highlight;
a->m_selected_index = m_selected_index;
a->m_lines = m_lines;
ActionManager::add(a);
m_lines.erase(m_lines.begin() + m_selected_index);
m_highlight = false;
}
}
}
Action* ActionModeGrid::get_redo()
{
auto a = new ActionModeGrid;
a->m_mode = m_mode;
a->m_highlight = m_mode->m_highlight;
a->m_selected_index = m_mode->m_selected_index;
a->m_lines = m_mode->m_lines;
return a;
}
void ActionModeGrid::undo()
{
m_mode->m_highlight = m_highlight;
m_mode->m_selected_index = m_selected_index;
m_mode->m_lines = m_lines;
}
////////////////////////////////////////////////////////////////////
void CanvasModeMaskFree::init()

View File

@@ -3,6 +3,7 @@
#include "shape.h"
#include "brush.h"
#include "texture.h"
#include "action.h"
#include <poly2tri.h>
enum class kCanvasMode
@@ -106,6 +107,7 @@ public:
virtual void leave(kCanvasMode next) override;
};
struct ray_t { glm::vec3 o, d; };
class CanvasModeGrid : public CanvasMode
{
LineSegment m_line;
@@ -113,15 +115,30 @@ class CanvasModeGrid : public CanvasMode
glm::vec3 dir;
int m_plane_id;
bool m_dragging = false;
struct ray_t { glm::vec3 o, d; };
std::vector<ray_t> m_lines;
bool m_added = false;
std::unique_ptr<class ActionModeGrid> m_action;
public:
bool m_highlight = false;
int m_selected_index;
std::vector<ray_t> m_lines;
virtual void on_MouseEvent(MouseEvent* me, glm::vec2& loc) override;
virtual void on_KeyEvent(KeyEvent* ke) override;
virtual void on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) override;
virtual void init() override;
void commit();
void clear();
};
struct ActionModeGrid : public Action
{
CanvasModeGrid* m_mode;
bool m_highlight;
int m_selected_index;
std::vector<ray_t> m_lines;
virtual void run() override { }
virtual Action* get_redo() override;
virtual void undo() override;
virtual size_t memory() override { return 0; }
};
class CanvasModeCamera : public CanvasMode
{

View File

@@ -74,6 +74,7 @@ enum class kKey : uint8_t
KeyTab,
KeyEnter,
KeyBackspace,
KeyDel,
};
enum class kEventResult : uint8_t

View File

@@ -191,7 +191,7 @@ kKey convert_key(int key)
CASE(kVK_Return, kKey::KeyEnter);
CASE(kVK_Tab, kKey::KeyTab);
CASE(kVK_Space, kKey::Unknown);
CASE(kVK_Delete, kKey::Unknown);
CASE(kVK_Delete, kKey::KeyDel);
CASE(kVK_Escape, kKey::Unknown);
CASE(kVK_Command, kKey::KeyCtrl);
CASE(kVK_Shift, kKey::KeyShift);
@@ -277,7 +277,7 @@ kKey convert_key(int key)
CASE(VK_EXECUTE, kKey::Unknown);
CASE(VK_SNAPSHOT, kKey::Unknown);
CASE(VK_INSERT, kKey::Unknown);
CASE(VK_DELETE, kKey::Unknown);
CASE(VK_DELETE, kKey::KeyDel);
CASE(VK_HELP, kKey::Unknown);
CASE('0', kKey::Key0);
CASE('1', kKey::Key1);
@@ -432,6 +432,230 @@ kKey convert_key(int key)
CASE(VK_NONAME, kKey::Unknown);
CASE(VK_PA1, kKey::Unknown);
CASE(VK_OEM_CLEAR, kKey::Unknown);
#elif defined(__ANDROID__)
CASE(AKEYCODE_UNKNOWN, kKey::Unknown);
CASE(AKEYCODE_SOFT_LEFT, kKey::Unknown);
CASE(AKEYCODE_SOFT_RIGHT, kKey::Unknown);
CASE(AKEYCODE_HOME, kKey::AndroidHome);
CASE(AKEYCODE_BACK, kKey::AndroidBack);
CASE(AKEYCODE_CALL, kKey::Unknown);
CASE(AKEYCODE_ENDCALL, kKey::Unknown);
CASE(AKEYCODE_0, kKey::Unknown);
CASE(AKEYCODE_1, kKey::Unknown);
CASE(AKEYCODE_2, kKey::Unknown);
CASE(AKEYCODE_3, kKey::Unknown);
CASE(AKEYCODE_4, kKey::Unknown);
CASE(AKEYCODE_5, kKey::Unknown);
CASE(AKEYCODE_6, kKey::Unknown);
CASE(AKEYCODE_7, kKey::Unknown);
CASE(AKEYCODE_8, kKey::Unknown);
CASE(AKEYCODE_9, kKey::Unknown);
CASE(AKEYCODE_STAR, kKey::Unknown);
CASE(AKEYCODE_POUND, kKey::Unknown);
CASE(AKEYCODE_DPAD_UP, kKey::Unknown);
CASE(AKEYCODE_DPAD_DOWN, kKey::Unknown);
CASE(AKEYCODE_DPAD_LEFT, kKey::Unknown);
CASE(AKEYCODE_DPAD_RIGHT, kKey::Unknown);
CASE(AKEYCODE_DPAD_CENTER, kKey::Unknown);
CASE(AKEYCODE_VOLUME_UP, kKey::AndroidVolumeUp);
CASE(AKEYCODE_VOLUME_DOWN, kKey::AndroidVolumeDown);
CASE(AKEYCODE_POWER, kKey::Unknown);
CASE(AKEYCODE_CAMERA, kKey::Unknown);
CASE(AKEYCODE_CLEAR, kKey::Unknown);
CASE(AKEYCODE_A, kKey::Unknown);
CASE(AKEYCODE_B, kKey::Unknown);
CASE(AKEYCODE_C, kKey::Unknown);
CASE(AKEYCODE_D, kKey::Unknown);
CASE(AKEYCODE_E, kKey::Unknown);
CASE(AKEYCODE_F, kKey::Unknown);
CASE(AKEYCODE_G, kKey::Unknown);
CASE(AKEYCODE_H, kKey::Unknown);
CASE(AKEYCODE_I, kKey::Unknown);
CASE(AKEYCODE_J, kKey::Unknown);
CASE(AKEYCODE_K, kKey::Unknown);
CASE(AKEYCODE_L, kKey::Unknown);
CASE(AKEYCODE_M, kKey::Unknown);
CASE(AKEYCODE_N, kKey::Unknown);
CASE(AKEYCODE_O, kKey::Unknown);
CASE(AKEYCODE_P, kKey::Unknown);
CASE(AKEYCODE_Q, kKey::Unknown);
CASE(AKEYCODE_R, kKey::Unknown);
CASE(AKEYCODE_S, kKey::Unknown);
CASE(AKEYCODE_T, kKey::Unknown);
CASE(AKEYCODE_U, kKey::Unknown);
CASE(AKEYCODE_V, kKey::Unknown);
CASE(AKEYCODE_W, kKey::Unknown);
CASE(AKEYCODE_X, kKey::Unknown);
CASE(AKEYCODE_Y, kKey::Unknown);
CASE(AKEYCODE_Z, kKey::Unknown);
CASE(AKEYCODE_COMMA, kKey::Unknown);
CASE(AKEYCODE_PERIOD, kKey::Unknown);
CASE(AKEYCODE_ALT_LEFT, kKey::Unknown);
CASE(AKEYCODE_ALT_RIGHT, kKey::Unknown);
CASE(AKEYCODE_SHIFT_LEFT, kKey::Unknown);
CASE(AKEYCODE_SHIFT_RIGHT, kKey::Unknown);
CASE(AKEYCODE_TAB, kKey::Unknown);
CASE(AKEYCODE_SPACE, kKey::Unknown);
CASE(AKEYCODE_SYM, kKey::Unknown);
CASE(AKEYCODE_EXPLORER, kKey::Unknown);
CASE(AKEYCODE_ENVELOPE, kKey::Unknown);
CASE(AKEYCODE_ENTER, kKey::KeyEnter);
CASE(AKEYCODE_DEL, kKey::KeyBackspace);
CASE(AKEYCODE_GRAVE, kKey::Unknown);
CASE(AKEYCODE_MINUS, kKey::Unknown);
CASE(AKEYCODE_EQUALS, kKey::Unknown);
CASE(AKEYCODE_LEFT_BRACKET, kKey::Unknown);
CASE(AKEYCODE_RIGHT_BRACKET, kKey::Unknown);
CASE(AKEYCODE_BACKSLASH, kKey::Unknown);
CASE(AKEYCODE_SEMICOLON, kKey::Unknown);
CASE(AKEYCODE_APOSTROPHE, kKey::Unknown);
CASE(AKEYCODE_SLASH, kKey::Unknown);
CASE(AKEYCODE_AT, kKey::Unknown);
CASE(AKEYCODE_NUM, kKey::Unknown);
CASE(AKEYCODE_HEADSETHOOK, kKey::Unknown);
CASE(AKEYCODE_FOCUS, kKey::Unknown);
CASE(AKEYCODE_PLUS, kKey::Unknown);
CASE(AKEYCODE_MENU, kKey::Unknown);
CASE(AKEYCODE_NOTIFICATION, kKey::Unknown);
CASE(AKEYCODE_SEARCH, kKey::Unknown);
CASE(AKEYCODE_MEDIA_PLAY_PAUSE, kKey::Unknown);
CASE(AKEYCODE_MEDIA_STOP, kKey::Unknown);
CASE(AKEYCODE_MEDIA_NEXT, kKey::Unknown);
CASE(AKEYCODE_MEDIA_PREVIOUS, kKey::Unknown);
CASE(AKEYCODE_MEDIA_REWIND, kKey::Unknown);
CASE(AKEYCODE_MEDIA_FAST_FORWARD, kKey::Unknown);
CASE(AKEYCODE_MUTE, kKey::Unknown);
CASE(AKEYCODE_PAGE_UP, kKey::Unknown);
CASE(AKEYCODE_PAGE_DOWN, kKey::Unknown);
CASE(AKEYCODE_PICTSYMBOLS, kKey::Unknown);
CASE(AKEYCODE_SWITCH_CHARSET, kKey::Unknown);
CASE(AKEYCODE_BUTTON_A, kKey::Unknown);
CASE(AKEYCODE_BUTTON_B, kKey::Unknown);
CASE(AKEYCODE_BUTTON_C, kKey::Unknown);
CASE(AKEYCODE_BUTTON_X, kKey::Unknown);
CASE(AKEYCODE_BUTTON_Y, kKey::Unknown);
CASE(AKEYCODE_BUTTON_Z, kKey::Unknown);
CASE(AKEYCODE_BUTTON_L1, kKey::Unknown);
CASE(AKEYCODE_BUTTON_R1, kKey::Unknown);
CASE(AKEYCODE_BUTTON_L2, kKey::Unknown);
CASE(AKEYCODE_BUTTON_R2, kKey::Unknown);
CASE(AKEYCODE_BUTTON_THUMBL, kKey::Unknown);
CASE(AKEYCODE_BUTTON_THUMBR, kKey::Unknown);
CASE(AKEYCODE_BUTTON_START, kKey::Unknown);
CASE(AKEYCODE_BUTTON_SELECT, kKey::Unknown);
CASE(AKEYCODE_BUTTON_MODE, kKey::Unknown);
CASE(AKEYCODE_ESCAPE, kKey::Unknown);
CASE(AKEYCODE_FORWARD_DEL, kKey::Unknown);
CASE(AKEYCODE_CTRL_LEFT, kKey::Unknown);
CASE(AKEYCODE_CTRL_RIGHT, kKey::Unknown);
CASE(AKEYCODE_CAPS_LOCK, kKey::Unknown);
CASE(AKEYCODE_SCROLL_LOCK, kKey::Unknown);
CASE(AKEYCODE_META_LEFT, kKey::Unknown);
CASE(AKEYCODE_META_RIGHT, kKey::Unknown);
CASE(AKEYCODE_FUNCTION, kKey::Unknown);
CASE(AKEYCODE_SYSRQ, kKey::Unknown);
CASE(AKEYCODE_BREAK, kKey::Unknown);
CASE(AKEYCODE_MOVE_HOME, kKey::Unknown);
CASE(AKEYCODE_MOVE_END, kKey::Unknown);
CASE(AKEYCODE_INSERT, kKey::Unknown);
CASE(AKEYCODE_FORWARD, kKey::Unknown);
CASE(AKEYCODE_MEDIA_PLAY, kKey::Unknown);
CASE(AKEYCODE_MEDIA_PAUSE, kKey::Unknown);
CASE(AKEYCODE_MEDIA_CLOSE, kKey::Unknown);
CASE(AKEYCODE_MEDIA_EJECT, kKey::Unknown);
CASE(AKEYCODE_MEDIA_RECORD, kKey::Unknown);
CASE(AKEYCODE_F1, kKey::Unknown);
CASE(AKEYCODE_F2, kKey::Unknown);
CASE(AKEYCODE_F3, kKey::Unknown);
CASE(AKEYCODE_F4, kKey::Unknown);
CASE(AKEYCODE_F5, kKey::Unknown);
CASE(AKEYCODE_F6, kKey::Unknown);
CASE(AKEYCODE_F7, kKey::Unknown);
CASE(AKEYCODE_F8, kKey::Unknown);
CASE(AKEYCODE_F9, kKey::Unknown);
CASE(AKEYCODE_F10, kKey::Unknown);
CASE(AKEYCODE_F11, kKey::Unknown);
CASE(AKEYCODE_F12, kKey::Unknown);
CASE(AKEYCODE_NUM_LOCK, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_0, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_1, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_2, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_3, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_4, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_5, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_6, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_7, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_8, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_9, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_DIVIDE, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_MULTIPLY, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_SUBTRACT, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_ADD, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_DOT, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_COMMA, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_ENTER, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_EQUALS, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_LEFT_PAREN, kKey::Unknown);
CASE(AKEYCODE_NUMPAD_RIGHT_PAREN, kKey::Unknown);
CASE(AKEYCODE_VOLUME_MUTE, kKey::Unknown);
CASE(AKEYCODE_INFO, kKey::Unknown);
CASE(AKEYCODE_CHANNEL_UP, kKey::Unknown);
CASE(AKEYCODE_CHANNEL_DOWN, kKey::Unknown);
CASE(AKEYCODE_ZOOM_IN, kKey::Unknown);
CASE(AKEYCODE_ZOOM_OUT, kKey::Unknown);
CASE(AKEYCODE_TV, kKey::Unknown);
CASE(AKEYCODE_WINDOW, kKey::Unknown);
CASE(AKEYCODE_GUIDE, kKey::Unknown);
CASE(AKEYCODE_DVR, kKey::Unknown);
CASE(AKEYCODE_BOOKMARK, kKey::Unknown);
CASE(AKEYCODE_CAPTIONS, kKey::Unknown);
CASE(AKEYCODE_SETTINGS, kKey::Unknown);
CASE(AKEYCODE_TV_POWER, kKey::Unknown);
CASE(AKEYCODE_TV_INPUT, kKey::Unknown);
CASE(AKEYCODE_STB_POWER, kKey::Unknown);
CASE(AKEYCODE_STB_INPUT, kKey::Unknown);
CASE(AKEYCODE_AVR_POWER, kKey::Unknown);
CASE(AKEYCODE_AVR_INPUT, kKey::Unknown);
CASE(AKEYCODE_PROG_RED, kKey::Unknown);
CASE(AKEYCODE_PROG_GREEN, kKey::Unknown);
CASE(AKEYCODE_PROG_YELLOW, kKey::Unknown);
CASE(AKEYCODE_PROG_BLUE, kKey::Unknown);
CASE(AKEYCODE_APP_SWITCH, kKey::Unknown);
CASE(AKEYCODE_BUTTON_1, kKey::Unknown);
CASE(AKEYCODE_BUTTON_2, kKey::Unknown);
CASE(AKEYCODE_BUTTON_3, kKey::Unknown);
CASE(AKEYCODE_BUTTON_4, kKey::Unknown);
CASE(AKEYCODE_BUTTON_5, kKey::Unknown);
CASE(AKEYCODE_BUTTON_6, kKey::Unknown);
CASE(AKEYCODE_BUTTON_7, kKey::Unknown);
CASE(AKEYCODE_BUTTON_8, kKey::Unknown);
CASE(AKEYCODE_BUTTON_9, kKey::Unknown);
CASE(AKEYCODE_BUTTON_10, kKey::Unknown);
CASE(AKEYCODE_BUTTON_11, kKey::Unknown);
CASE(AKEYCODE_BUTTON_12, kKey::Unknown);
CASE(AKEYCODE_BUTTON_13, kKey::Unknown);
CASE(AKEYCODE_BUTTON_14, kKey::Unknown);
CASE(AKEYCODE_BUTTON_15, kKey::Unknown);
CASE(AKEYCODE_BUTTON_16, kKey::Unknown);
CASE(AKEYCODE_LANGUAGE_SWITCH, kKey::Unknown);
CASE(AKEYCODE_MANNER_MODE, kKey::Unknown);
CASE(AKEYCODE_3D_MODE, kKey::Unknown);
CASE(AKEYCODE_CONTACTS, kKey::Unknown);
CASE(AKEYCODE_CALENDAR, kKey::Unknown);
CASE(AKEYCODE_MUSIC, kKey::Unknown);
CASE(AKEYCODE_CALCULATOR, kKey::Unknown);
CASE(AKEYCODE_ZENKAKU_HANKAKU, kKey::Unknown);
CASE(AKEYCODE_EISU, kKey::Unknown);
CASE(AKEYCODE_MUHENKAN, kKey::Unknown);
CASE(AKEYCODE_HENKAN, kKey::Unknown);
CASE(AKEYCODE_KATAKANA_HIRAGANA, kKey::Unknown);
CASE(AKEYCODE_YEN, kKey::Unknown);
CASE(AKEYCODE_RO, kKey::Unknown);
CASE(AKEYCODE_KANA, kKey::Unknown);
CASE(AKEYCODE_ASSIST, kKey::Unknown);
CASE(AKEYCODE_BRIGHTNESS_DOWN, kKey::Unknown);
CASE(AKEYCODE_BRIGHTNESS_UP, kKey::Unknown);
CASE(AKEYCODE_MEDIA_AUDIO_TRACK, kKey::Unknown);
#endif
default:
return kKey::Unknown;

View File

@@ -584,7 +584,9 @@ kEventResult NodeCanvas::handle_event(Event* e)
ActionManager::undo();
if (ke->m_key == kKey::KeyAlt && m_mouse_focus)
App::I.show_cursor();
break;
for (auto& mode : *m_canvas->m_mode)
mode->on_KeyEvent(ke);
break;
case kEventType::KeyUp:
if (ke->m_key == kKey::KeyAlt && m_mouse_focus)
m_canvas->m_current_mode == kCanvasMode::Draw ||
@@ -618,6 +620,8 @@ kEventResult NodeCanvas::handle_event(Event* e)
App::I.dialog_save_ver();
}
}
for (auto& mode : *m_canvas->m_mode)
mode->on_KeyEvent(ke);
break;
case kEventType::GestureStart:
mouse_capture();

View File

@@ -75,6 +75,76 @@ bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_orig
return true;
};
// see: http://geomalgorithms.com/a07-_distance.html
// dist3D_Line_to_Line(): get the 3D minimum distance between 2 lines
// Input: two 3D lines L1 and L2
// Return: the shortest distance between L1 and L2
float lines_distance(const glm::vec3& p0a, const glm::vec3& p0b,
const glm::vec3& p1a, const glm::vec3& p1b)
{
glm::vec3 u = p0b - p0a;
glm::vec3 v = p1b - p1a;
glm::vec3 w = p0a - p1a;
float a = glm::dot(u,u); // always >= 0
float b = glm::dot(u,v);
float c = glm::dot(v,v); // always >= 0
float d = glm::dot(u,w);
float e = glm::dot(v,w);
float D = a*c - b*b; // always >= 0
float sc, tc;
// compute the line parameters of the two closest points
if (D < 0.00001f) { // the lines are almost parallel
sc = 0.0;
tc = (b>c ? d/b : e/c); // use the largest denominator
}
else {
sc = (b*e - c*d) / D;
tc = (a*e - b*d) / D;
}
// get the difference of the two closest points
glm::vec3 dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
return glm::length(dP); // return the closest distance
}
bool segments_intersect_3d(const glm::vec3& p0a, const glm::vec3& p0b,
const glm::vec3& p1a, const glm::vec3& p1b, glm::vec3& out_pt, glm::vec2& out_hit_uv)
{
float denom = ((p1b.y - p1a.y)*(p0b.x - p0a.x)) -
((p1b.x - p1a.x)*(p0b.y - p0a.y));
float nume_a = ((p1b.x - p1a.x)*(p0a.y - p1a.y)) -
((p1b.y - p1a.y)*(p0b.x - p1a.x));
float nume_b = ((p0b.x - p0a.x)*(p0a.y - p1a.y)) -
((p0b.y - p0a.y)*(p0a.x - p1a.x));
if(denom == 0.0f)
{
if(nume_a == 0.0f && nume_b == 0.0f)
{
return 0;//COINCIDENT;
}
return 0;//PARALLEL;
}
float ua = nume_a / denom;
float ub = nume_b / denom;
if(ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
{
// Get the intersection point.
out_pt.x = p0a.x + ua*(p0b.x - p0a.x);
out_pt.y = p0a.y + ua*(p0b.y - p0a.y);
return 1;//INTERESECTING;
}
return 0;//NOT_INTERESECTING;
}
// see: https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
const glm::vec2& p1a, const glm::vec2& p1b, glm::vec2& out_pt, glm::vec2& out_hit_uv)

View File

@@ -57,6 +57,10 @@ glm::vec4 box_union(glm::vec4 a, glm::vec4 b);
glm::vec4 box_intersection(glm::vec4 a, glm::vec4 b);
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit, float& out_t);
float lines_distance(const glm::vec3& p0a, const glm::vec3& p0b,
const glm::vec3& p1a, const glm::vec3& p1b);
bool segments_intersect_3d(const glm::vec3& p0a, const glm::vec3& p0b,
const glm::vec3& p1a, const glm::vec3& p1b, glm::vec3& out_pt, glm::vec2& out_hit_uv);
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
const glm::vec2& p1a, const glm::vec2& p1b, glm::vec2& out_pt, glm::vec2& out_hit_uv);
bool point_side(glm::vec2 a, glm::vec2 b, glm::vec2 p);