- [Path From Mask] Improve performace and add maximum surface attributes (larger surface will be downsampled)

This commit is contained in:
Tanasart 2024-05-10 10:14:55 +07:00
parent e85e502f01
commit 05efb4b74f
3 changed files with 71 additions and 50 deletions

View file

@ -55,10 +55,17 @@ function buffer_from_file(path) { #region
} #endregion } #endregion
function buffer_read_at(buffer, position, type) { #region function buffer_read_at(buffer, position, type) { #region
INLINE
buffer_seek(buffer, buffer_seek_start, position); buffer_seek(buffer, buffer_seek_start, position);
return buffer_read(buffer, type); return buffer_read(buffer, type);
} #endregion } #endregion
function buffer_write_at(buffer, position, type, data) { #region
INLINE
buffer_seek(buffer, buffer_seek_start, position);
return buffer_write(buffer, type, data);
} #endregion
function buffer_serialize(buffer, compress = true) { #region function buffer_serialize(buffer, compress = true) { #region
INLINE INLINE
if(!buffer_exists(buffer)) return ""; if(!buffer_exists(buffer)) return "";

View file

@ -17,6 +17,10 @@ function Node_Path_From_Mask(_x, _y, _group = noone) : Node(_x, _y, _group) cons
loop = true; loop = true;
cached_pos = ds_map_create(); cached_pos = ds_map_create();
attributes.maximum_dim = 64;
array_push(attributeEditors, ["Max Dimension", function() { return attributes.maximum_dim; },
new textBox(TEXTBOX_INPUT.number, function(val) { attributes.maximum_dim = clamp(val, 8, 8192); })]);
static getBoundary = function() { return boundary; } static getBoundary = function() { return boundary; }
static getAccuLength = function() { return lengthAccs; } static getAccuLength = function() { return lengthAccs; }
static getLength = function() { return lengthTotal; } static getLength = function() { return lengthTotal; }
@ -96,73 +100,78 @@ function Node_Path_From_Mask(_x, _y, _group = noone) : Node(_x, _y, _group) cons
if(!is_surface(_surf)) return; if(!is_surface(_surf)) return;
var _dim = surface_get_dimension(_surf); var _dim = surface_get_dimension(_surf);
var _sca = min(1, attributes.maximum_dim / _dim[0], attributes.maximum_dim / _dim[1]);
_dim[0] *= _sca;
_dim[1] *= _sca;
temp_surface[0] = surface_verify(temp_surface[0], _dim[0], _dim[1]); temp_surface[0] = surface_verify(temp_surface[0], _dim[0], _dim[1]);
surface_set_shader(temp_surface[0], sh_image_trace); surface_set_shader(temp_surface[0], sh_image_trace);
shader_set_f("dimension", _dim); shader_set_f("dimension", _dim);
draw_surface(_surf, 0, 0); draw_surface_stretched(_surf, 0, 0, _dim[0], _dim[1]);
surface_reset_shader(); surface_reset_shader();
var _w = _dim[0], _h = _dim[1]; var _w = _dim[0], _h = _dim[1];
var _x = 0, _y = 0; var _x = 0, _y = 0;
var _buff = buffer_from_surface(temp_surface[0], false); var _buff = buffer_from_surface(temp_surface[0], false);
var _emp = false; var _emp = true;
var _ind = 0;
while(buffer_getPixel(_buff, _w, _h, _x, _y) == 0) { buffer_seek(_buff, buffer_seek_start, 0);
_x++; repeat(_w * _h) {
if(_x == _w) { var _b = buffer_read(_buff, buffer_u32);
_x = 0; if(_b > 0) {
_y++; _emp = false;
if(_y == _h) { _x = _ind % _w;
_emp = true; _y = floor(_ind / _w);
break; break;
}
} }
_ind++;
} }
if(_emp) return; if(_emp) { print("Empty surface"); return; }
var _sx = _x; var _sx = _x;
var _sy = _y; var _sy = _y;
var _c = 0; var _px = _x;
var _px = _x; var _py = _y;
var _py = _y;
var _a = [];
var _amo = _w * _h; var _amo = _w * _h;
var _rep = 0; var _rep = 0;
var _a = array_create(_amo * 2);
var _ind = 0;
do { do {
buffer_setPixel(_buff, _w, _h, _x, _y, 0); buffer_write_at(_buff, (_y * _w + _x) * 4, buffer_u32, 0);
array_push(_a, [ _x + 0.5, _y + 0.5 ]); _a[_ind++] = _x / _sca + 0.5;
_a[_ind++] = _y / _sca + 0.5;
if(_x < _w - 1 && buffer_getPixel(_buff, _w, _h, _x + 1, _y)) { _x++; } if(_x < _w - 1 && buffer_read_at(_buff, ((_y ) * _w + _x + 1) * 4, buffer_u32)) { _x++; }
else if(_y < _h - 1 && buffer_getPixel(_buff, _w, _h, _x, _y + 1)) { _y++; } else if(_y < _h - 1 && buffer_read_at(_buff, ((_y + 1) * _w + _x ) * 4, buffer_u32)) { _y++; }
else if(_x > 0 && buffer_getPixel(_buff, _w, _h, _x - 1, _y)) { _x--; } else if(_x > 0 && buffer_read_at(_buff, ((_y ) * _w + _x - 1) * 4, buffer_u32)) { _x--; }
else if(_y > 0 && buffer_getPixel(_buff, _w, _h, _x, _y - 1)) { _y--; } else if(_y > 0 && buffer_read_at(_buff, ((_y - 1) * _w + _x ) * 4, buffer_u32)) { _y--; }
else if(_x < _w - 1 && _y < _h - 1 && buffer_getPixel(_buff, _w, _h, _x + 1, _y + 1)) { _x++; _y++; } else if(_x < _w - 1 && _y < _h - 1 && buffer_read_at(_buff, ((_y + 1) * _w + _x + 1) * 4, buffer_u32)) { _x++; _y++; }
else if(_x < _w - 1 && _y > 0 && buffer_getPixel(_buff, _w, _h, _x + 1, _y - 1)) { _x++; _y--; } else if(_x < _w - 1 && _y > 0 && buffer_read_at(_buff, ((_y - 1) * _w + _x + 1) * 4, buffer_u32)) { _x++; _y--; }
else if(_x > 0 && _y < _h - 1 && buffer_getPixel(_buff, _w, _h, _x - 1, _y + 1)) { _x--; _y++; } else if(_x > 0 && _y < _h - 1 && buffer_read_at(_buff, ((_y + 1) * _w + _x - 1) * 4, buffer_u32)) { _x--; _y++; }
else if(_x > 0 && _y > 0 && buffer_getPixel(_buff, _w, _h, _x - 1, _y - 1)) { _x--; _y--; } else if(_x > 0 && _y > 0 && buffer_read_at(_buff, ((_y - 1) * _w + _x - 1) * 4, buffer_u32)) { _x--; _y--; }
if(++_rep >= _amo) break; if(++_rep >= _amo) break;
} until(_x == _sx && _y == _sy); } until(_x == _sx && _y == _sy);
buffer_delete(_buff); buffer_delete(_buff);
anchors = []; anchors = array_verify(anchors, _ind / 2);
var _aind = 0;
var lx = _a[0][0]; var lx = _a[0];
var ly = _a[0][1]; var ly = _a[1];
var ox, oy, nx, ny; var ox, oy, nx, ny;
array_push(_a, _a[0]); for( var i = 0; i < _ind; i += 2 ) {
array_push(anchors, _a[0]); nx = _a[i + 0];
ny = _a[i + 1];
for( var i = 0, n = array_length(_a); i < n; i++ ) {
nx = _a[i][0];
ny = _a[i][1];
if(i) { if(i) {
var na = point_direction(ox, oy, nx, ny); var na = point_direction(ox, oy, nx, ny);
@ -172,7 +181,7 @@ function Node_Path_From_Mask(_x, _y, _group = noone) : Node(_x, _y, _group) cons
lx = ox; lx = ox;
ly = oy; ly = oy;
array_push(anchors, [ ox, oy ]); anchors[_aind++] = [ ox, oy ];
} }
} }
@ -180,25 +189,30 @@ function Node_Path_From_Mask(_x, _y, _group = noone) : Node(_x, _y, _group) cons
oy = ny; oy = ny;
} }
array_push(anchors, _a[0]); anchors[_aind++] = [ _a[0], _a[1] ];
array_resize(anchors, _aind);
var ox, oy, nx, ny; var ox, oy, nx, ny;
lengthTotal = 0; lengthTotal = 0;
lengths = []; lengths = array_verify(lengths, (_ind / 2) - 1);
lengthAccs = []; lengthAccs = array_verify(lengthAccs, (_ind / 2) - 1);
boundary = new BoundingBox(); boundary = new BoundingBox();
for( var i = 0, n = array_length(anchors); i < n; i++ ) { var _lind = 0;
nx = _a[i][0];
ny = _a[i][1]; for( var i = 0; i < _ind; i += 2 ) {
nx = _a[i + 0];
ny = _a[i + 1];
boundary.addPoint(nx, ny); boundary.addPoint(nx, ny);
if(i) { if(i) {
var ds = point_distance(ox, oy, nx, ny); var ds = point_distance(ox, oy, nx, ny);
lengthTotal += ds;
array_push(lengths, ds); lengthTotal += ds;
array_push(lengthAccs, lengthTotal); lengths[_lind] = ds;
lengthAccs[_lind] = lengthTotal;
_lind++;
} }
ox = nx; ox = nx;

View file

@ -2108,12 +2108,12 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
} }
if(!typeCompatible(_valueFrom.type, type)) { if(!typeCompatible(_valueFrom.type, type)) {
if(log) noti_warning($"setFrom: Type mismatch {_valueFrom.type} to {type}",, node); noti_warning($"Connection error: Incompatible type {_valueFrom.type} to {type}",, node);
return -1; return -1;
} }
if(typeIncompatible(_valueFrom, self)) { if(typeIncompatible(_valueFrom, self)) {
if(log) noti_warning("setFrom: Type mismatch",, node); noti_warning("Connection error: Incompatible type",, node);
return -1; return -1;
} }
@ -2128,7 +2128,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
} }
if(!accept_array && isArray(_valueFrom.getValue())) { if(!accept_array && isArray(_valueFrom.getValue())) {
if(log) noti_warning("setFrom: Array mismatch",, node); noti_warning($"Connection error: {name} does not support array input.",, node);
return -1; return -1;
} }