We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi Jeremy, thank you for taking the time to answer my question.
...now you want create a hard threshold on your alpha mask by multiplying the alpha() of each pixel by 18, then subtract 7. Is that right?
It is right: multiplying by 19 to 60 (alpha contrast), then subtracting 9 (alpha offset).
A shader is not the only way to manipulate color information -- you can use red(), green(), blue(), alpha(), or use bit fiddling and shifting of the ARGB color information
I know, that's exactly what I tried previously (see our last discussion). Overall, I think this approach (loadPixels(
) / updatePixels()
) is not appropriate when dealing with multiple moving objects, even with bit-shifting (good for pictures though).
Based on the example you provided, my sketch runs at 5 fps with 5 bouncing balls and for some reason they do not "melt" when colliding (no gooey effect).
With a shader, the same sketch runs at 60 fps with 700 bouncing balls and I get that metaball sort of effect. (Not exactly the one I'm looking for, obviously, but something quite close I came up with by fiddling with the color matrix).
test with 100 balls
I really believe the solution lies in a shader implementation. Let's hope someone can help me find a way to play with that alpha contrast channel in GLSL.
@digitalmartyn -- How are the shapes defined? Boxes / voxels? A collection of vertices and edges?
The nature of your shape data is going to affect how you discover / define the bounds that the metaball must enclose. For example, you could define a sphere whose radius is the corner radius of each box, then use the collection of spheres to define the metaball.
Lots of metaball algorithm discussion recently:
Has anyone seen examples or references for creating a smoothed hull around randomly placed shapes?
Essentially a metaball algorithm
thanks in advance.
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:
for
loop.Alternatively, what I would like to know:
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:
add_library('toxiclibs_p5')
add_library('toxiclibscore')
add_library('volumeutils')
add_library('peasycam')
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
@kfrajer @jeremydouglass Since my script is heavily depending on the tocixlibs library, would you guys mind if I post a question related to this metaball in the Library Questions" category ? I was hoping that maybe amnon or toxmeister would help even though they both don't seem to be very active on this forum anymore.
Update: I've managed to make a bloby metaball (sort of fusion of several metaballs) using the toxclibs library.
But there's still one major thing I can't figure out:
On a similar issue with the toxiclibs library, @amnon replied:
TriangleMesh does not support colored faces. You have to either extend the class or store this information externally and then draw each face individually with it's connected color.
Following this answer I tried to draw each face individually:
beginShape(TRIANGLES)
num = mesh.getNumFaces()
for e in range(num):
f = mesh.faces[e]
fill(e * .01 , 82 , e*.03)
vertex(f.a.x(), f.a.y(), f.a.z())
vertex(f.b.x(), f.b.y(), f.b.z())
vertex(f.c.x(), f.c.y(), f.c.z())
endShape()
It becomes then possible to draw different colors depending on the face's index, however it still doesn't tell me how to give each ball a different color
Do you guys have any idea how to solve this problem ?
Full code:
add_library('toxiclibs_p5')
add_library('toxiclibscore')
add_library('volumeutils')
add_library('peasycam')
from toxi.processing import ToxiclibsSupport
mesh = TriangleMesh("mesh")
iso, grid, dim = .5, 50, 800
scl = Vec3D(dim, dim, dim)
volume = VolumetricSpaceArray(scl, grid, grid, grid)
surface, brush = ArrayIsoSurface(volume), RoundBrush(volume, scl.x() / 2)
def setup():
global points, gfx, a
size(720, 720, OPENGL)
cam, gfx, a = PeasyCam(this, 800), ToxiclibsSupport(this), Attractor(0, 0, 0, 1, 100)
cam.rotateY(4)
points = []
[points.append(Point()) for e in range(10)]
noStroke()
def draw():
background(0)
lights()
volume.clear()
for i, p in enumerate(points):
force = a.attract(p)
p.applyForce(force)
p.update()
p.display()
volume.closeSides()
surface.reset()
surface.computeSurfaceMesh(mesh,iso)
mesh.computeVertexNormals()
gfx.mesh(mesh, True)
# beginShape(TRIANGLES)
# num = mesh.getNumFaces()
# for i in range(num):
# f = mesh.faces[i]
# fill(100 + i * .01 , 182 , 100 + i*.03)
# vertex(f.a.x(), f.a.y(), f.a.z())
# vertex(f.b.x(), f.b.y(), f.b.z())
# vertex(f.c.x(), f.c.y(), f.c.z())
# endShape()
class Point(object):
def __init__(self):
self.r = random(15, 140)
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 * .006)
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
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()
force.normalize()
strength = (self.G * self.mass * m.mass) / (d * d)
if keyPressed:
force.mult(-strength*2)
return force
@kfrajer @jeremydouglass sorry for not replying I'm doing some research. I'll comment back as soon as I'm finished with this metaball thing. (Thank you both for the links. It seems the ray marching technique is more widespread than I thought. Not sure yet if I'll implement it in a shader)
Of course I've read it but it seems that coding a 3d metaball is slightly more complicated than just adding another dimension to the 2d version.
The solution you suggest is computationnally very expensive and doesn't take into account the tracing of the metaball edges.
Quoting Zack Lieberman:
Metaballs is an old school computer graphics algorithm where you define shapes via an implicit functions and use a technique like marching cubes to trace the edges of those functions on some sort of grid.
Quoting Mike Walczyk:
The trick is to use signed distance functions or SDF. These are mathematical functions that take a point in space and tell you how far that point is from a surface.
In order to render the scene, we are going to use a technique called ray marching. At a high level, we will shoot out a bunch of imaginary rays from a virtual camera that is looking at our world. For each of these rays, we are going to "march" along the direction of the ray, and at each step, evaluate our SDF. This will tell us: "from where I currently stand, how far am I from the closest point on the surface of our sphere?"
More on his blog post
Did you read the 2D metaball? It’s essentially a heat map of summing up distances to the balls.
if you think this in 3D you would have a 3D heat map. That means triple nested for loop over a section of space and adding up colors following distance to balls.
Hi everyone,
Among the various coding challenges I set for myself there's one at the top of my list that still remains obscure and rather complex to me: coding a 3d metaball.
Since I first saw Zack Lieberman's work on 3d blobs and metaballs I've been obssessed with them.
made by Zack Lieberman with OpenFrameworks
made by Satoshi Horii (Rhizomatics) probably with OpenFrameworks
made by Mike Walczyk with OpenFrameworks and rendered in TouchDesigner (? not sure)
made by Martin Meurin with Processing
I've read the wikipedia page, I know from other sources that it may involve Ray Marching shaders and Signed distance Functions but the problem is I haven't been able to find a source code, even a snippet, to work on. I'm relatively new to Processing and starting from scratch for this challenge seems really tough.
I would love to read your suggestions and advices. If you have any link to tutorials, step-by-step roadmaps or even code in Java, Python or even C++ I would really appreciate if you could share it here.
Thank you !
Hi guys,
I made several Python versions of 2d metaball sketches I found here on the forum or on the CodingTrain Github.
Problem: It runs super slow (<1fps !) while all Java versions run very smoothly (60fps).
Questions:
Why such a difference in the framerates ?
Is is possible to improve the Python code or am i for ever doomed for having chosen Python mode over Java mode ?
original JAVA code
main tab:
Blob[] blobs = new Blob[10];
void setup() {
size(640, 360);
colorMode(HSB);
for (int i = 0; i < blobs.length; i++) {
blobs[i] = new Blob(random(width), random(height));
}
}
void draw() {
background(51);
println(frameRate);
loadPixels();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = x + y * width;
float sum = 0;
for (Blob b : blobs) {
float d = dist(x, y, b.pos.x, b.pos.y);
sum += 10 * b.r / d;
}
pixels[index] = color(sum, 255, 255);
}
}
updatePixels();
for (Blob b : blobs) {
b.update();
//b.show();
}
}
blob class
class Blob {
PVector pos;
float r;
PVector vel;
Blob(float x, float y) {
pos = new PVector(x, y);
vel = PVector.random2D();
vel.mult(random(2, 5));
r = random(120, 400);
}
void update() {
pos.add(vel);
if (pos.x > width || pos.x < 0) {
vel.x *= -1;
}
if (pos.y > height || pos.y < 0) {
vel.y *= -1;
}
}
void show() {
noFill();
stroke(0);
strokeWeight(4);
ellipse(pos.x, pos.y, r*2, r*2);
}
}
PYTHON code
liste = []
def setup():
size(640, 360, FX2D)
colorMode(HSB)
[liste.append(Blob(random(width), random(height))) for e in range(10)]
def draw():
loadPixels()
for x in range(width):
for y in range(height):
index = x + y * width
sum = 0
for e in liste:
d = dist(x, y, e.pos.x, e.pos.y)
try:
sum += 10 * e.r / d
except ZeroDivisionError:
return 1
pixels[index] = color(sum, 255, 255)
updatePixels()
for e in liste:
e.update()
class Blob(object):
def __init__(self, x, y):
self.pos = PVector(x, y)
self.velocity = PVector.random2D()
self.velocity.mult(random(2, 5))
self.r = random(120, 400)
def update(self):
self.pos.add(self.velocity)
if self.pos.x > width or self.pos.x < 0:
self.velocity.x *= -1
if self.pos.y > height or self.pos.y < 0:
self.velocity.y *= -1
For every Blob detected by the library I create a new object of my class Metaball.
void createMetaballs()
{
Blob blob;
Metaball mettball;
int numberOfBlobs = theBlobDetection.getBlobNb();
int numberOfMetaballs = 0;
float blobX, blobY;
for (int n=0; n<numberOfBlobs; n++)
{
blob=theBlobDetection.getBlob(n);
blobX=blob.x*width;
blobY=blob.y*height;
if (blob != null && numberOfMetaballs <= numberOfBlobs)
{
mettball = new Metaball(blobX, blobY);
mettball.id = blob.id;
metaballs.add(mettball);
numberOfMetaballs++;
}
}
text("Mettbälle: " + metaballs.size() + " / Blobs: " + numberOfBlobs, 10, height-10);
}
The problem for which I didn't manage to come up with a solution is how to kill the Metaball when a blob 'dies'. I tried to remove them from the arraylist when a blob is null but I didn't worked and the method just creates more metaballs... Somehow I have to compare the metaball with the blob I guess. Any ideas? Highly appreciated
I am trying to extend the Blob-class of v3ga blobDetection library but I get an error saying:
implicit super constructor Blob() is undefined. must explicitly invoke another constructor
Calling super() in the constructor did not help because it says that class Blob does not have a constructor Blob()
.
Does anybody have experience in extending this class?