mesh concave

This commit is contained in:
Tanasart 2024-12-12 16:48:18 +07:00
parent 09535bb03a
commit 47a3f5e90d
4 changed files with 83 additions and 35 deletions

View file

@ -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
}
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;
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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];