@ -85,8 +85,16 @@ public final class Bone implements Savable {
private Vector3f worldPos = new Vector3f ( ) ;
private Quaternion worldRot = new Quaternion ( ) ;
private Vector3f worldScale = new Vector3f ( ) ;
//used for getCombinedTransform
// Used for getCombinedTransform
private Transform tmpTransform = new Transform ( ) ;
/ * *
* Used to handle blending from one animation to another .
* See { @link # blendAnimTransforms ( com . jme3 . math . Vector3f , com . jme3 . math . Quaternion , com . jme3 . math . Vector3f , float ) }
* on how this variable is used .
* /
private transient float currentWeightSum = - 1 ;
/ * *
* Creates a new bone with the given name .
@ -323,6 +331,25 @@ public final class Bone implements Savable {
* world transform with this bones ' local transform .
* /
public final void updateWorldVectors ( ) {
if ( currentWeightSum = = 1f ) {
currentWeightSum = - 1 ;
} else if ( currentWeightSum ! = - 1f ) {
// Apply the weight to the local transform
if ( currentWeightSum = = 0 ) {
localRot . set ( initialRot ) ;
localPos . set ( initialPos ) ;
localScale . set ( initialScale ) ;
} else {
float invWeightSum = 1f - currentWeightSum ;
localRot . nlerp ( initialRot , invWeightSum ) ;
localPos . interpolate ( initialPos , invWeightSum ) ;
localScale . interpolate ( initialScale , invWeightSum ) ;
}
// Future invocations of transform blend will start over.
currentWeightSum = - 1 ;
}
if ( parent ! = null ) {
//rotation
parent . worldRot . mult ( localRot , worldRot ) ;
@ -522,34 +549,70 @@ public final class Bone implements Savable {
}
}
/ * *
* Blends the given animation transform onto the bone ' s local transform .
* < p >
* Subsequent calls of this method stack up , with the final transformation
* of the bone computed at { @link # updateWorldVectors ( ) } which resets
* the stack .
* < p >
* E . g . a single transform blend with weight = 0 . 5 followed by an
* updateWorldVectors ( ) call will result in final transform = transform * 0 . 5 .
* Two transform blends with weight = 0 . 5 each will result in the two
* transforms blended together ( nlerp ) with blend = 0 . 5 .
*
* @param translation The translation to blend in
* @param rotation The rotation to blend in
* @param scale The scale to blend in
* @param weight The weight of the transform to apply . Set to 1 . 0 to prevent
* any other transform from being applied until updateWorldVectors ( ) .
* /
void blendAnimTransforms ( Vector3f translation , Quaternion rotation , Vector3f scale , float weight ) {
if ( userControl ) {
return ;
}
TempVars vars = TempVars . get ( ) ;
// assert vars.lock();
Vector3f tmpV = vars . vect1 ;
Vector3f tmpV2 = vars . vect2 ;
Quaternion tmpQ = vars . quat1 ;
//location
tmpV . set ( initialPos ) . addLocal ( translation ) ;
localPos . interpolate ( tmpV , weight ) ;
//rotation
tmpQ . set ( initialRot ) . multLocal ( rotation ) ;
localRot . nlerp ( tmpQ , weight ) ;
//scale
if ( scale ! = null ) {
tmpV2 . set ( initialScale ) . multLocal ( scale ) ;
localScale . interpolate ( tmpV2 , weight ) ;
if ( weight = = 0 ) {
// Do not apply this transform at all.
return ;
}
vars . release ( ) ;
if ( currentWeightSum = = 1 ) {
return ; // More than 2 transforms are being blended
} else if ( currentWeightSum = = - 1 | | currentWeightSum = = 0 ) {
// Set the transform fully
localPos . set ( initialPos ) . addLocal ( translation ) ;
localRot . set ( initialRot ) . multLocal ( rotation ) ;
if ( scale ! = null ) {
localScale . set ( initialScale ) . multLocal ( scale ) ;
}
// Set the weight. It will be applied in updateWorldVectors().
currentWeightSum = weight ;
} else {
// The weight is already set.
// Blend in the new transform.
TempVars vars = TempVars . get ( ) ;
Vector3f tmpV = vars . vect1 ;
Vector3f tmpV2 = vars . vect2 ;
Quaternion tmpQ = vars . quat1 ;
tmpV . set ( initialPos ) . addLocal ( translation ) ;
localPos . interpolate ( tmpV , weight ) ;
tmpQ . set ( initialRot ) . multLocal ( rotation ) ;
localRot . nlerp ( tmpQ , weight ) ;
if ( scale ! = null ) {
tmpV2 . set ( initialScale ) . multLocal ( scale ) ;
localScale . interpolate ( tmpV2 , weight ) ;
}
// Ensures no new weights will be blended in the future.
currentWeightSum = 1 ;
vars . release ( ) ;
}
}
/ * *