fieldkit
Version:
Basic building blocks for computational design projects. Written in CoffeeScript for browser and server environments.
135 lines (103 loc) • 3.42 kB
text/coffeescript
###
Soft Body Dynamics
###
class Example extends fk.client.Sketch
Vec2 = fk.math.Vec2
State = fk.physics.State
rng = new fk.math.Random()
cMouse = new fk.Color(1,1,0)
setup: ->
@physics = new fk.physics.Physics()
@physics.constraintIterations = 1
@physics.springIterations = 16 # should be equals the maximum number of springs connected to a single object
# use 2D particles
@physics.emitter.type = fk.physics.Particle2
@physics.emitter.rate = 0
# Gravity
@physics.add new fk.physics.Force new Vec2(0, 1), 0.65
# makes sure our particles never leave the canvas
@physics.add new fk.physics.Area new Vec2(), new Vec2(@width, @height-100)
# @physics.add new fk.physics.Collision(@physics)
# a = @a
# class CustomAttractor extends fk.physics.Attractor
# tmp = a.position.clone()
# rangeSq = 0
#
# isEnabled: false
#
# prepare: -> rangeSq = @range * @range
#
# apply: (particle) ->
# if @isEnabled and particle == a
# tmp.set(@target).sub particle.position
# distSq = tmp.lengthSquared()
# if distSq > 0 and distSq < rangeSq
#
# # normalize and inverse proportional weight
# dist = Math.sqrt(distSq)
## tmp.scale (1 / dist) * (1 - dist / @range) * @weight
# tmp.normalize().scale @weight
# particle.force.add tmp
#
# @attractor = new CustomAttractor new Vec2(), 150, 1.0
# @physics.addBehaviour @attractor
@makeCreature @width / 2, @height / 2
makeCreature: (x, y) ->
sizeMin = 100
sizeMax = 150
center = particle = @physics.emitter.create()
particle.setPosition2 x, y
nPoints = fk.math.randi 8, 64
hull = []
alpha = 0
for i in [0..nPoints]
alpha += Math.PI * 2 / nPoints
jitter = sizeMin + Math.random() * (sizeMax - sizeMin)
particle = @physics.emitter.create()
particle.position.set center.position
particle.position.x += Math.sin(alpha) * jitter
particle.position.y += Math.cos(alpha) * jitter
particle.clearVelocity()
particle.size = 3
hull.push particle
createLink = (a, b, strength) =>
spring = @physics.addSpring new fk.physics.Spring a, b, strength
spring
# create exterior springs
for particle, i in hull
prev = if i == 0 then hull[ hull.length - 1] else hull[ i-1 ]
spring = createLink particle, prev, 0.3
spring.color = new fk.Color(1,1,0)
# create interior support springs
for particle, i in hull
if fk.math.randf(0,1) > 0.25
spring = createLink particle, center, 0.5
spring.color = new fk.Color(0,1,1)
mouseDown: ->
@makeCreature @mouseX, @mouseY
# @attractor.isEnabled = true
mouseUp: ->
# @attractor.isEnabled = false
draw: ->
#
# @attractor.target.set2 @mouseX, @mouseY
# update physics
@physics.update()
# -- Draw --
@background(0)
# draw springs
@noFill()
@lineWidth 2
@stroke 255
for spring in @physics.springs
@stroke spring.color
@line spring.a.position, spring.b.position
# draw particles
@noStroke()
for particle in @physics.particles
@fill 255
@circle particle.position.x, particle.position.y, particle.size
# draw mouse
# if @attractor.isEnabled
# @fill 0, 255, 0
# @circle this.mouseX, this.mouseY, 7