class Ball{
 
Tuple3f pos;
Tuple3f vel;
Vector history = new Vector();
Ball(float x, float y, float z, float dx, float dy, float dz){
pos = new Tuple3f(x,y,z);
vel = new Tuple3f(dx,dy,dz);
}
void draw(Raytracer tracer){
//check if we ran into anything
Ray isect = new Ray(pos,vel);
 
//are we going to collide in the next timeStep?
float mag = vel.getLength();
isect.maxDist = 100;
tracer.accelerator.findNearest(isect);
if (isect.occluder != null){
isect.maxDist = isect.distance;
/*
lightRay.draw(g,isect.maxDist);
pushMatrix();
fill(200,0,0);
noStroke();
translate(pos.x + isect.distance*vel.x,pos.y + isect.distance*vel.y,pos.z + isect.distance*vel.z);
sphere(1);
popMatrix();
*/
}
if (isect.distance < 50 && isect.occluder != null){
vel = vel.reflect(((Triangle)isect.occluder).gNormal);
vel.normalize();
vel.timesEquals((1.f-damping.getVal())*mag);
}
 
if (paused == 0){
pos.plusEquals(vel);
vel.y += 2;
}
 
pushMatrix();
fill(255,255,255);
noStroke();
translate(pos.x,pos.y,pos.z);
sphere(20);
popMatrix();
if (time%2 == 0){
history.insertElementAt(pos.getCopy(),0);
if (history.size() > 8) history.removeElementAt(8);
}
if (showTrails.getVal()){
stroke(250,250,250,50);
noFill();
beginShape();
Tuple3f pt;
for (int i =0; i < history.size(); i++){
pt = (Tuple3f)history.elementAt(i);
vertex(pt.x,pt.y,pt.z);
}
endShape();
}
}
}
//created=14 Oct 07
//description=Collision detection using a KD-Tree and an arbitrary mesh.
//title=Collision
//publish=true
//titlebar=Collision Detection Using a KD Tree
//tags=kdtree
 
import SGGUI.*;
import SGCamera.*;
import Raytracing.*;
import Tuple.*;
 
SGCamera cam;
Raytracer tracer;
 
Accelerator accel;
 
SGGUI controller;
VerticalLayout settings;
 
SGSlider damping, rate,energy;
SGCheckBox showOctree, showTrails;
SGLabel numHit;
PFont fnt;
 
Lamp light;
Ray isect;
 
Vector balls = new Vector();
 
 
int paused = 0;
 
int time = 0;
void setup(){
 
size(550,550,P3D);
fnt = loadFont("writing.vlw");
textFont(fnt);
textMode(SCREEN);
 
controller = new SGGUI(this,fnt);
controller.GUI_HIGHLIGHT = color(200,220,200);
settings = new VerticalLayout(controller,10,10,150);
settings.title = "Settings";
damping = new SGSlider( "Damping",.2,.05,0,.5);
rate = new SGSlider( "Rate",.4,.05,0,1);
energy = new SGSlider( "Energy",.5,.05,0,2);
showOctree = new SGCheckBox("Show KD-tree",0);
showTrails = new SGCheckBox("Show Trails",1);
 
settings.add(showOctree);
settings.add(showTrails);
settings.add(rate);
settings.add(damping);
settings.add(energy);
controller.add(settings);
cam = new SGCamera(this,100,-50,100,0,0,0);
cam.setMouseMode(LEFT,SGCamera.ORBIT);
cam.setMouseMode(RIGHT,SGCamera.DOLLY);
 
tracer = new Raytracer(this);
tracer.openFile("terrain.mra",cam);
sphereDetail(3);
frameRate(30);
 
 
accel = tracer.accelerator;
cam.lookAt(0,0,0);
 
}
 
 
 
public void draw(){
 
time++;
if (random(0,1)< rate.getVal()) balls.add(new Ball(0, random(-300,-100),random(-400,400),0,-energy.getVal(),energy.getVal()*random(-10,10)));
 
 
accel.showTree = showOctree.getVal();
 
background(64);
cam.feed();
tracer.draw();
lights();
Ball b;
for (int i=balls.size()-1; i >= 0; i--){
b = (Ball)balls.elementAt(i);
b.draw(tracer);
if (b.pos.y > 2500) balls.removeElementAt(i);
}
 
}