hi tadr, sorry for the delay, but I also think you misunderstood some of the logic in the constraint logic... For example setting the direction of the intersection ray as you did using this line below MUST be a failure and doesn't make any sense.
Code:intersectRay.dir=p.constrain(box); // WRONG! :(
The
constrain method is used to clip a point to stay within a given bounding box. Since you've already established in an earlier line above that the point is inside the box, then this method simply does nothing. But on top of that, the context of how you use this method is wrong, since you now also assign this point position as direction for the intersection test ray and this will produce chaotic results you're getting. Instead the direction should be relative to the box position, see my previous post...
Anyway, I've created a new example showing how to use the above BoxConstraint class properly, so hope this helps now for real
Code:import processing.opengl.*;
import toxi.geom.*;
import toxi.physics.*;
import toxi.physics.constraints.*;
BoxConstraint[] boxes=new BoxConstraint[2];
int NUM_PARTICLES = 100;
int REST_LENGTH=10;
VerletPhysics physics;
VerletParticle head;
void setup() {
size(1024,576,OPENGL);
// create 2 boxes
boxes[0]=new BoxConstraint(new Vec3D(100,-100,-100),new Vec3D(150,100,100));
boxes[1]=new BoxConstraint(new Vec3D(-150,-100,-100),new Vec3D(-100,100,100));
// setup physics engine
physics=new VerletPhysics();
physics.gravity=Vec3D.Y_AXIS.scale(0.02);
VerletParticle prev=null;
// create particle string and assign boxes as constraints to each particle
for(int i=0; i<NUM_PARTICLES; i++) {
VerletParticle p=new VerletParticle(new Vec3D((i-NUM_PARTICLES/2)*REST_LENGTH,-200,0));
for(int j=0; j<boxes.length; j++) {
p.addConstraint(boxes[j]);
}
physics.addParticle(p);
if (prev!=null) {
physics.addSpring(new VerletSpring(prev,p,REST_LENGTH, 0.5));
}
prev=p;
}
// anchor the 1st particle in space
physics.particles.get(0).lock();
}
void draw() {
physics.update();
background(255);
noFill();
translate(width/2,height/2,0);
rotateX(-0.33);
rotateY(frameCount*0.01);
// draw the box obstacles
for(int i=0; i<boxes.length; i++) {
boxes[i].draw();
}
// draw all springs
beginShape(LINES);
for(Iterator i=physics.springs.iterator(); i.hasNext();) {
VerletSpring s=(VerletSpring)i.next();
vertex(s.a.x,s.a.y,s.a.z); vertex(s.b.x,s.b.y,s.b.z);
}
endShape();
for(Iterator i=physics.particles.iterator(); i.hasNext();) {
VerletParticle p=(VerletParticle)i.next();
ellipse(p.x,p.y,2,2);
}
}
class BoxConstraint implements ParticleConstraint {
public AABB box;
protected Ray3D intersectRay;
public BoxConstraint(Vec3D min, Vec3D max) {
this(AABB.fromMinMax(min,max));
}
public BoxConstraint(AABB box) {
this.box=box;
this.intersectRay=new Ray3D(box,new Vec3D());
}
public void apply(VerletParticle p) {
if (p.isInAABB(box)) {
intersectRay.dir=box.sub(p).normalize();
p.set(box.intersectsRay(intersectRay,0,Float.MAX_VALUE));
}
}
public void draw() {
Vec3D m=box.getMin();
Vec3D n=box.getMax();
beginShape(QUAD_STRIP);
stroke(0);
vertex(m.x,m.y,m.z); vertex(n.x,m.y,m.z);
vertex(m.x,n.y,m.z); vertex(n.x,n.y,m.z);
vertex(m.x,n.y,n.z); vertex(n.x,n.y,n.z);
vertex(m.x,m.y,n.z); vertex(n.x,m.y,n.z);
vertex(m.x,m.y,m.z); vertex(n.x,m.y,m.z);
endShape();
}
}