Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

How to draw colored 3D metaballs with toxiclibs ?

edited April 2018

Hi,

Following this thread (where I was trying to gather informations on metaballs) I decided to use the toxiclibs library in order to draw one myself.

Here is the kind of result I would like to achieve: from Zach Lieberman (see full motion here) from Wenzy Yang (see full motion here)

Here's what I could do so far:  see HD here

Questions:

• How to give each metaball a specific color like in the first picture ? I tried here but to no avail. It seems toxiclibs doesn't allow to assign different colors to multiple objects within a for loop.
• How to apply linear interpolations to the mesh vertices (with the toxiclibs library) in order to get smoother contours ?
• How can I improve the script to make the sketch run faster ? When I draw each face individually with coordinates-based colors (see GIF above) (from line 42 to 51 below) the sketch is running very slow (8 fps vs 60 fps without coordinates-based colors).

Alternatively, what I would like to know:

• How did Wenzy Yang draw live such smooth contours (second picture) without experiencing any lag ? With toxiclibs, drawing colored metaballs from an equally dense VolumetricSpaceArray would be too computer intensive. (Hence my question on linear interpolations).

If @amnon or @toxmeister or anyone familiar with the toxiclibs library happen to read this question, I would be immensely grateful for your help !

PS: PLEASE do not move this thread to the "Python mode" category since all the questions are about the toxiclibs library !

full code:

from toxi.processing import ToxiclibsSupport

mesh = TriangleMesh("mesh")
iso, grid, dim = .3, 70, 700
scl = Vec3D(dim, dim, dim)
volume = VolumetricSpaceArray(scl, grid, grid, grid)
surface, brush = ArrayIsoSurface(volume), RoundBrush(volume, scl.x() / 2)

def setup():
global balls, gfx, a, cam
size(720, 720, P3D)
smooth(8)

cam, gfx, a = PeasyCam(this, 700), ToxiclibsSupport(this), Attractor(0, 0, 0, 1, 100)
balls = []
[balls.append(Ball()) for e in range(10)]
noStroke()
beginShape(TRIANGLES)

def draw():
background(0)
print frameRate

volume.clear()
for i, b in enumerate(balls):
force = a.attract(b)
b.applyForce(force)
b.update()
b.display()
volume.closeSides()

surface.reset()
surface.computeSurfaceMesh(mesh,iso)
mesh.computeVertexNormals()
gfx.mesh(mesh, True)

num = mesh.getNumFaces()
for i in range(num):
f = mesh.faces[i]
fill(180 + f.a.x(), 180 + f.a.y(), 180 - f.a.z())
vertex(f.a.x(), f.a.y(), f.a.z())
fill(180 + f.b.x(), 180 + f.b.y(), 180 - f.b.z())
vertex(f.b.x(), f.b.y(), f.b.z())
fill(180 + f.c.x(), 180 + f.c.y(), 180 - f.c.z())
vertex(f.c.x(), f.c.y(), f.c.z())
endShape()

cam.rotateY(.03)

class Ball(object):
def __init__(self):
self.r = random(10, 220)
self.pos = PVector(random(-100,100), random(-100,100), random(-100, 100))
self.vel = PVector(0, 0, 0)
self.acceleration = PVector(0, 0, 0)
self.mass = 1 + (self.r * .01)

def display(self):
v = Vec3D(self.pos.x, self.pos.y, self.pos.z)
brush.setSize(self.r)
brush.drawAtAbsolutePos(v, 1)

def applyForce(self, f):
f = f / self.mass
self.acceleration += f *.5

def update(self):
self.vel += self.acceleration
self.pos += self.vel
self.acceleration *= 0
self.vel.limit(10)

class Attractor():
def __init__(self, x, y, z, m, g):
self.location = PVector(x, y, z)
self.mass = m
self.G = g

def attract(self, m):
force = PVector.sub(self.location, m.pos)
d = force.mag()
d = constrain(d, 5, 25)
force.normalize()
strength = (self.G * self.mass * m.mass) / (d * d)

if keyPressed and m.mass < 1.5:
force.mult(-strength*2)

return force
Tagged: