Dear all,
In the following example code I’m trying to add 3 new faces on top of one of the original 4 faces of a tetrahedron mesh. The mesh vertices are connected by springs.
My problem is that the vertices of the newly added faces don’t match the original tetrahedron, as if they were disconnected from the mesh (top grey 3D triangle).
It is all the more surprising that the newly added springs that share the same vertices positions DO fit the tetrahedron (top 3 red lines)
I would really appreciate if someone could help me find what’s wrong with this example sketch
import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.geom.mesh.subdiv.*;
import toxi.physics3d.*;
import toxi.physics3d.behaviors.*;
import toxi.physics3d.constraints.*;
import toxi.processing.*;
import peasy.*;
VerletPhysics3D physics;
WETriangleMesh mesh;
ToxiclibsSupport gfx;
PeasyCam cam;
void setup() {
perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000);
size(690, 460, P3D);
smooth(8);
cam = new PeasyCam(this, 150);
physics = new VerletPhysics3D();
physics.setDrag(1.1);
physics.setWorldBounds(new AABB(new Vec3D(), new Vec3D(width, height, height)));
mesh = new WETriangleMesh();
gfx = new ToxiclibsSupport(this);
//Create 4 particles to form a tetrahedron
for (int i = 0; i < 4; i++) {
VerletParticle3D p = new VerletParticle3D(Vec3D.randomVector());
physics.addParticle(p);
physics.addBehavior(new AttractionBehavior3D(p, 10, -4));
}
//Adding springs between particles
for (VerletParticle3D p1 : physics.particles) {
for (VerletParticle3D p2 : physics.particles) {
if (p1 != p2) {
VerletSpring3D s = new VerletSpring3D(p1, p2, 60, .1);
physics.addSpring(s);
}
}
}
//Adding faces between the 4 particles
VerletParticle3D p1 = physics.particles.get(0);
VerletParticle3D p2 = physics.particles.get(1);
VerletParticle3D p3 = physics.particles.get(2);
VerletParticle3D p4 = physics.particles.get(3);
mesh.addFace(p1, p2, p3);
mesh.addFace(p1, p3, p4);
mesh.addFace(p1, p2, p4);
mesh.addFace(p2, p3, p4);
}
void draw(){
background(30);
//Update physics
physics.update();
//Update mesh vertices by moving them to the current position of their associated particles
for (int i = 0, num = physics.particles.size(); i < num; i++) {
mesh.getVertexForID(i).set(physics.particles.get(i));
}
//Draw springs
for (int i = 0, num = physics.springs.size(); i < num; i++) {
stroke(255, 30, 30);
strokeWeight(1);
line(physics.springs.get(i).a.x(), physics.springs.get(i).a.y(), physics.springs.get(i).a.z(),
physics.springs.get(i).b.x(), physics.springs.get(i).b.y(), physics.springs.get(i).b.z());
}
//Display WETriangle mesh
noStroke();
fill(255, 200);
gfx.mesh(mesh);
}
void keyReleased(){
//Selecting first face + computing its centroid
Face f = mesh.getFaces().get(0);
VerletParticle3D centroid = new VerletParticle3D(new Triangle3D(f.a, f.b, f.c).computeCentroid());
// 3 vertices of the the first face
VerletParticle3D a = physics.particles.get(physics.particles.indexOf(f.a));
VerletParticle3D b = physics.particles.get(physics.particles.indexOf(f.b));
VerletParticle3D c = physics.particles.get(physics.particles.indexOf(f.c));
CreateFaces(a, b, c, centroid);
}
void CreateFaces(VerletParticle3D a, VerletParticle3D b, VerletParticle3D c, VerletParticle3D n) {
//Add centroid to physics + set repulsive behavior
physics.addParticle(n);
physics.addBehavior(new AttractionBehavior3D(n, 10, -4));
//Attach springs between the face vertices and the centroid
VerletSpring3D s1 = new VerletSpring3D(a, n, 40, .1);
VerletSpring3D s2 = new VerletSpring3D(b, n, 40, .1);
VerletSpring3D s3 = new VerletSpring3D(c, n, 40, .1);
physics.addSpring(s1);
physics.addSpring(s2);
physics.addSpring(s3);
//Remove original face
mesh.removeFace(mesh.getFaces().get(0));
//Add faces of the newly formed tetrahedron to the mesh
mesh.addFace(n, a, b);
mesh.addFace(n, b, c);
mesh.addFace(n, a, c);
}