Undo a commit I made and minor fix the DesertPanel
[desert.git] / src / org / sourceforge / desert / ParticleEngineJBulletImplementation.java
blob5999ff8834ba74586efd8fa672c241d2fc465115
1 /*
2 * Copyright (c) 2010 The Desert team
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
26 package org.sourceforge.desert;
28 import com.bulletphysics.collision.broadphase.AxisSweep3;
29 import com.bulletphysics.collision.broadphase.BroadphaseInterface;
30 import com.bulletphysics.collision.dispatch.CollisionDispatcher;
31 import com.bulletphysics.collision.dispatch.CollisionObject;
32 import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
33 import com.bulletphysics.collision.shapes.CollisionShape;
34 import com.bulletphysics.collision.shapes.SphereShape;
35 import com.bulletphysics.collision.shapes.StaticPlaneShape;
36 import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
37 import com.bulletphysics.dynamics.DynamicsWorld;
38 import com.bulletphysics.dynamics.RigidBody;
39 import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
40 import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
41 import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
42 import com.bulletphysics.linearmath.DefaultMotionState;
43 import com.bulletphysics.linearmath.Transform;
44 import java.awt.Dimension;
45 import java.util.Iterator;
46 import java.util.ListIterator;
47 import javax.vecmath.Vector3f;
48 import org.sourceforge.desert.Particle.Type;
50 /**
52 * @author codistmonk (creation 2010-04-17)
54 public class ParticleEngineJBulletImplementation implements ParticleEngine {
56 private final DynamicsWorld dynamicsWorld;
58 private final ParticleIterator particleIterator;
60 private RigidBody bottomBorder;
62 private RigidBody leftBorder;
64 private RigidBody topBorder;
66 private RigidBody rightBorder;
68 public ParticleEngineJBulletImplementation() {
69 this.dynamicsWorld = createDynamicsWorld();
70 this.particleIterator = this.new ParticleIterator();
73 @Override
74 public final Dimension getBoardSize() {
75 // FIXME this method doesn't work
76 final Transform transform = new Transform();
77 final int bottom = (int) this.bottomBorder.getMotionState().getWorldTransform(transform).origin.y;
78 final int left = (int) this.leftBorder.getMotionState().getWorldTransform(transform).origin.x;
79 final int top = (int) this.topBorder.getMotionState().getWorldTransform(transform).origin.y;
80 final int right = (int) this.rightBorder.getMotionState().getWorldTransform(transform).origin.x;
82 return new Dimension(right - left, top - bottom);
85 @Override
86 public final void setBoardSize(final Dimension size) {
87 if (this.bottomBorder != null) {
88 this.getDynamicsWorld().removeRigidBody(this.bottomBorder);
89 this.getDynamicsWorld().removeRigidBody(this.leftBorder);
90 this.getDynamicsWorld().removeRigidBody(this.topBorder);
91 this.getDynamicsWorld().removeRigidBody(this.rightBorder);
94 this.bottomBorder = createPlane(new Vector3f(0F, 1F, 0F), 0F);
95 this.leftBorder = createPlane(new Vector3f(1F, 0F, 0F), 0F);
96 this.topBorder = createPlane(new Vector3f(0F, -1F, 0F), (float) (-size.height));
97 this.rightBorder = createPlane(new Vector3f(-1F, 0F, 0F), (float) (-size.width));
99 this.getDynamicsWorld().addRigidBody(this.bottomBorder);
100 this.getDynamicsWorld().addRigidBody(this.leftBorder);
101 this.getDynamicsWorld().addRigidBody(this.topBorder);
102 this.getDynamicsWorld().addRigidBody(this.rightBorder);
105 @Override
106 public void addParticle(final Particle.Type type, final float x, final float y, final float speedX, final float speedY) {
107 final RigidBody rigidBody = createSphere(type.getMass(), type.getRadius(), new Vector3f(x, y, 0.0F));
109 rigidBody.setUserPointer(type);
110 rigidBody.setLinearVelocity(new Vector3f(speedX, speedY, 0F));
112 this.getDynamicsWorld().addRigidBody(rigidBody);
115 @Override
116 public final int getParticleCount() {
117 // The 4 border planes are also collision objects, so they must be
118 // subtracted (if they are defined) to count only the particles
119 return this.dynamicsWorld.getNumCollisionObjects() - (this.bottomBorder == null ? 0 : 4);
122 @Override
123 public final void update(final float deltaTime) {
124 this.getDynamicsWorld().stepSimulation(1000F * deltaTime);
127 @Override
128 public final Iterator<Particle> iterator() {
129 this.particleIterator.reset();
131 return this.particleIterator;
134 @Override
135 public final float getGravity() {
136 return (float) this.getDynamicsWorld().getGravity(new Vector3f()).y;
139 @Override
140 public final void setGravity(final float gravity) {
141 this.getDynamicsWorld().setGravity(new Vector3f(0F, gravity, 0F));
144 final DynamicsWorld getDynamicsWorld() {
145 return this.dynamicsWorld;
149 * @author codistmonk (creation 2010-04-17)
151 private final class ParticleIterator implements Iterator<Particle> {
153 private final ParticleDefaultImplementation iterationParticle;
155 private final Transform transform;
157 private final Vector3f linearVelocity;
159 private ListIterator<CollisionObject> collisionObjectIterator;
161 public ParticleIterator() {
162 this.iterationParticle = new ParticleDefaultImplementation(Particle.Type.values()[0], 0F, 0F, 0F, 0F);
163 this.transform = new Transform();
164 this.linearVelocity = new Vector3f();
167 public final void reset() {
168 this.collisionObjectIterator = ParticleEngineJBulletImplementation.this.getDynamicsWorld().getCollisionObjectArray().listIterator();
171 @Override
172 public final boolean hasNext() {
173 this.ignoreNonparticles();
175 return this.collisionObjectIterator.hasNext();
178 @Override
179 public final Particle next() {
180 this.ignoreNonparticles();
182 final RigidBody particle = (RigidBody) this.collisionObjectIterator.next();
183 final Type type = (Type) particle.getUserPointer();
185 particle.getWorldTransform(this.transform);
186 particle.getLinearVelocity(this.linearVelocity);
188 this.iterationParticle.setType(type);
189 this.iterationParticle.setX(this.transform.origin.x);
190 this.iterationParticle.setY(this.transform.origin.y);
191 this.iterationParticle.setSpeedX(this.linearVelocity.x);
192 this.iterationParticle.setSpeedY(this.linearVelocity.y);
194 return this.iterationParticle;
197 @Override
198 public final void remove() {
199 throw new UnsupportedOperationException("Not supported");
202 private final void ignoreNonparticles() {
203 CollisionObject collisionObject = null;
205 while (this.collisionObjectIterator.hasNext() && !((collisionObject = this.collisionObjectIterator.next()).getUserPointer() instanceof Type)) {
206 // Nothing
209 if (collisionObject != null && collisionObject.getUserPointer() instanceof Type) {
210 this.collisionObjectIterator.previous();
218 * @return
219 * <br>A new value
220 * <br>A non-null value
222 private static final DynamicsWorld createDynamicsWorld() {
223 final DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
224 final CollisionDispatcher collisionDispatcher = new CollisionDispatcher(collisionConfiguration);
225 final Float size = 10000F;
226 final BroadphaseInterface overlappingPairCache = new AxisSweep3(new Vector3f(-size, -size, -size), new Vector3f(size, size, size));
227 final ConstraintSolver solver = new SequentialImpulseConstraintSolver();
228 final DynamicsWorld result = new DiscreteDynamicsWorld(collisionDispatcher, overlappingPairCache, solver, collisionConfiguration);
230 result.setGravity(new Vector3f(0F, -10F, 0F));
232 return result;
237 * @param planeNormal
238 * <br>Shoudl not be null
239 * @param planeC
240 * <br>Should not be null
241 * @return
242 * <br>A new value
243 * <br>A non-null value
245 private static final RigidBody createPlane(final Vector3f planeNormal, final Float planeC) {
246 final Float mass = 0F;
247 final DefaultMotionState motionState = new DefaultMotionState(createIdentityTransform());
248 final CollisionShape collisionShape = new StaticPlaneShape(planeNormal, planeC);
249 final RigidBodyConstructionInfo constructionInfo = new RigidBodyConstructionInfo(mass, motionState, collisionShape);
251 return new RigidBody(constructionInfo);
256 * @param mass
257 * <br>Range: <code>[0 .. Float.POSITIVE_INFINITY]</code>
258 * @param radius
259 * <br>Range: <code>[0 .. Float.POSITIVE_INFINITY[</code>
260 * @param origin
261 * <br>Should not be null
262 * @return
263 * <br>A new value
264 * <br>A non-null value
266 private static final RigidBody createSphere(final float mass, final Float radius, final Vector3f origin) {
267 final CollisionShape collisionShape = new SphereShape(radius);
268 final Transform transform = createIdentityTransform();
269 final float jbulletMass = (mass == Float.POSITIVE_INFINITY ? 0F : mass);
271 if (jbulletMass != 0F) {
272 collisionShape.calculateLocalInertia(mass, new Vector3f());
275 transform.origin.set(origin);
277 final DefaultMotionState motionState = new DefaultMotionState(transform);
278 final RigidBodyConstructionInfo constructionInfo = new RigidBodyConstructionInfo(mass, motionState, collisionShape);
280 return new RigidBody(constructionInfo);
285 * @return
286 * <br>A new value
287 * <br>A non-null value
289 private static final Transform createIdentityTransform() {
290 final Transform result = new Transform();
292 result.setIdentity();
294 return result;