use of com.jme3.math.Quaternion in project jmonkeyengine by jMonkeyEngine.
the class RagdollUtils method setTransform.
/**
* Updates a bone position and rotation.
* if the child bones are not in the bone list this means, they are not associated with a physic shape.
* So they have to be updated
* @param bone the bone
* @param pos the position
* @param rot the rotation
*/
public static void setTransform(Bone bone, Vector3f pos, Quaternion rot, boolean restoreBoneControl, Set<String> boneList) {
//we ensure that we have the control
if (restoreBoneControl) {
bone.setUserControl(true);
}
//we set te user transforms of the bone
bone.setUserTransformsInModelSpace(pos, rot);
for (Bone childBone : bone.getChildren()) {
//each child bone that is not in the list is updated
if (!boneList.contains(childBone.getName())) {
Transform t = childBone.getCombinedTransform(pos, rot);
setTransform(childBone, t.getTranslation(), t.getRotation(), restoreBoneControl, boneList);
}
}
//we give back the control to the keyframed animation
if (restoreBoneControl) {
bone.setUserControl(false);
}
}
use of com.jme3.math.Quaternion in project jmonkeyengine by jMonkeyEngine.
the class CharacterControl method update.
public void update(float tpf) {
if (enabled && spatial != null) {
Quaternion localRotationQuat = spatial.getLocalRotation();
Vector3f localLocation = spatial.getLocalTranslation();
if (!applyLocal && spatial.getParent() != null) {
getPhysicsLocation(localLocation);
localLocation.subtractLocal(spatial.getParent().getWorldTranslation());
localLocation.divideLocal(spatial.getParent().getWorldScale());
tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation);
spatial.setLocalTranslation(localLocation);
if (useViewDirection) {
localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y);
spatial.setLocalRotation(localRotationQuat);
}
} else {
spatial.setLocalTranslation(getPhysicsLocation());
localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y);
spatial.setLocalRotation(localRotationQuat);
}
}
}
use of com.jme3.math.Quaternion in project jmonkeyengine by jMonkeyEngine.
the class KinematicRagdollControl method ragDollUpdate.
protected void ragDollUpdate(float tpf) {
TempVars vars = TempVars.get();
Quaternion tmpRot1 = vars.quat1;
Quaternion tmpRot2 = vars.quat2;
for (PhysicsBoneLink link : boneLinks.values()) {
Vector3f position = vars.vect1;
//retrieving bone position in physic world space
Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
//transforming this position with inverse transforms of the model
targetModel.getWorldTransform().transformInverseVector(p, position);
//retrieving bone rotation in physic world space
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
//multiplying this rotation by the initialWorld rotation of the bone,
//then transforming it with the inverse world rotation of the model
tmpRot1.set(q).multLocal(link.initalWorldRotation);
tmpRot2.set(targetModel.getWorldRotation()).inverseLocal().mult(tmpRot1, tmpRot1);
tmpRot1.normalizeLocal();
//if the bone is the root bone, we apply the physic's transform to the model, so its position and rotation are correctly updated
if (link.bone.getParent() == null) {
//offsetting the physic's position/rotation by the root bone inverse model space position/rotaion
modelPosition.set(p).subtractLocal(link.bone.getBindPosition());
targetModel.getParent().getWorldTransform().transformInverseVector(modelPosition, modelPosition);
modelRotation.set(q).multLocal(tmpRot2.set(link.bone.getBindRotation()).inverseLocal());
//applying transforms to the model
targetModel.setLocalTranslation(modelPosition);
targetModel.setLocalRotation(modelRotation);
//Applying computed transforms to the bone
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
} else {
//so we just update the bone position
if (boneList.isEmpty()) {
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
} else {
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
//So we update them recusively
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
}
}
}
vars.release();
}
use of com.jme3.math.Quaternion in project jmonkeyengine by jMonkeyEngine.
the class KinematicRagdollControl method createSpatialData.
@Override
protected void createSpatialData(Spatial model) {
targetModel = model;
Node parent = model.getParent();
Vector3f initPosition = model.getLocalTranslation().clone();
Quaternion initRotation = model.getLocalRotation().clone();
initScale = model.getLocalScale().clone();
model.removeFromParent();
model.setLocalTranslation(Vector3f.ZERO);
model.setLocalRotation(Quaternion.IDENTITY);
model.setLocalScale(1);
//HACK ALERT change this
//I remove the skeletonControl and readd it to the spatial to make sure it's after the ragdollControl in the stack
//Find a proper way to order the controls.
SkeletonControl sc = model.getControl(SkeletonControl.class);
if (sc == null) {
throw new IllegalArgumentException("The root node of the model should have a SkeletonControl. Make sure the control is there and that it's not on a sub node.");
}
model.removeControl(sc);
model.addControl(sc);
// put into bind pose and compute bone transforms in model space
// maybe dont reset to ragdoll out of animations?
scanSpatial(model);
if (parent != null) {
parent.attachChild(model);
}
model.setLocalTranslation(initPosition);
model.setLocalRotation(initRotation);
model.setLocalScale(initScale);
if (added) {
addPhysics(space);
}
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
}
use of com.jme3.math.Quaternion in project jmonkeyengine by jMonkeyEngine.
the class KinematicRagdollControl method updateBone.
public void updateBone(PhysicsBoneLink link, float tpf, TempVars vars, Quaternion tmpRot1, Quaternion[] tmpRot2, Bone tipBone, Vector3f target, int depth, int maxDepth) {
if (link == null || link.bone.getParent() == null) {
return;
}
Quaternion preQuat = link.bone.getLocalRotation();
Vector3f vectorAxis;
float[] measureDist = new float[] { Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY };
for (int dirIndex = 0; dirIndex < 3; dirIndex++) {
if (dirIndex == 0) {
vectorAxis = Vector3f.UNIT_Z;
} else if (dirIndex == 1) {
vectorAxis = Vector3f.UNIT_X;
} else {
vectorAxis = Vector3f.UNIT_Y;
}
for (int posOrNeg = 0; posOrNeg < 2; posOrNeg++) {
float rot = ikRotSpeed * tpf / (link.rigidBody.getMass() * 2);
rot = FastMath.clamp(rot, link.joint.getRotationalLimitMotor(dirIndex).getLoLimit(), link.joint.getRotationalLimitMotor(dirIndex).getHiLimit());
tmpRot1.fromAngleAxis(rot, vectorAxis);
// tmpRot1.fromAngleAxis(rotSpeed * tpf / (link.rigidBody.getMass() * 2), vectorAxis);
tmpRot2[posOrNeg] = link.bone.getLocalRotation().mult(tmpRot1);
tmpRot2[posOrNeg].normalizeLocal();
ikRotSpeed = -ikRotSpeed;
link.bone.setLocalRotation(tmpRot2[posOrNeg]);
link.bone.update();
measureDist[posOrNeg] = tipBone.getModelSpacePosition().distance(target);
link.bone.setLocalRotation(preQuat);
}
if (measureDist[0] < measureDist[1]) {
link.bone.setLocalRotation(tmpRot2[0]);
} else if (measureDist[0] > measureDist[1]) {
link.bone.setLocalRotation(tmpRot2[1]);
}
}
link.bone.getLocalRotation().normalizeLocal();
link.bone.update();
// link.usedbyIK = true;
if (link.bone.getParent() != null && depth < maxDepth) {
updateBone(boneLinks.get(link.bone.getParent().getName()), tpf * limbDampening, vars, tmpRot1, tmpRot2, tipBone, target, depth + 1, maxDepth);
}
}
Aggregations