Fix to Y-up axis issue when parent was present bu not loaded (in different layer for example). git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7913 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
f182b5d91b
commit
99746c72ec
@ -0,0 +1,129 @@ |
|||||||
|
package com.jme3.scene.plugins.blender.structures; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
import com.jme3.animation.Bone; |
||||||
|
import com.jme3.animation.BoneTrack; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
|
||||||
|
/** |
||||||
|
* The purpose of this class is to imitate bone's movement when calculating inverse kinematics. |
||||||
|
* @author Marcin Roguski |
||||||
|
*/ |
||||||
|
public class CalculationBone extends Node { |
||||||
|
private Bone bone; |
||||||
|
/** The bone's tracks. Will be altered at the end of calculation process. */ |
||||||
|
private BoneTrack track; |
||||||
|
/** The starting position of the bone. */ |
||||||
|
private Vector3f startTranslation; |
||||||
|
/** The starting rotation of the bone. */ |
||||||
|
private Quaternion startRotation; |
||||||
|
/** The starting scale of the bone. */ |
||||||
|
private Vector3f startScale; |
||||||
|
private Vector3f[] translations; |
||||||
|
private Quaternion[] rotations; |
||||||
|
private Vector3f[] scales; |
||||||
|
|
||||||
|
public CalculationBone(Bone bone, int boneFramesCount) { |
||||||
|
this.bone = bone; |
||||||
|
this.startRotation = bone.getModelSpaceRotation().clone(); |
||||||
|
this.startTranslation = bone.getModelSpacePosition().clone(); |
||||||
|
this.startScale = bone.getModelSpaceScale().clone(); |
||||||
|
this.reset(); |
||||||
|
if(boneFramesCount > 0) { |
||||||
|
this.translations = new Vector3f[boneFramesCount]; |
||||||
|
this.rotations = new Quaternion[boneFramesCount]; |
||||||
|
this.scales = new Vector3f[boneFramesCount]; |
||||||
|
|
||||||
|
Arrays.fill(this.translations, 0, boneFramesCount, this.startTranslation); |
||||||
|
Arrays.fill(this.rotations, 0, boneFramesCount, this.startRotation); |
||||||
|
Arrays.fill(this.scales, 0, boneFramesCount, this.startScale); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. Stores the track, starting transformation and sets the transformation to the starting positions. |
||||||
|
* @param bone |
||||||
|
* the bone this class will imitate |
||||||
|
* @param track |
||||||
|
* the bone's tracks |
||||||
|
*/ |
||||||
|
public CalculationBone(Bone bone, BoneTrack track) { |
||||||
|
this(bone, 0); |
||||||
|
this.track = track; |
||||||
|
this.translations = track.getTranslations(); |
||||||
|
this.rotations = track.getRotations(); |
||||||
|
this.scales = track.getScales(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getBoneFramesCount() { |
||||||
|
return this.translations==null ? 0 : this.translations.length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This method returns the end point of the bone. If the bone has parent it is calculated from the start point |
||||||
|
* of parent to the start point of this bone. If the bone doesn't have a parent the end location is considered |
||||||
|
* to be 1 point up along Y axis (scale is applied if set to != 1.0); |
||||||
|
* @return the end point of this bone |
||||||
|
*/ |
||||||
|
//TODO: set to Z axis if user defined it this way
|
||||||
|
public Vector3f getEndPoint() { |
||||||
|
if (this.getParent() == null) { |
||||||
|
return new Vector3f(0, this.getLocalScale().y, 0); |
||||||
|
} else { |
||||||
|
Node parent = this.getParent(); |
||||||
|
return parent.getWorldTranslation().subtract(this.getWorldTranslation()).multLocal(this.getWorldScale()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This method resets the calculation bone to the starting position. |
||||||
|
*/ |
||||||
|
public void reset() { |
||||||
|
this.setLocalTranslation(startTranslation); |
||||||
|
this.setLocalRotation(startRotation); |
||||||
|
this.setLocalScale(startScale); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int attachChild(Spatial child) { |
||||||
|
if (this.getChildren() != null && this.getChildren().size() > 1) { |
||||||
|
throw new IllegalStateException(this.getClass().getName() + " class instance can only have one child!"); |
||||||
|
} |
||||||
|
return super.attachChild(child); |
||||||
|
} |
||||||
|
|
||||||
|
public Spatial rotate(Quaternion rot, int frame) { |
||||||
|
Spatial spatial = super.rotate(rot); |
||||||
|
this.updateWorldTransforms(); |
||||||
|
if (this.getChildren() != null && this.getChildren().size() > 0) { |
||||||
|
CalculationBone child = (CalculationBone) this.getChild(0); |
||||||
|
child.updateWorldTransforms(); |
||||||
|
} |
||||||
|
rotations[frame].set(this.getLocalRotation()); |
||||||
|
translations[frame].set(this.getLocalTranslation()); |
||||||
|
if (scales != null) { |
||||||
|
scales[frame].set(this.getLocalScale()); |
||||||
|
} |
||||||
|
return spatial; |
||||||
|
} |
||||||
|
|
||||||
|
public void applyCalculatedTracks() { |
||||||
|
if(track != null) { |
||||||
|
track.setKeyframes(track.getTimes(), translations, rotations);//TODO:scales
|
||||||
|
} else { |
||||||
|
bone.setUserControl(true); |
||||||
|
bone.setUserTransforms(translations[0], rotations[0], scales[0]); |
||||||
|
bone.setUserControl(false); |
||||||
|
bone.updateWorldVectors(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return bone.getName() + ": " + this.getLocalRotation() + " " + this.getLocalTranslation(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue