diff --git a/scripts/draw_corner/draw_corner.gml b/scripts/draw_corner/draw_corner.gml index 8e3d389fa..953885b76 100644 --- a/scripts/draw_corner/draw_corner.gml +++ b/scripts/draw_corner/draw_corner.gml @@ -52,12 +52,12 @@ function draw_corner(x1, y1, xc, yc, x3, y3, thick = 1, col = c_white, sample = draw_primitive_end(); } -function get_corner(x1, y1, xc, yc, x3, y3, sample = 10) { +function get_corner(x1, y1, xc, yc, x3, y3, sample = 10, thres = 8) { var dir0 = point_direction(x1, y1, xc, yc); var dir1 = point_direction(x3, y3, xc, yc); var dis = point_distance(x1, y1, x3, y3); - if(dis < 8) return [ [x1, y1], [x3, y3] ]; + if(dis < thres) return [ [x1, y1], [x3, y3] ]; var p2 = point_rotate(xc, yc, x1, y1, -90); var x2 = p2[0]; @@ -91,4 +91,17 @@ function get_corner(x1, y1, xc, yc, x3, y3, sample = 10) { } return pnt; +} + +function get_corner_radius(x1, y1, xc, yc, x3, y3, rad, sample = 10, thres = 8) { + var dir0 = point_direction(xc, yc, x1, y1); + var dir1 = point_direction(xc, yc, x3, y3); + + x1 = xc + lengthdir_x(rad, dir0); + y1 = yc + lengthdir_y(rad, dir0); + + x3 = xc + lengthdir_x(rad, dir1); + y3 = yc + lengthdir_y(rad, dir1); + + return get_corner(x1, y1, xc, yc, x3, y3, sample, thres); } \ No newline at end of file diff --git a/scripts/node_path_morph/node_path_morph.gml b/scripts/node_path_morph/node_path_morph.gml index 3f587e28f..984a0ceba 100644 --- a/scripts/node_path_morph/node_path_morph.gml +++ b/scripts/node_path_morph/node_path_morph.gml @@ -12,7 +12,7 @@ function Node_Path_Morph(_x, _y, _group = noone) : Node_Processor(_x, _y, _group newInput(2, nodeValue_Dimension(self)); - newInput(3, nodeValue_Int("Subdivision", self, 128)) + newInput(3, nodeValue_Int("Subdivision", self, 64)) .setValidator(VV_min(2)) .rejectArray(); @@ -52,22 +52,65 @@ function Node_Path_Morph(_x, _y, _group = noone) : Node_Processor(_x, _y, _group var _cur = _data[5]; var _mid = _data[6]; - var _p1 = array_create(_sub * 2); - var _p2 = array_create(_sub * 2); - var _isb = 1 / (_sub - 1); var _pp = new __vec2(); - for( var i = 0; i < _sub; i++ ) { - var _prog = frac(i * _isb); + if(_mid) { + var _p1 = array_create(_sub * 2); + var _p2 = array_create(_sub * 2); + var p1 = array_create(_sub); + var p2 = array_create(_sub); - _pp = _path1.getPointRatio(_prog, 0, _pp); - _p1[i * 2 + 0] = _pp.x; - _p1[i * 2 + 1] = _pp.y; + cx1 = 0; cy1 = 0; + cx2 = 0; cy2 = 0; - _pp = _path2.getPointRatio(_prog, 0, _pp); - _p2[i * 2 + 0] = _pp.x; - _p2[i * 2 + 1] = _pp.y; + for( var i = 0; i < _sub; i++ ) { + var _prog = frac(i * _isb); + + _pp = _path1.getPointRatio(_prog, 0, _pp); + p1[i] = [ _pp.x, _pp.y ]; + + cx1 += _pp.x; + cy1 += _pp.y; + + _pp = _path2.getPointRatio(_prog, 0, _pp); + p2[i] = [ _pp.x, _pp.y ]; + + cx2 += _pp.x; + cy2 += _pp.y; + } + + cx1 /= _sub; + cy1 /= _sub; + cx2 /= _sub; + cy2 /= _sub; + + // array_sort(p1, (a,b) => { return point_direction(cx1, cy1, a[0], a[1]) - point_direction(cx1, cy1, b[0], b[1]); }); + // array_sort(p2, (a,b) => { return point_direction(cx2, cy2, a[0], a[1]) - point_direction(cx2, cy2, b[0], b[1]); }); + + for( var i = 0; i < _sub; i++ ) { + _p1[i * 2 + 0] = p1[i][0]; + _p1[i * 2 + 1] = p1[i][1]; + + _p2[i * 2 + 0] = p2[i][0]; + _p2[i * 2 + 1] = p2[i][1]; + } + + } else { + var _p1 = array_create(_sub * 2); + var _p2 = array_create(_sub * 2); + + for( var i = 0; i < _sub; i++ ) { + var _prog = frac(i * _isb); + + _pp = _path1.getPointRatio(_prog, 0, _pp); + _p1[i * 2 + 0] = _pp.x; + _p1[i * 2 + 1] = _pp.y; + + _pp = _path2.getPointRatio(_prog, 0, _pp); + _p2[i * 2 + 0] = _pp.x; + _p2[i * 2 + 1] = _pp.y; + } } surface_set_shader(_outSurf, sh_path_morph); diff --git a/scripts/node_path_shape/node_path_shape.gml b/scripts/node_path_shape/node_path_shape.gml index 5a5e651b5..ed4e639ee 100644 --- a/scripts/node_path_shape/node_path_shape.gml +++ b/scripts/node_path_shape/node_path_shape.gml @@ -79,16 +79,6 @@ function Node_Path_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) construc _rat = frac(_rat); switch(shapeScroll[shape].name) { - case "Rectangle" : - case "Trapezoid" : - case "Parallelogram" : - var i = floor(_rat * 4); - var r = (_rat - i * .25) * 4; - - out.x = lerp(points[i * 2][0], points[i * 2 + 1][0], r); - out.y = lerp(points[i * 2][1], points[i * 2 + 1][1], r); - break; - case "Ellipse" : var a = 360 * _rat; out.x = posx + lengthdir_x(scax, a); @@ -109,6 +99,9 @@ function Node_Path_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) construc out.y = posy + lengthdir_y(scay * r, a); break; + case "Trapezoid" : + case "Parallelogram" : + case "Rectangle" : case "Polygon" : case "Star" : case "Line" : @@ -195,7 +188,7 @@ function Node_Path_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) construc pa2y = _aran[1]; pa3 = _pa3; - corners = _c; + corners = _c; var ox, oy, nx, ny, x0, y0; @@ -208,66 +201,131 @@ function Node_Path_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) construc switch(shapeScroll[shape].name) { case "Rectangle" : + loop = true; inputs[9].setVisible(true); - loop = true; var x0 = posx - scax; var y0 = posy - scay; var x1 = posx + scax; var y1 = posy + scay; - points = [ - [ x0 + _c[0], y0 ], - [ x1 - _c[1], y0 ], - - [ x1, y0 + _c[1] ], - [ x1, y1 - _c[2] ], - - [ x1 - _c[2], y1 ], - [ x0 + _c[3], y1 ], - - [ x0, y1 - _c[3] ], - [ x0, y0 + _c[0] ], - ]; + var p = [ + [ x0, y1 ], + [ x0, y0 ], + [ x1, y0 ], + + [ x0, y0 ], + [ x1, y0 ], + [ x1, y1 ], + + [ x1, y0 ], + [ x1, y1 ], + [ x0, y1 ], + + [ x1, y1 ], + [ x0, y1 ], + [ x0, y0 ], + ]; + + var ar = array_create(4); + for( var i = 0; i < 4; i++ ) { + ar[i] = _c[i]? get_corner_radius(p[i * 3 + 0][0], p[i * 3 + 0][1], + p[i * 3 + 1][0], p[i * 3 + 1][1], + p[i * 3 + 2][0], p[i * 3 + 2][1], _c[i], 64, 0) : [ p[i * 3 + 1] ]; + } + + points = array_merge( ar[0], ar[1], ar[2], ar[3] ); break; case "Trapezoid" : loop = true; inputs[4].setVisible(true); + inputs[9].setVisible(true); - points = [ - [ posx - scax * saturate(1 - _pa1), posy - scay ], - [ posx + scax * saturate(1 - _pa1), posy - scay ], - - [ posx + scax * saturate(1 - _pa1), posy - scay ], - [ posx + scax * saturate(1 + _pa1), posy + scay ], - - [ posx + scax * saturate(1 + _pa1), posy + scay ], - [ posx - scax * saturate(1 + _pa1), posy + scay ], - - [ posx - scax * saturate(1 + _pa1), posy + scay ], - [ posx - scax * saturate(1 - _pa1), posy - scay ], - ]; + var x0 = posx - scax * saturate(1 - _pa1); + var y0 = posy - scay; + + var x1 = posx + scax * saturate(1 - _pa1); + var y1 = posy - scay; + + var x2 = posx + scax * saturate(1 + _pa1); + var y2 = posy + scay; + + var x3 = posx - scax * saturate(1 + _pa1); + var y3 = posy + scay; + + var p = [ + [ x3, y3 ], + [ x0, y0 ], + [ x1, y1 ], + + [ x0, y0 ], + [ x1, y1 ], + [ x2, y2 ], + + [ x1, y1 ], + [ x2, y2 ], + [ x3, y3 ], + + [ x2, y3 ], + [ x3, y3 ], + [ x0, y0 ], + ]; + + var ar = array_create(4); + for( var i = 0; i < 4; i++ ) { + ar[i] = _c[i]? get_corner_radius(p[i * 3 + 0][0], p[i * 3 + 0][1], + p[i * 3 + 1][0], p[i * 3 + 1][1], + p[i * 3 + 2][0], p[i * 3 + 2][1], _c[i], 64, 0) : [ p[i * 3 + 1] ]; + } + + points = array_merge( ar[0], ar[1], ar[2], ar[3] ); break; case "Parallelogram" : loop = true; inputs[4].setVisible(true); + inputs[9].setVisible(true); - points = [ - [ posx - scax * saturate(1 - _pa1), posy - scay ], - [ posx + scax * saturate(1 + _pa1), posy - scay ], - - [ posx + scax * saturate(1 + _pa1), posy - scay ], - [ posx + scax * saturate(1 - _pa1), posy + scay ], - - [ posx + scax * saturate(1 - _pa1), posy + scay ], - [ posx - scax * saturate(1 + _pa1), posy + scay ], - - [ posx - scax * saturate(1 + _pa1), posy + scay ], - [ posx - scax * saturate(1 - _pa1), posy - scay ], - ]; + var x0 = posx - scax * saturate(1 - _pa1); + var y0 = posy - scay; + + var x1 = posx + scax * saturate(1 + _pa1); + var y1 = posy - scay; + + var x2 = posx + scax * saturate(1 - _pa1); + var y2 = posy + scay; + + var x3 = posx - scax * saturate(1 + _pa1); + var y3 = posy + scay; + + var p = [ + [ x3, y3 ], + [ x0, y0 ], + [ x1, y1 ], + + [ x0, y0 ], + [ x1, y1 ], + [ x2, y2 ], + + [ x1, y1 ], + [ x2, y2 ], + [ x3, y3 ], + + [ x2, y3 ], + [ x3, y3 ], + [ x0, y0 ], + ]; + + var ar = array_create(4); + for( var i = 0; i < 4; i++ ) { + ar[i] = _c[i]? get_corner_radius(p[i * 3 + 0][0], p[i * 3 + 0][1], + p[i * 3 + 1][0], p[i * 3 + 1][1], + p[i * 3 + 2][0], p[i * 3 + 2][1], _c[i], 64, 0) : [ p[i * 3 + 1] ]; + } + + points = array_merge( ar[0], ar[1], ar[2], ar[3] ); break; case "Ellipse" : @@ -381,6 +439,7 @@ function Node_Path_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) construc } array_map_ext(points, function(p) /*=>*/ {return point_rotate(p[0], p[1], posx, posy, rot, p)}); + var n = array_length(points); lengths = array_create(n + loop); diff --git a/shaders/sh_path_morph/sh_path_morph.fsh b/shaders/sh_path_morph/sh_path_morph.fsh index 0297cc016..8ceb79550 100644 --- a/shaders/sh_path_morph/sh_path_morph.fsh +++ b/shaders/sh_path_morph/sh_path_morph.fsh @@ -131,17 +131,12 @@ float pointOnLine(in vec2 p, in vec2 l0, in vec2 l1) { return t; } -float tsign (in vec2 p1, in vec2 p2, in vec2 p3) { return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y); } - bool pointInTriangle(in vec2 p, in vec2 t0, in vec2 t1, in vec2 t2) { - float d1 = tsign(p, t0, t1); - float d2 = tsign(p, t1, t2); - float d3 = tsign(p, t2, t0); + float d1 = (p.x - t1.x) * (t0.y - t1.y) - (t0.x - t1.x) * (p.y - t1.y); + float d2 = (p.x - t2.x) * (t1.y - t2.y) - (t1.x - t2.x) * (p.y - t2.y); + float d3 = (p.x - t0.x) * (t2.y - t0.y) - (t2.x - t0.x) * (p.y - t0.y); - bool has_neg = (d1 < 0.) || (d2 < 0.) || (d3 < 0.); - bool has_pos = (d1 > 0.) || (d2 > 0.) || (d3 > 0.); - - return !(has_neg && has_pos); + return (d1 >= 0. && d2 >= 0. && d3 >= 0.) || (d1 <= 0. && d2 <= 0. && d3 <= 0.); } bool intersect(in vec2 p, in vec2 l0, in vec2 l1) { @@ -197,37 +192,63 @@ void main() { a = dF / (dF + dT); } else { - float ma = 99999.; - float index = 0.; - bool infr = false; a = 0.; + float d1, d2, d3; + for(int i = 1; i < subdivision; i++) { pF1 = point1[i]; - pT1 = point2[i]; + pT0 = point2[0]; vec2 f = pointToLine(px, pF0, pF1); - vec2 t = pointToLine(px, pT0, pT1); - - if(intersect(px, pF0, pF1) && f.x >= px.x) inFrom = !inFrom; - if(intersect(px, pT0, pT1) && t.x >= px.x) inTo = !inTo; - - bool inRegion = pointInTriangle(px, pF0, pF1, pT0) || pointInTriangle(px, pF1, pT0, pT1); - - pF0 = pF1; - pT0 = pT1; - - if(!inRegion) continue; - float _f = distance(px, f); - float _t = distance(px, t); - a = max(a, _f / (_f + _t)); + float pxx_f1x = (px.x - pF1.x); + float pxy_f1y = (px.y - pF1.y); + float pxx_f0x = (px.x - pF0.x); + float pxy_f0y = (px.y - pF0.y); + float f0y_f1y = (pF0.y - pF1.y); + float f0x_f1x = (pF0.x - pF1.x); + float dd1 = pxx_f1x * f0y_f1y - f0x_f1x * pxy_f1y; - infr = true; + for(int j = 1; j < subdivision; j++) { + pT1 = point2[j]; + + d1 = dd1; + d2 = (px.x - pT0.x) * (pF1.y - pT0.y) - (pF1.x - pT0.x) * (px.y - pT0.y); + d3 = pxx_f0x * (pT0.y - pF0.y) - (pT0.x - pF0.x) * pxy_f0y; + bool i1 = (d1 >= 0. && d2 >= 0. && d3 >= 0.) || (d1 <= 0. && d2 <= 0. && d3 <= 0.); + + d1 = (px.x - pT0.x) * (pF1.y - pT0.y) - (pF1.x - pT0.x) * (px.y - pT0.y); + d2 = (px.x - pT1.x) * (pT0.y - pT1.y) - (pT0.x - pT1.x) * (px.y - pT1.y); + d3 = pxx_f1x * (pT1.y - pF1.y) - (pT1.x - pF1.x) * pxy_f1y; + bool i2 = (d1 >= 0. && d2 >= 0. && d3 >= 0.) || (d1 <= 0. && d2 <= 0. && d3 <= 0.); + + bool inRegion = i1 || i2; + + if(!inRegion) { + pT0 = pT1; + continue; + } + + vec2 t = pointToLine(px, pT0, pT1); + float _t = distance(px, t); + a = max(a, _f / (_f + _t)); + + pT0 = pT1; + inFrom = true; + } + + pF0 = pF1; + } + + pT0 = point2[0]; + for(int i = 1; i < subdivision; i++) { + pT1 = point2[i]; + vec2 t = pointToLine(px, pT0, pT1); + if(intersect(px, pT0, pT1) && t.x >= px.x) inTo = !inTo; + pT0 = pT1; } - - if(infr) inFrom = true; } if(clip == 1) {