# Soft Bodies example - Modify 2d mesh in real time

It uses hidden control points (circle bodies) to modify the shape of the mesh, the function triangulate use all of these centers and then with a shader draw it.
Using some specific options of joints you can setup this behaviour, check out the code.

```MyNode = class()

function MyNode:init(nSegments)
touches = 0
parameter.watch("touches")
parameter.boolean("detach",false,detachInner)
parameter.boolean("elastic",false,changeJoints)
self.numSegments = nSegments or 12
self.ptmRatio    = math.pi
local center = vec2(WIDTH/2,HEIGHT/2)
local springness = 4.0
local deltaAngle = (2.0*math.pi)/self.numSegments
self.bodies = {}
local cos = math.cos
local sin = math.sin
for i=0, self.numSegments-1 do
local theta = deltaAngle * i
local x = radius * cos(theta)
local y = radius * sin(theta)
self.bodies[i] = self:createCircle(
vec2( x/self.ptmRatio + math.random(-16,16),
y/self.ptmRatio + math.random(6) ) + center
,37
)
self.bodies[i].info= {origin = vec2(x,y)}
end
-- inner circle
self.inner = self:createCircle(center, 23)
-- create joints
self.inner.info = {
joints = {}
}
self.inner.type = STATIC
self.inner.fixedRotation = true
for i=0, self.numSegments-1 do
local neighborIndex = math.fmod (i+1, self.numSegments)
local currentBody   = self.bodies[i]
local neighborBody  = self.bodies[neighborIndex]

currentBody.info.joint = physics.joint(
DISTANCE, currentBody,neighborBody,
currentBody.worldCenter,
neighborBody.worldCenter
)
currentBody.info.color = color(
math.random(10,80), math.random(20,60), math.random(166,255)
)

currentBody.info.joint.frequency = springness
currentBody.info.joint.dampingRatio = 0.5

-- connect center body with a joint
self.inner.info.joints[i] = physics.joint(
DISTANCE,
currentBody, self.inner,
currentBody.worldCenter,
center
)

self.inner.info.joints[i].frequency = springness
self.inner.info.joints[i].dampingRatio = 0.1
end
-- create ground
self.ground = physics.body(POLYGON,
vec2(0,10),
vec2(0,0),
vec2(WIDTH,0),
vec2(WIDTH,10)
)
self.ground.type = STATIC
-- touches table
self.touches = {}

-- mesh
self.m = mesh()

[[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec4 color;
varying lowp vec4 vColor;
varying mediump vec4 vPos;
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
vPos = position;

//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
[[
//Default precision qualifier
precision highp float;

//interpolated vertex color for this fragment
varying lowp vec4 vColor;
varying mediump vec4 vPos;

//Brick variables
uniform vec4 brickColor;
uniform vec4 mortarColor;
uniform float time;
uniform vec3 brickSize;
uniform vec3 brickPct;

void main()
{
vec3 color;
vec3 position, useBrick;

position = vPos.xyz / brickSize.xyz;

if( fract(position.y * 0.5) > 0.5 )
{
position.x += 0.5;
position.z += 1.0;
}

position = fract(position);
useBrick = step(position, brickPct.xyz);

color = mix(mortarColor.rgb, brickColor.rgb,
useBrick.x * useBrick.y * useBrick.z);
color *= vColor.rgb;

//Set the output color to the texture color
gl_FragColor = vec4(color, 1.0);
vec2 uv = gl_FragColor.xy/vec3(1.0,1.0,0.0).xy;
gl_FragColor = vec4(uv, 0.5 + 0.5 * sin(time), 1.0);
}

]])
end

function MyNode:createCircle(pos,r)
local circle = physics.body(CIRCLE, r)
circle.density = 0.1
circle.restitution = 0.05
circle.friction = 1.0
circle.type = DYNAMIC
circle.x = pos.x
circle.y = pos.y
circle.fixedRotation = true
return circle
end

function MyNode:draw()
sprite(self.bg, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)

fill(255)
-- draw ground
rectMode(CENTER)
rect(
self.ground.points[1].x/2, self.ground.points[1].y/2,
self.ground.points[1].x, self.ground.points[1].y
)
strokeWidth(1)
lineCapMode(ROUND)

-- draw inner joints
for i=0,#self.inner.info.joints do
local joint = self.inner.info.joints[i]
--[[ line(
joint.anchorA.x, joint.anchorA.y,
joint.anchorB.x, joint.anchorB.y
)]]--
end
local vs = {}
for i=0, self.numSegments-1 do
local body = self.bodies[i]
-- draw joint also
if body.info.joint then
--[[ line(
body.info.joint.anchorA.x, body.info.joint.anchorA.y,
body.info.joint.anchorB.x, body.info.joint.anchorB.y
)]]--
end
fill(body.info.color)
table.insert(vs, vec2(body.x,body.y))
end
fill(0)
--table.sort(vs, compareV2)
self.m.vertices = triangulate(vs)
self.m:setColors(127,127,127,155)
blendMode(MULTIPLY)
self.m:draw()
blendMode(NORMAL)
end

function MyNode:isTouchingBody(touch)
local tpoint = vec2(touch.x, touch.y)
for i=0, self.numSegments-1 do
local body = self.bodies[i]
if body:testPoint(tpoint) then
return body
end
end
return nil
end

function MyNode:isDraggingKey(key)
for i,b in ipairs(self.touches) do
if key==b.key then return i end
end
return -1
end

function MyNode:touched(touch)
-- check if it is touching a body:
local index = self:isDraggingKey(touch.id)
if index>-1 then
local tpoint = vec2(touch.x,touch.y)
if self.touches[index].body then
local t =  self.touches[index]
if t.origin:dist(tpoint)v2.x and v1.y>v2.y)
return v1.x<v2.x and v1.y<v2.y
end

-- SoftBody
node = nil
-- Use this function to perform your initial setup
function setup()
node = MyNode()
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)

-- This sets the line thickness
strokeWidth(5)

node:draw()
end

function touched(touch)
node:touched(touch)
end

```

Video: