/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.app.balls3d; import sim.engine.*; import sim.util.*; import sim.field.network.*; import sim.field.continuous.*; public class Ball implements Steppable { private static final long serialVersionUID = 1; // force on the Ball public double forcex; public double forcey; public double forcez; // Ball mass public double mass; // Old mass -- for Java3D to know the mass has changed public double oldMass; // Current Ball velocity public double velocityx; public double velocityy; public double velocityz; // did the Ball collide? public boolean collision; // Old collision -- for Java3D to know the collision has changed public boolean oldCollision; // for drawing: always sqrt of mass public double diameter; public double getVelocityX() { return velocityx; } public void setVelocityX(double val) { velocityx = val; } public double getVelocityY() { return velocityy; } public void setVelocityY(double val) { velocityy = val; } public double getVelocityZ() { return velocityz; } public void setVelocityZ(double val) { velocityz = val; } public double getMass() { return mass; } public void setMass(double val) { if (val > 0) { mass = val; diameter = Math.sqrt(val); } } public Ball(double vx, double vy, double vz, double m) { velocityx=vx; velocityy=vy; velocityz=vz; mass = m; oldMass = m; diameter = Math.sqrt(m); } Bag myBag = new Bag(); public void computeCollision(Balls3D tut) { Double3D me = tut.balls.getObjectLocation(this); Bag b = tut.balls.getNeighborsExactlyWithinDistance(me,Balls3D.collisionDistance); collision = b.numObjs > 1; // other than myself of course } public void addForce(Double3D otherBallLoc, Double3D myLoc, Band band) { // compute difference final double dx = otherBallLoc.x - myLoc.x; final double dy = otherBallLoc.y - myLoc.y; final double dz = otherBallLoc.z - myLoc.z; final double len = Math.sqrt(dx*dx + dy*dy + dz*dz); final double l = band.laxDistance; final double k = band.strength/512.0; // cut-down final double forcemagnitude = (len - l) * k; // add rubber band force if (len - l > 0) { forcex += (dx * forcemagnitude) / len; forcey += (dy * forcemagnitude) / len; forcez += (dz * forcemagnitude) / len; } } public void computeForce(SimState state) { Balls3D tut = (Balls3D) state; Network bands = tut.bands; Continuous3D balls = tut.balls; Double3D me = balls.getObjectLocation(this); forcex = 0; forcey = 0; forcez = 0; // rubber bands exert a force both ways -- // so our graph is undirected. We need to get edges // both in and out, as they could be located either place Bag in = bands.getEdgesIn(this); Bag out = bands.getEdgesOut(this); if (in!=null) for(int x=0;x<in.numObjs;x++) { Edge e = (Edge)(in.objs[x]); Band b = (Band) (e.info); Ball other = (Ball)(e.from()); // from him to me Double3D him = balls.getObjectLocation(other); addForce(him,me,b); } if (out!=null) for(int x=0;x<out.numObjs;x++) { Edge e = (Edge)(out.objs[x]); Band b = (Band) (e.info); Ball other = (Ball)(e.to()); // from me to him Double3D him = balls.getObjectLocation(other); addForce(him,me,b); } } public void step(SimState state) { Balls3D tut = (Balls3D) state; // acceleration = force / mass final double ax = forcex / mass; final double ay = forcey / mass; final double az = forcez / mass; // velocity = velocity + acceleration velocityx += ax; velocityy += ay; velocityz += az; // position = position + velocity Double3D pos = tut.balls.getObjectLocation(this); Double3D newpos = new Double3D(pos.x+velocityx, pos.y + velocityy, pos.z + velocityz); tut.balls.setObjectLocation(this,newpos); // compute collisions computeCollision(tut); } }