From 47a3f5e90d4b03859728aef78ff1716cd44654eb Mon Sep 17 00:00:00 2001 From: Tanasart Date: Thu, 12 Dec 2024 16:48:18 +0700 Subject: [PATCH] mesh concave --- scripts/delau_helper/delau_helper.gml | 47 ++++++++++++------- scripts/delaunay/delaunay.gml | 7 +-- scripts/line_intersect/line_intersect.gml | 7 +++ scripts/node_mesh_warp/node_mesh_warp.gml | 57 ++++++++++++++++------- 4 files changed, 83 insertions(+), 35 deletions(-) diff --git a/scripts/delau_helper/delau_helper.gml b/scripts/delau_helper/delau_helper.gml index 79934ecf1..a767cf37f 100644 --- a/scripts/delau_helper/delau_helper.gml +++ b/scripts/delau_helper/delau_helper.gml @@ -1,4 +1,4 @@ -function _find_polygon_edges(triangles) { #region +function _find_polygon_edges(triangles) { var polygon = []; for (var i = 0; i < array_length(triangles); i++) { @@ -24,9 +24,9 @@ function _find_polygon_edges(triangles) { #region } return polygon; -} #endregion +} -function _shares_vertex(triangle1, triangle2) { #region +function _shares_vertex(triangle1, triangle2) { for (var i = 0; i < 3; i++) for (var j = 0; j < 3; j++) { if (triangle1[i].equal(triangle2[j])) @@ -34,9 +34,9 @@ function _shares_vertex(triangle1, triangle2) { #region } return false; -} #endregion +} -function _shares_edge(triangle, edge_start, edge_end) { #region +function _shares_edge(triangle, edge_start, edge_end) { var count = 0; for (var i = 0; i < 3; i++) { @@ -45,9 +45,9 @@ function _shares_edge(triangle, edge_start, edge_end) { #region } return count == 2; -} #endregion +} -function _create_super_triangle(points) { #region +function _create_super_triangle(points) { var min_x = points[0].x, max_x = min_x, min_y = points[0].y, max_y = min_y; for (var i = 1; i < array_length(points); i++) { @@ -67,20 +67,20 @@ function _create_super_triangle(points) { #region new __vec2(center_x, center_y + 2 * d_max), new __vec2(center_x + 2 * d_max, center_y - d_max) ]; -} #endregion +} -function _triangle_is_ccw(triangle) { #region +function _triangle_is_ccw(triangle) { var a = triangle[0], b = triangle[1], c = triangle[2]; return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y)) > 0; -} #endregion +} -function _triangle_is_equal(tri0, tri1) { #region +function _triangle_is_equal(tri0, tri1) { return (tri0[0] == tri1[0] || tri0[0] == tri1[1] || tri0[0] == tri1[2]) && (tri0[1] == tri1[0] || tri0[1] == tri1[1] || tri0[1] == tri1[2]) && (tri0[2] == tri1[0] || tri0[2] == tri1[1] || tri0[2] == tri1[2]); -} #endregion +} -function _point_in_circumcircle(point, triangle) { #region +function _point_in_circumcircle(point, triangle) { var a = triangle[0], b = triangle[1], c = triangle[2]; if(!_triangle_is_ccw(triangle)) { b = triangle[2]; @@ -97,11 +97,26 @@ function _point_in_circumcircle(point, triangle) { #region + (cx * cx + cy * cy) * (ax * by - bx * ay); return det > 0; -} #endregion +} -function array_remove_triangles(arr, target) { #region +function array_remove_triangles(arr, target) { for (var i = array_length(arr) - 1; i >= 0; i--) { if (_triangle_is_equal(arr[i], target)) array_delete(arr, i, 1); } -} #endregion \ No newline at end of file +} + +function delaunay_triangle_in_polygon(points, triangle) { + var xc = (triangle[0].x + triangle[1].x + triangle[2].x) / 3; + var yc = (triangle[0].y + triangle[1].y + triangle[2].y) / 3; + var ins = 0; + + for( var i = 0, n = array_length(points); i < n; i++ ) { + var p0 = points[i]; + var p1 = points[(i + 1) % n]; + + ins += line_is_intersect(xc, yc, xc + 10000, yc, p0[0], p0[1], p1[0], p1[1]); + } + + return ins % 2; +} \ No newline at end of file diff --git a/scripts/delaunay/delaunay.gml b/scripts/delaunay/delaunay.gml index 5044ba2ef..5f5145b0e 100644 --- a/scripts/delaunay/delaunay.gml +++ b/scripts/delaunay/delaunay.gml @@ -1,4 +1,4 @@ -function delaunay_triangulation(points) { #region +function delaunay_triangulation(points, polygons = noone) { if(array_length(points) < 3) return []; var super_triangle = _create_super_triangle(points); @@ -11,6 +11,7 @@ function delaunay_triangulation(points) { #region for (var j = 0; j < array_length(triangles); j++) { var _triangle = triangles[j]; + if (_point_in_circumcircle(_point, _triangle)) array_push(bad_triangles, _triangle); } @@ -28,9 +29,9 @@ function delaunay_triangulation(points) { #region for (var i = array_length(triangles) - 1; i >= 0; i--) { var _triangle = triangles[i]; - if (_shares_vertex(super_triangle, _triangle)) + if (_shares_vertex(super_triangle, _triangle) || (polygons != noone && !delaunay_triangle_in_polygon(polygons, _triangle))) array_delete(triangles, i, 1); } return triangles; -} #endregion \ No newline at end of file +} \ No newline at end of file diff --git a/scripts/line_intersect/line_intersect.gml b/scripts/line_intersect/line_intersect.gml index 01d03e142..8ef0c949c 100644 --- a/scripts/line_intersect/line_intersect.gml +++ b/scripts/line_intersect/line_intersect.gml @@ -6,4 +6,11 @@ function line_intersect(x1, y1, x2, y2, x3, y3, x4, y4) { var py = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4); return [ px / d, py / d, d ]; +} + +function line_is_intersect_ccw(x0, y0, x1, y1, x2, y2) { return (y2 - y0) * (x1 - x0) > (y1 - y0) * (x2 - x0) } + +function line_is_intersect(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1) { + return line_is_intersect_ccw(ax0, ay0, bx0, by0, bx1, by1) != line_is_intersect_ccw(ax1, ay1, bx0, by0, bx1, by1) && + line_is_intersect_ccw(ax0, ay0, ax1, ay1, bx0, by0) != line_is_intersect_ccw(ax0, ay0, ax1, ay1, bx1, by1) } \ No newline at end of file diff --git a/scripts/node_mesh_warp/node_mesh_warp.gml b/scripts/node_mesh_warp/node_mesh_warp.gml index e76fd32dc..ca0c054c8 100644 --- a/scripts/node_mesh_warp/node_mesh_warp.gml +++ b/scripts/node_mesh_warp/node_mesh_warp.gml @@ -234,6 +234,9 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) newInput(9, nodeValueSeed(self)); + newInput(10, nodeValue_Float("Randomness", self, 0.5)) + .setDisplay(VALUE_DISPLAY.slider); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone)); @@ -241,7 +244,7 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) newOutput(1, nodeValue_Output("Mesh data", self, VALUE_TYPE.mesh, mesh_data)); input_display_list = [ 5, - ["Mesh", false], 0, 8, 9, 1, 7, 3, + ["Mesh", false], 0, 8, 9, 1, 7, 10, 3, ["Link", false], 4, 6, ["Control points", false], ]; @@ -396,8 +399,16 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) for(var i = 0; i < array_length(mesh_data.links); i++) mesh_data.links[i].draw(_x, _y, _s); - for(var i = 0; i < array_length(mesh_data.tris); i++) + for(var i = 0; i < array_length(mesh_data.tris); i++) { mesh_data.tris[i].drawPoints(_x, _y, _s); + + // var _t = mesh_data.tris[i]; + // var _in = delaunay_triangle_in_polygon(attributes.mesh_bound, _t); + // draw_set_color(_in? c_lime : c_red); + // draw_circle(_x + (_t.p0.x + _t.p1.x + _t.p2.x) / 3 * _s, + // _y + (_t.p0.y + _t.p1.y + _t.p2.y) / 3 * _s, + // 4, false); + } var _hover = -1; for(var i = control_index; i < array_length(inputs); i++) { @@ -455,9 +466,10 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) static step = function() { var _type = getInputData(8); - inputs[2].setVisible(_type == 0); - inputs[4].setVisible(_type == 0); - inputs[7].setVisible(_type == 0); + inputs[ 2].setVisible(_type == 0); + inputs[ 4].setVisible(_type == 0); + inputs[ 7].setVisible(_type == 0); + inputs[10].setVisible(_type == 1); if(_type == 0) tools = tools_edit; else if(_type == 1) tools = tools_mesh; @@ -569,8 +581,9 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) } static Mesh_build_Triangulate = function(surf) { - var sample = getInputData(1); - var seed = getInputData(9); + var sample = getInputData( 1); + var seed = getInputData( 9); + var _rand = getInputData(10); if(!inputs[0].value_from) return; if(is_array(surf)) surf = surf[0]; @@ -581,8 +594,8 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) var _m = attributes.mesh_bound; if(array_length(_m) < 3) return; - var _mb = array_length(_m); - var ind = 0; + var _mb = array_length(_m); + var ind = 0; var minX, maxX, minY, maxY; @@ -602,8 +615,8 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) } } - var gw = ww / sample / 3; - var gh = hh / sample / 3; + var gw = ww / sample / 3 * _rand; + var gh = hh / sample / 3 * _rand; random_set_seed(seed); var _p = []; @@ -620,14 +633,26 @@ function Node_Mesh_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) } mesh_data.points = array_create(_mb + array_length(_p)); + var _i = 0; + var _sp = min(ww, hh) / sample; - for( var i = 0, n = _mb; i < n; i++ ) - mesh_data.points[i] = new MeshedPoint(i, _m[i][0], _m[i][1]); + for( var i = 0, n = _mb; i < n; i++ ) { + mesh_data.points[_i] = new MeshedPoint(_i, _m[i][0], _m[i][1]); _i++; - for( var i = 0, n = array_length(_p); i < n; i++ ) - mesh_data.points[_mb + i] = new MeshedPoint(_mb + i, _p[i][0], _p[i][1]); + var _p0 = _m[i]; + var _p1 = _m[(i + 1) % n]; + var _ds = point_distance(_p0[0], _p0[1], _p1[0], _p1[1]); + var _sm = round(_ds / _sp); + for( var j = 0; j < _sm; j++ ) { + mesh_data.points[_i] = new MeshedPoint(_i, lerp(_p0[0], _p1[0], j / _sm), lerp(_p0[1], _p1[1], j / _sm)); _i++; + } + } + + for( var i = 0, n = array_length(_p); i < n; i++ ) { + mesh_data.points[_i] = new MeshedPoint(_i, _p[i][0], _p[i][1]); _i++; + } - var _t = delaunay_triangulation(mesh_data.points); + var _t = delaunay_triangulation(mesh_data.points, _m); for( var i = 0, n = array_length(_t); i < n; i++ ) { var t = _t[i];