/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package automenta.spacenet.space.geom.physics; import automenta.spacenet.space.Repeat; import automenta.spacenet.space.Space; import automenta.spacenet.space.geom.Box; import automenta.spacenet.space.geom.Box.BoxShape; import automenta.spacenet.var.vector.V3; import com.ardor3d.math.Ray3; import com.ardor3d.scenegraph.Spatial; import com.bulletphysics.BulletStats; import com.bulletphysics.collision.dispatch.CollisionObject; import com.bulletphysics.collision.dispatch.CollisionWorld; import com.bulletphysics.collision.dispatch.CollisionWorld.ClosestRayResultCallback; import com.bulletphysics.dynamics.DynamicsWorld; import com.bulletphysics.dynamics.RigidBody; import com.bulletphysics.dynamics.constraintsolver.Point2PointConstraint; import com.bulletphysics.dynamics.constraintsolver.TypedConstraint; import com.bulletphysics.linearmath.Transform; import javax.vecmath.Vector3f; /** * wraps a PhySpace as a Box that can be added in space */ public class PhySpaceBox extends Box { public final PhySpace physics; public class PhyPointer extends Repeat { private Point2PointConstraint pickConstraint; private final PhySpace phySpace; private final DynamicsWorld dynamicsWorld; // private final PhyBox b2; private Vector3f pickPos; float pickDist = 370.0f; //for some reason, the larger the more accurate the pick response private Space pickedSpace; private ClosestRayResultCallback rayCallback; private RigidBody draggedBody; public PhyPointer(PhySpace sp) { super(); this.phySpace = sp; this.dynamicsWorld = sp.dynamicsWorld; // b2 = PhySpaceBox.this.add(new PhyBox(new V3(0, 0, 0), new V3(0.1, 0.1, 0.1), 1f)); } RigidBody pickedBody; Vector3f cameraPosition = new Vector3f(); Vector3f rayTo = new Vector3f(); Vector3f rayEnd = new Vector3f(); Vector3f dir = new Vector3f(); int lastState = -1; public void mouseFunc(int button, int state) { //printf("button %i, state %i, x=%i,y=%i\n",button,state,x,y); //button 0, state 0 means left mouse down /*if (lastState != state)*/ { switch (button) { // case 2: { // if (state == 0) { // shootBox(rayTo); // } // break; // } // case 1: { // if (state == 0) { // // apply an impulse // if (dynamicsWorld != null) { // CollisionWorld.ClosestRayResultCallback rayCallback = new CollisionWorld.ClosestRayResultCallback(cameraPosition, rayTo); // dynamicsWorld.rayTest(cameraPosition, rayTo, rayCallback); // if (rayCallback.hasHit()) { // RigidBody body = RigidBody.upcast(rayCallback.collisionObject); // if (body != null) { // body.setActivationState(CollisionObject.ACTIVE_TAG); // Vector3f impulse = new Vector3f(rayTo); // impulse.normalize(); // float impulseStrength = 10f; // impulse.scale(impulseStrength); // Vector3f relPos = new Vector3f(); // relPos.sub(rayCallback.hitPointWorld, body.getCenterOfMassPosition(new Vector3f())); // body.applyImpulse(impulse, relPos); // } // } // } // } else { // } // break; // } case 0: { if (state == 0) { if ((pickedBody != null) && (draggedBody == null)) { draggedBody = pickedBody; draggedBody.setActivationState(CollisionObject.DISABLE_DEACTIVATION); pickPos.set(rayCallback.hitPointWorld); Transform tmpTrans = pickedBody.getCenterOfMassTransform(new Transform()); tmpTrans.inverse(); Vector3f localPivot = new Vector3f(pickPos); tmpTrans.transform(localPivot); Point2PointConstraint p2p = new Point2PointConstraint(draggedBody, localPivot); dynamicsWorld.addConstraint(p2p); pickConstraint = p2p; // save mouse position for dragging BulletStats.gOldPickingPos.set(rayTo); Vector3f eyePos = new Vector3f(cameraPosition); Vector3f tmp = new Vector3f(); tmp.sub(pickPos, eyePos); BulletStats.gOldPickingDist = tmp.length(); // very weak constraint for picking p2p.setting.tau = 0.1f; } } else { if (pickConstraint != null && dynamicsWorld != null && draggedBody != null) { dynamicsWorld.removeConstraint(pickConstraint); // delete m_pickConstraint; //printf("removed constraint %i",gPickingConstraintId); pickConstraint = null; draggedBody.forceActivationState(CollisionObject.ACTIVE_TAG); draggedBody.setDeactivationTime(0f); //System.out.println("detach " + draggedBody); draggedBody = null; } } break; } } lastState = state; } if (pickConstraint != null) { // move the constraint pivot Point2PointConstraint p2p = (Point2PointConstraint) pickConstraint; if (p2p != null) { // keep it at the same picking distance dir.set(rayTo); dir.sub(cameraPosition); dir.normalize(); dir.scale(BulletStats.gOldPickingDist); Vector3f newPos = new Vector3f(cameraPosition); newPos.add(newPos, dir); p2p.setPivotB(newPos); } } } @Override protected void update(double t, double dt, Spatial parent) { if (dynamicsWorld != null) { V3 center = getSpacetime().getCamera().getCurrentPosition(); Ray3 pickRay = getSpacetime().getPointer().getPickRay(); cameraPosition.set(center.getXf(), center.getYf(), center.getZf()); rayTo.set(pickRay.getDirection().getXf(), pickRay.getDirection().getYf(), pickRay.getDirection().getZf()); //rayEnd.set(rayTo); rayTo.scale(pickDist); // b2.getPosition().set(getSpacetime().getCamera().getCurrentPosition()); // b2.getPosition().addLocal(pickRay.getDirection()); // b2.getPosition().addLocal(pickRay.getDirection()); // b2.setVelocity(0, 0, 0); // rayCallback = new CollisionWorld.ClosestRayResultCallback(cameraPosition, rayTo); dynamicsWorld.rayTest(cameraPosition, rayTo, rayCallback); pickedBody = null; if (rayCallback.hasHit()) { RigidBody body = RigidBody.upcast(rayCallback.collisionObject); if (body != null) { // other exclusions? if (!(body.isStaticObject() || body.isKinematicObject())) { pickedBody = body; //pickedBody.setActivationState(CollisionObject.DISABLE_DEACTIVATION); pickedSpace = physics.getSpace(pickedBody); pickPos = new Vector3f(rayCallback.hitPointWorld); } } } } mouseFunc(0, getSpacetime().getPointer().isPressed(0) ? 0 : 1); } } public PhySpaceBox(double worldDimension) { this(worldDimension, worldDimension, worldDimension); } public PhySpaceBox(double wx, double wy, double wz) { super(BoxShape.Empty); this.physics = add(new PhySpace(wx, wy, wz)); add(new PhyPointer(physics)); } @Deprecated public PhySpaceBox() { this(100.0); } public TypedConstraint addConstraint(TypedConstraint j, boolean collisionsBetweenBodies) { physics.dynamicsWorld.addConstraint(j, collisionsBetweenBodies); return j; } public PhyBox add(PhyBox pb) { physics.add(pb); return super.add(pb); } }