This commit is contained in:
Tanasart 2023-12-30 20:21:56 +07:00
parent 065b2cb4ad
commit f582db702c
15 changed files with 207 additions and 50 deletions

View file

@ -712,6 +712,7 @@
{"name":"s_node_note","order":35,"path":"sprites/s_node_note/s_node_note.yy",},
{"name":"node_strand_gravity","order":4,"path":"scripts/node_strand_gravity/node_strand_gravity.yy",},
{"name":"palette_functions","order":3,"path":"scripts/palette_functions/palette_functions.yy",},
{"name":"node_FLIP_apply_velocity","order":7,"path":"scripts/node_FLIP_apply_velocity/node_FLIP_apply_velocity.yy",},
{"name":"luaHighlight","order":1,"path":"scripts/luaHighlight/luaHighlight.yy",},
{"name":"d3d_rot3","order":3,"path":"scripts/d3d_rot3/d3d_rot3.yy",},
{"name":"sh_sample_points","order":26,"path":"shaders/sh_sample_points/sh_sample_points.yy",},

View file

@ -966,6 +966,7 @@
{"id":{"name":"node_strand_gravity","path":"scripts/node_strand_gravity/node_strand_gravity.yy",},},
{"id":{"name":"palette_functions","path":"scripts/palette_functions/palette_functions.yy",},},
{"id":{"name":"sh_alpha_cutoff","path":"shaders/sh_alpha_cutoff/sh_alpha_cutoff.yy",},},
{"id":{"name":"node_FLIP_apply_velocity","path":"scripts/node_FLIP_apply_velocity/node_FLIP_apply_velocity.yy",},},
{"id":{"name":"luaHighlight","path":"scripts/luaHighlight/luaHighlight.yy",},},
{"id":{"name":"d3d_rot3","path":"scripts/d3d_rot3/d3d_rot3.yy",},},
{"id":{"name":"sh_sample_points","path":"shaders/sh_sample_points/sh_sample_points.yy",},},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -7,6 +7,8 @@
height = 0;
particleSize = 0;
density = 0;
viscosity = 0;
friction = 0;
maxParticles = 0;
numParticles = 0;
@ -20,10 +22,13 @@
numPressureIters = 3;
numParticleIters = 3;
overRelaxation = 1.5;
wallCollide = true;
#endregion
function init(width, height, particleSize, density, maxParticles) { #region domain init
particlePos = array_create(2 * maxParticles);
particlePos = array_create(maxParticles * 2);
particleLife = array_create(maxParticles);
obstracles = [];
numParticles = 0;
@ -45,6 +50,11 @@ function init(width, height, particleSize, density, maxParticles) { #region doma
self.maxParticles = maxParticles;
particlePosBuff = buffer_create(maxParticles * 2 * 8, buffer_grow, 8);
particleLifeBuff = buffer_create(maxParticles * 8, buffer_grow, 8);
aPosBuff = buffer_get_address(particlePosBuff);
aLifeBuff = buffer_get_address(particleLifeBuff);
domain = FLIP_initDomain(width, height, particleSize, density, maxParticles);
particleRadius = FLIP_getParticleRadius(domain);
} #endregion
@ -52,9 +62,12 @@ function init(width, height, particleSize, density, maxParticles) { #region doma
function update() { #region
FLIP_setQuality( domain, iteration, numPressureIters, numParticleIters);
FLIP_setGravity( domain, g);
FLIP_setViscosity( domain, viscosity);
FLIP_setFriction( domain, power(1 - friction, 0.025));
FLIP_setFlipRatio( domain, flipRatio);
FLIP_setVelocityDamping( domain, velocityDamping);
FLIP_setOverRelaxation( domain, overRelaxation);
FLIP_setWallCollisions( domain, wallCollide);
} #endregion
function step() { #region
@ -65,8 +78,25 @@ function step() { #region
FLIP_simulate(domain, dt);
FLIP_setParticleBuffer(domain, buffer_get_address(particlePosBuff));
//FLIP_setTimeStep(domain, dt);
//repeat(iteration) {
// FLIP_simulate_integrateParticles(domain);
// FLIP_simulate_pushParticlesApart(domain);
// FLIP_simulate_handleParticleCollisions(domain);
// FLIP_simulate_transferVelocities(domain, 1);
// FLIP_simulate_updateParticleDensity(domain);
// FLIP_simulate_solveIncompressibility(domain);
// FLIP_simulate_transferVelocities(domain, 0);
//}
FLIP_setParticleBuffer(domain, aPosBuff, aLifeBuff);
buffer_seek(particlePosBuff, buffer_seek_start, 0);
for(var i = 0; i < 2 * maxParticles; i++)
buffer_seek(particleLifeBuff, buffer_seek_start, 0);
for(var i = 0; i < maxParticles * 2; i++)
particlePos[i] = buffer_read(particlePosBuff, buffer_f64);
for(var i = 0; i < maxParticles; i++)
particleLife[i] = buffer_read(particleLifeBuff, buffer_f64);
} #endregion

View file

@ -191,7 +191,7 @@ event_inherited();
tx = min(tx, _new_list[| i].x);
ty = min(tx, _new_list[| i].y);
if(is_instanceof(context, Node_Collection_Inline))
if(is_instanceof(context, Node_Collection_Inline) && !is_instanceof(_new_list[| i], Node_Collection_Inline))
context.addNode(_new_list[| i]);
}

View file

@ -0,0 +1,66 @@
function Node_FLIP_Apply_Velocity(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Apply Velocity";
color = COLORS.node_blend_fluid;
icon = THEME.fluid_sim;
w = 96;
min_h = 96;
manual_ungroupable = false;
inputs[| 0] = nodeValue("Domain", self, JUNCTION_CONNECT.input, VALUE_TYPE.fdomain, noone )
.setVisible(true, true);
inputs[| 1] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] )
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 2] = nodeValue("Radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4 )
.setDisplay(VALUE_DISPLAY.slider, { range: [1, 16, 0.1] });
inputs[| 3] = nodeValue("Velocity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] )
.setDisplay(VALUE_DISPLAY.vector);
input_display_list = [ 0,
["Velocity", false], 1, 2, 3,
]
outputs[| 0] = nodeValue("Domain", self, JUNCTION_CONNECT.output, VALUE_TYPE.fdomain, noone );
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var _posit = getInputData(1);
var _rad = getInputData(2);
var _velo = getInputData(3);
var _px = _x + _posit[0] * _s;
var _py = _y + _posit[1] * _s;
var _vx = _px + _velo[0] * _s;
var _vy = _py + _velo[1] * _s;
if(inputs[| 2].drawOverlay(active, _px, _py, _s, _mx, _my, _snx, _sny, 0, 1, THEME.anchor_scale_hori)) active = false;
draw_set_color(COLORS._main_accent);
draw_circle(_px, _py, _rad * _s, true);
draw_set_color(COLORS._main_accent);
draw_set_alpha(0.5);
draw_line_width2(_px, _py, _vx, _vy, 6, 2);
draw_set_alpha(1);
if(inputs[| 1].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny)) active = false;
if(inputs[| 3].drawOverlay(active, _px, _py, _s, _mx, _my, _snx, _sny)) active = false;
} #endregion
static update = function(frame = CURRENT_FRAME) {
var domain = getInputData(0);
if(!instance_exists(domain)) return;
outputs[| 0].setValue(domain);
var _posit = getInputData(1);
var _rad = getInputData(2);
var _velo = getInputData(3);
FLIP_applyVelocity_circle(domain.domain, _posit[0], _posit[1], _rad, _velo[0], _velo[1]);
}
}

View file

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "node_FLIP_apply_velocity",
"isCompatibility": false,
"isDnD": false,
"parent": {
"name": "FLIP",
"path": "folders/nodes/data/simulation/FLIP.yy",
},
}

View file

@ -29,10 +29,18 @@ function Node_FLIP_Domain(_x, _y, _group = noone) : Node(_x, _y, _group) constru
inputs[| 8] = nodeValue("Time Step", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.05);
inputs[| 9] = nodeValue("Collide wall", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
inputs[| 10] = nodeValue("Viscosity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.)
.setDisplay(VALUE_DISPLAY.slider);
inputs[| 11] = nodeValue("Friction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.)
.setDisplay(VALUE_DISPLAY.slider);
input_display_list = [
["Domain", false], 0, 1, 2,
["Solver", false], 3, 4, 5,
["Physics", false], 8, 6, 7,
["Domain", false], 0, 1, 2, 9,
["Solver", false], 3, 4, 5, 8,
["Physics", false], 6, 7, 10, 11,
]
outputs[| 0] = nodeValue("Domain", self, JUNCTION_CONNECT.output, VALUE_TYPE.fdomain, noone);
@ -53,6 +61,10 @@ function Node_FLIP_Domain(_x, _y, _group = noone) : Node(_x, _y, _group) constru
var _dmp = getInputData(6);
var _grv = getInputData(7);
var _dt = getInputData(8);
var _col = getInputData(9);
var _vis = getInputData(10);
var _fric = getInputData(11);
if(frame == 0 || domain == noone) {
var width = _dim[0] + _siz * 2;
@ -73,9 +85,19 @@ function Node_FLIP_Domain(_x, _y, _group = noone) : Node(_x, _y, _group) constru
domain.numPressureIters = 3;
domain.numParticleIters = 3;
domain.overRelaxation = _ovr;
domain.viscosity = _vis;
domain.friction = _fric;
domain.wallCollide = _col;
domain.update();
outputs[| 0].setValue(domain);
}
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
var bbox = drawGetBbox(xx, yy, _s);
draw_sprite_fit(s_node_fluidSim_domain, 0, bbox.xc, bbox.yc, bbox.w, bbox.h);
}
}

View file

@ -8,7 +8,14 @@ function Node_FLIP_Render(_x, _y, _group = noone) : Node(_x, _y, _group) constru
inputs[| 0] = nodeValue("Domain", self, JUNCTION_CONNECT.input, VALUE_TYPE.fdomain, noone)
.setVisible(true, true);
input_display_list = [ 0 ];
inputs[| 1] = nodeValue("Blending", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
.setDisplay(VALUE_DISPLAY.slider);
inputs[| 2] = nodeValue("Vaporize", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0);
input_display_list = [ 0,
["Rendering", false], 1, 2,
];
outputs[| 0] = nodeValue("Rendered", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
@ -18,7 +25,10 @@ function Node_FLIP_Render(_x, _y, _group = noone) : Node(_x, _y, _group) constru
var domain = getInputData(0);
if(!instance_exists(domain)) return;
domain.step();
if(IS_PLAYING) domain.step();
var _bln = getInputData(1);
var _vap = getInputData(2);
var _outSurf = outputs[| 0].getValue();
var _padd = domain.particleSize;
@ -30,29 +40,41 @@ function Node_FLIP_Render(_x, _y, _group = noone) : Node(_x, _y, _group) constru
outputs[| 0].setValue(_outSurf);
var _x, _y, _r, _l;
var _rad = domain.particleRadius;
var _mx = min(array_length(domain.particlePos) / 2 - 1, domain.numParticles);
surface_set_target(temp_surface[0]);
DRAW_CLEAR
BLEND_ADD
for( var i = 0; i < domain.numParticles; i++ ) {
var _x = domain.particlePos[i * 2 + 0];
var _y = domain.particlePos[i * 2 + 1];
for( var i = 0; i < _mx; i++ ) {
_x = domain.particlePos[i * 2 + 0];
_y = domain.particlePos[i * 2 + 1];
_l = domain.particleLife[i];
if(_x == 0 && _y == 0) continue;
_x -= _padd
_y -= _padd
_x -= _padd;
_y -= _padd;
_r = _rad * 4;
draw_circle_color(_x, _y, _rad * 4, c_white, c_black, false);
if(_vap) {
var _r = (_vap - _l) / _vap * _rad * 4;
if(_r < 0) continue;
}
draw_circle_color(_x, _y, _r, c_white, c_black, false);
}
BLEND_NORMAL
surface_reset_target();
surface_set_shader(_outSurf, sh_FLIP_render_threshold);
shader_set_f("threshold", 1 - _bln);
draw_surface(temp_surface[0], 0, 0);
surface_reset_shader();
}
}

View file

@ -17,14 +17,14 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 3] = nodeValue("Spawn type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0 )
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Stream", "Splash" ]);
.setDisplay(VALUE_DISPLAY.enum_button, [ "Stream", "Splash" ]);
inputs[| 4] = nodeValue("Spawn frame", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0 );
inputs[| 5] = nodeValue("Spawn amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4 );
inputs[| 6] = nodeValue("Spawn velocity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] )
.setDisplay(VALUE_DISPLAY.vector);
.setDisplay(VALUE_DISPLAY.range);
inputs[| 7] = nodeValue("Spawn surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone );
@ -33,9 +33,12 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
inputs[| 9] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, irandom_range(100000, 999999) );
inputs[| 10] = nodeValue("Spawn direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 45, 135, 0, 0 ] )
.setDisplay(VALUE_DISPLAY.rotation_random);
input_display_list = [ 0, 9,
["Spawner", false], 1, 7, 8, 2, 3, 4, 5,
["Physics", false], 6,
["Physics", false], 10, 6,
]
outputs[| 0] = nodeValue("Domain", self, JUNCTION_CONNECT.output, VALUE_TYPE.fdomain, noone );
@ -45,19 +48,13 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var _shp = getInputData(1);
var _posit = getInputData(2);
var _velo = getInputData(6);
var _px = _x + _posit[0] * _s;
var _py = _y + _posit[1] * _s;
var _vx = _px + _velo[0] * _s;
var _vy = _py + _velo[1] * _s;
if(_shp == 0) {
var _rad = getInputData(8);
if(inputs[| 8].drawOverlay(active, _px, _py, _s, _mx, _my, _snx, _sny, 0, 1, THEME.anchor_scale_hori)) active = false;
draw_set_color(COLORS._main_accent);
draw_circle(_px, _py, _rad * _s, true);
} else if(_shp == 1) {
@ -70,13 +67,7 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
draw_surface_ext(_surf, _px - _sw * _s / 2, _py - _sh * _s / 2, _s, _s, 0, c_white, 0.5);
}
draw_set_color(COLORS._main_accent);
draw_set_alpha(0.5);
draw_line_width2(_px, _py, _vx, _vy, 6, 2);
draw_set_alpha(1);
if(inputs[| 2].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny)) active = false;
if(inputs[| 6].drawOverlay(active, _px, _py, _s, _mx, _my, _snx, _sny)) active = false;
} #endregion
@ -100,11 +91,15 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
var _type = getInputData(3);
var _fra = getInputData(4);
var _amo = getInputData(5);
var _vel = getInputData(6);
var _surf = getInputData(7);
var _rad = getInputData(8);
var _seed = getInputData(9);
var _vel = getInputData( 6);
var _dirr = getInputData(10);
if(frame == 0) spawn_amo = 0;
_amo = min(_amo, domain.maxParticles - domain.numParticles);
spawn_amo += _amo;
@ -133,7 +128,7 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
buffer_seek(_buffP, buffer_seek_start, 0);
buffer_seek(_buffV, buffer_seek_start, 0);
random_set_seed(_seed + ceil(_amo) * frame);
random_set_seed(_seed + (ceil(_amo) + 10) * frame);
var ind = 0;
repeat(_samo) {
@ -146,26 +141,32 @@ function Node_FLIP_Spawner(_x, _y, _group = noone) : Node(_x, _y, _group) constr
_x = _posit[0] + lengthdir_x(_dis, _dir);
_y = _posit[1] + lengthdir_y(_dis, _dir);
buffer_write(_buffP, buffer_f64, _x);
buffer_write(_buffP, buffer_f64, _y);
} else if(_shape == 1) {
_x = _posit[0] - _sw / 2 + _points[ind][0] * _sw;
_y = _posit[1] - _sh / 2 + _points[ind][1] * _sh;
buffer_write(_buffP, buffer_f64, _x);
buffer_write(_buffP, buffer_f64, _y);
}
buffer_write(_buffV, buffer_f64, _vel[0]);
buffer_write(_buffV, buffer_f64, _vel[1]);
buffer_write(_buffP, buffer_f64, clamp(_x, 0, domain.width));
buffer_write(_buffP, buffer_f64, clamp(_y, 0, domain.height));
var _vdis = random_range(_vel[0], _vel[1]);
var _vdir = angle_random_eval(_dirr);
buffer_write(_buffV, buffer_f64, lengthdir_x(_vdis, _vdir));
buffer_write(_buffV, buffer_f64, lengthdir_y(_vdis, _vdir));
ind++;
}
FLIP_spawnParticles(domain.domain, buffer_get_address(_buffP), buffer_get_address(_buffV), _amo);
FLIP_spawnParticles(domain.domain, buffer_get_address(_buffP), buffer_get_address(_buffV), _samo);
buffer_delete(_buffP);
buffer_delete(_buffV);
}
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
var bbox = drawGetBbox(xx, yy, _s);
draw_sprite_fit(s_node_fluidSim_add_fluid, 0, bbox.xc, bbox.yc, bbox.w, bbox.h);
}
}

View file

@ -394,13 +394,14 @@ function __initNodes() {
#endregion
var flipSim = ds_list_create(); #region
addNodeCatagory("FLIP Fluid", smokeSim, ["Node_FLIP_Group_Inline"]);
addNodeCatagory("FLIP Fluid", flipSim, ["Node_FLIP_Group_Inline"]);
ds_list_add(flipSim, "Domain");
addNodeObject(flipSim, "Domain", s_node_smokeSim_domain, "Node_FLIP_Domain", [1, Node_FLIP_Domain]).hideRecent().setVersion(11620);
addNodeObject(flipSim, "Render", s_node_smokeSim_domain, "Node_FLIP_Render", [1, Node_FLIP_Render]).hideRecent().setVersion(11620);
addNodeObject(flipSim, "Domain", s_node_fluidSim_domain, "Node_FLIP_Domain", [1, Node_FLIP_Domain]).hideRecent().setVersion(11620);
addNodeObject(flipSim, "Render", s_node_fluidSim_render, "Node_FLIP_Render", [1, Node_FLIP_Render]).hideRecent().setVersion(11620);
ds_list_add(flipSim, "Fluid");
addNodeObject(flipSim, "Spawner", s_node_smokeSim_domain, "Node_FLIP_Spawner", [1, Node_FLIP_Spawner]).hideRecent().setVersion(11620);
addNodeObject(flipSim, "Spawner", s_node_fluidSim_add_fluid, "Node_FLIP_Spawner", [1, Node_FLIP_Spawner]).hideRecent().setVersion(11620);
addNodeObject(flipSim, "Apply Velocity", s_node_fluidSim_apply_velocity, "Node_FLIP_Apply_Velocity", [1, Node_FLIP_Apply_Velocity]).hideRecent().setVersion(11620);
#endregion
var strandSim = ds_list_create(); #region
@ -646,7 +647,7 @@ function __initNodes() {
addNodeObject(generator, "Particle", s_node_particle, "Node_Particle", [1, Node_Particle],, "Generate particle effect.");
addNodeObject(generator, "VFX", s_node_vfx, "Node_VFX_Group_Inline", [1, Node_VFX_Group_Inline],, "Create VFX group, which generate particles that can be manipulated using different force nodes.");
addNodeObject(generator, "RigidSim", s_node_rigidSim, "Node_Rigid_Group_Inline", [1, Node_Rigid_Group_Inline],, "Create group for rigidbody simulation.").setVersion(1110);
/**/ addNodeObject(generator, "FLIP Fluid", s_node_rigidSim, "Node_FLIP_Group_Inline", [1, Node_FLIP_Group_Inline],, "Create group for fluid simulation.").setVersion(11620);
addNodeObject(generator, "FLIP Fluid", s_node_fluidSim_group, "Node_FLIP_Group_Inline", [1, Node_FLIP_Group_Inline],, "Create group for fluid simulation.").setVersion(11620);
addNodeObject(generator, "SmokeSim", s_node_smokeSim_group, "Node_Fluid_Group_Inline", [1, Node_Fluid_Group_Inline],, "Create group for smoke simulation.").setVersion(1120);
addNodeObject(generator, "StrandSim", s_node_strandSim, "Node_Strand_Group_Inline", [1, Node_Strand_Group_Inline], ["Hair"], "Create group for hair simulation.").setVersion(1140);

View file

@ -4,10 +4,12 @@
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float threshold;
void main() {
vec4 fluid = texture2D( gm_BaseTexture, v_vTexcoord );
gl_FragColor = vec4(0.);
if(fluid.r * fluid.a > 0.5)
if(fluid.r * fluid.a > threshold)
gl_FragColor = vec4(1.);
}