diff --git a/Sources/arm/Context.hx b/Sources/arm/Context.hx index dd6c8e5e..c76a7107 100644 --- a/Sources/arm/Context.hx +++ b/Sources/arm/Context.hx @@ -143,6 +143,10 @@ class Context { public static var particleHitX = 0.0; public static var particleHitY = 0.0; public static var particleHitZ = 0.0; + public static var lastParticleHitX = 0.0; + public static var lastParticleHitY = 0.0; + public static var lastParticleHitZ = 0.0; + public static var particleTimer: iron.system.Tween.TAnim = null; public static var paintBody: arm.plugin.PhysicsBody = null; #end diff --git a/Sources/arm/io/ImportMesh.hx b/Sources/arm/io/ImportMesh.hx index 5fbab631..d1b63b89 100644 --- a/Sources/arm/io/ImportMesh.hx +++ b/Sources/arm/io/ImportMesh.hx @@ -95,7 +95,6 @@ class ImportMesh { #if arm_physics Context.paintBody = null; - arm.util.ParticleUtil.initParticlePhysics(); #end } diff --git a/Sources/arm/node/MakeParticle.hx b/Sources/arm/node/MakeParticle.hx index 79eb1c3a..644c129a 100644 --- a/Sources/arm/node/MakeParticle.hx +++ b/Sources/arm/node/MakeParticle.hx @@ -97,7 +97,14 @@ class MakeParticle { vert.add_uniform('mat4 W', '_worldMatrix'); vert.write_attrib('wpos = mul(vec4(pos.xyz, 1.0), W);'); frag.add_uniform('vec3 particleHit', '_particleHit'); - frag.write('dist = distance(particleHit, wpos.xyz) * 10.0;'); + frag.add_uniform('vec3 particleHitLast', '_particleHitLast'); + + frag.write('vec3 pa = wpos.xyz - particleHit;'); + frag.write('vec3 ba = particleHitLast - particleHit;'); + frag.write('float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);'); + frag.write('dist = length(pa - ba * h) * 10.0;'); + // frag.write('dist = distance(particleHit, wpos.xyz) * 10.0;'); + frag.write('if (dist > 1.0) discard;'); frag.write('float str = clamp(pow(1.0 / dist * brushHardness * 0.2, 4.0), 0.0, 1.0) * opacity;'); frag.write('if (particleHit.x == 0.0 && particleHit.y == 0.0 && particleHit.z == 0.0) str = 0.0;'); diff --git a/Sources/arm/render/Uniforms.hx b/Sources/arm/render/Uniforms.hx index 53fdf3dd..f178ebb9 100644 --- a/Sources/arm/render/Uniforms.hx +++ b/Sources/arm/render/Uniforms.hx @@ -220,6 +220,11 @@ class Uniforms { v.set(Context.particleHitX, Context.particleHitY, Context.particleHitZ); return v; } + case "_particleHitLast": { + v = iron.object.Uniforms.helpVec; + v.set(Context.lastParticleHitX, Context.lastParticleHitY, Context.lastParticleHitZ); + return v; + } #end } diff --git a/Sources/arm/ui/UISidebar.hx b/Sources/arm/ui/UISidebar.hx index 25b6d928..e6d7fd63 100644 --- a/Sources/arm/ui/UISidebar.hx +++ b/Sources/arm/ui/UISidebar.hx @@ -434,12 +434,19 @@ class UISidebar { #if arm_physics if (Context.tool == ToolParticle && Context.particlePhysics && inViewport && !Context.paint2d) { + arm.util.ParticleUtil.initParticlePhysics(); var world = arm.plugin.PhysicsWorld.active; world.lateUpdate(); Context.ddirty = 2; Context.rdirty = 2; if (mouse.started()) { + if (Context.particleTimer != null) { + iron.system.Tween.stop(Context.particleTimer); + Context.particleTimer.done(); + Context.particleTimer = null; + } History.pushUndo = true; + Context.particleHitX = Context.particleHitY = Context.particleHitZ = 0; Scene.active.spawnObject(".Sphere", null, function(o: Object) { iron.data.Data.getMaterial("Scene", ".Gizmo", function(md: MaterialData) { var mo: MeshObject = cast o; @@ -456,12 +463,15 @@ class UISidebar { var body = new arm.plugin.PhysicsBody(); body.shape = arm.plugin.PhysicsBody.ShapeType.ShapeSphere; body.mass = 1.0; + body.ccd = true; + mo.transform.radius /= 10; // Lower ccd radius mo.addTrait(body); + mo.transform.radius *= 10; var ray = iron.math.RayCaster.getRay(mouse.viewX, mouse.viewY, camera); - body.applyImpulse(ray.direction.mult(0.1)); + body.applyImpulse(ray.direction.mult(0.15)); - iron.system.Tween.timer(5, mo.remove); + Context.particleTimer = iron.system.Tween.timer(5, mo.remove); }); }); } @@ -469,10 +479,14 @@ class UISidebar { var pairs = world.getContactPairs(Context.paintBody); if (pairs != null) { for (p in pairs) { + Context.lastParticleHitX = Context.particleHitX != 0 ? Context.particleHitX : p.posA.x; + Context.lastParticleHitY = Context.particleHitY != 0 ? Context.particleHitY : p.posA.y; + Context.lastParticleHitZ = Context.particleHitZ != 0 ? Context.particleHitZ : p.posA.z; Context.particleHitX = p.posA.x; Context.particleHitY = p.posA.y; Context.particleHitZ = p.posA.z; Context.pdirty = 1; + break; // 1 pair for now } } }