mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-01-12 23:37:10 +01:00
[Path Shape] Add corner radius for quadrilateral shapes.
This commit is contained in:
parent
df4d289333
commit
f1e60b9213
4 changed files with 231 additions and 95 deletions
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue