package net.physx4java.dynamics.joints;
import javax.vecmath.Vector3f;
import net.physx4java.WorldPhysX;
import net.physx4java.dynamics.actors.Actor;
import net.physx4java.dynamics.actors.ActorParameters;
import net.physx4java.dynamics.actors.SphereActor;
import net.physx4java.dynamics.collision.CollisionDisabler;
/**
* NOTE this is not a true PhysxJoint. It emulates the two hinged universal joint as seen in ODE. Since PhysX does not support
* that out of the box and I needed it for my projects, I've found this rather clumsy solution: Joining two Revolute joints
* using a "helper actor". Remember that the size (the shape of that actor will be a rect) and mass of helper-actor must be specified
* and tweaked according to your application.
* TODO the right way to implement this is probably through a D6Joint. But I haven't figure out how to do that yet. If anyone knows
* how to do that, you're welcome to give it a try.
*
*/
public class UniversalJoint extends Joint {
RevoluteJoint jointHinge1;
RevoluteJoint jointHinge2;
Actor helperActor;
public Actor getHelperActor() {
return helperActor;
}
@Override
public int getNumberOfAxis() {
// TODO Auto-generated method stub
return 2;
}
@Override
public float getRotation(int axisNumber) {
// TODO Auto-generated method stub
return getAngle(axisNumber);
}
public float getAngle(int axis) {
if (axis == 0) {
return jointHinge1.getAngle();
} else if (axis == 1) {
return jointHinge2.getAngle();
} else {
return 0;
}
}
public void setDesiredSpeed(int axis, float speed, float power) {
if (axis == 0) {
jointHinge1.setMotor(speed, power, false);
} else
jointHinge2.setMotor(speed, power, false);
}
public void enableMotor() {
jointHinge1.enableMotor();
jointHinge2.enableMotor();
}
public UniversalJoint(WorldPhysX world, String name, float helperActorSize, float helperActorMass, float helperActorDensity, Vector3f axis1, Vector3f axis2, Actor actor1, Actor actor2, Vector3f anchor, float lostop, float histop, float lostop2, float histop2) {
super(null);
this.name = name;
this.actor1 = actor1;
this.actor2 = actor2;
// helperActor
ActorParameters actorParameters = new ActorParameters();
actorParameters.setDensity(helperActorDensity);
helperActor = new SphereActor(actorParameters, world, helperActorSize, 0);
CollisionDisabler.disableCollision(world, helperActor);
helperActor.setName(name + "helperActor");
helperActor.setRotation(actor1.getRotation());
helperActor.setPosition(anchor);
helperActor.setMass(helperActorMass);
helperActor.update();
world.addActor(helperActor);
// joint 1
RevoluteJointDesc r1 = new RevoluteJointDesc();
jointDesc = r1;
r1.setActors(actor1, helperActor);
r1.setGlobalAnchor(anchor);
r1.setGlobalAxis(axis1);
axis[0] = axis1;
jointHinge1 = new RevoluteJoint(name + "_0", r1, world);
System.out.println("LIMIT ="+lostop+" "+histop);
jointHinge1.setLimit(1, 1, lostop, 1, 1, histop);
// joint 2
//System.out.println("SKODKAJKAGE2");
RevoluteJointDesc r2 = new RevoluteJointDesc();
r2.setActors(helperActor, actor2);
r2.setGlobalAnchor(anchor);
r2.setGlobalAxis(axis2);
axis[1] = axis2;
jointHinge2 = new RevoluteJoint(name + "_0", r2, world);
jointHinge2.setLimit(1, 1, lostop2, 1, 1, histop2);
}
public void setSpringTarget(int axis, float spring, float damper, float targetValue) {
if (axis == 0) {
jointHinge1.setSpring(spring, damper, targetValue);
} else {
jointHinge2.setSpring(spring, damper, targetValue);
}
}
}