@ -1,6 +1,7 @@
package com.jme3.scene.plugins.blender.constraints ;
import java.util.Arrays ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
import com.jme3.animation.Animation ;
@ -10,14 +11,15 @@ import com.jme3.animation.Track;
import com.jme3.math.Quaternion ;
import com.jme3.math.Transform ;
import com.jme3.math.Vector3f ;
import com.jme3.scene.Spatial ;
import com.jme3.scene.plugins.blender.BlenderContext ;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType ;
import com.jme3.scene.plugins.blender.animations.ArmatureHelper ;
import com.jme3.scene.plugins.blender.animations.BoneContext ;
import com.jme3.scene.plugins.blender.animations.Ipo ;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space ;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException ;
import com.jme3.scene.plugins.blender.file.Structure ;
import com.jme3.scene.plugins.blender.objects.ObjectHelper ;
import com.jme3.scene.plugins.ogre.AnimData ;
/ * *
@ -26,52 +28,97 @@ import com.jme3.scene.plugins.ogre.AnimData;
* /
/*package*/ class BoneConstraint extends Constraint {
private static final Logger LOGGER = Logger . getLogger ( BoneConstraint . class . getName ( ) ) ;
/** The OMA of the target armature. */
protected Long targetArmatureOMA ;
protected boolean isNodeTarget ;
/ * *
* The bone constraint constructor .
*
* @param constraintStructure
* the constraint ' s structure
* @param ownerOMA
* the OMA of the bone that owns the constraint
* @param influenceIpo
* the influence interpolation curve
* @param blenderContext
* the blender context
* @throws BlenderFileException
* exception thrown when problems with blender file occur
* /
public BoneConstraint ( Structure constraintStructure , Long ownerOMA , Ipo influenceIpo , BlenderContext blenderContext )
throws BlenderFileException {
super ( constraintStructure , ownerOMA , influenceIpo , blenderContext ) ;
targetArmatureOMA = targetOMA ;
if ( targetArmatureOMA ! = null & & targetArmatureOMA < = 0L ) {
targetArmatureOMA = null ;
}
targetOMA = null ;
if ( targetArmatureOMA ! = null & & targetArmatureOMA > 0L & & ( subtargetName = = null | | subtargetName . length ( ) = = 0 ) ) {
invalid = true ;
}
}
@Override
public void performBakingOperation ( ) {
Bone owner = blenderContext . getBoneContext ( ownerOMA ) . getBone ( ) ;
Bone target = null ;
if ( targetArmatureOMA ! = null ) { //first make sure the target is loaded
ObjectHelper objectHelper = blenderContext . getHelper ( ObjectHelper . class ) ;
try {
objectHelper . toObject ( ( Structure ) blenderContext . getLoadedFeature ( targetArmatureOMA , LoadedFeatureDataType . LOADED_STRUCTURE ) , blenderContext ) ;
} catch ( BlenderFileException e ) {
LOGGER . warning ( "Problems occured during target object loading. The constraint " + name + " will not be applied." ) ;
return ;
protected boolean validate ( ) {
if ( targetOMA ! = null ) {
Spatial nodeTarget = ( Spatial ) blenderContext . getLoadedFeature ( targetOMA , LoadedFeatureDataType . LOADED_FEATURE ) ;
//the second part of the if expression verifies if the found node (if any) is an armature node
if ( nodeTarget = = null | | nodeTarget . getUserData ( ArmatureHelper . ARMETURE_NODE_MARKER ) ! = null ) {
//if the target is not an object node then it is an Armature, so make sure the bone is in the current skeleton
BoneContext boneContext = blenderContext . getBoneContext ( ownerOMA ) ;
if ( targetOMA . longValue ( ) ! = boneContext . getArmatureObjectOMA ( ) . longValue ( ) ) {
LOGGER . log ( Level . WARNING , "Bone constraint {0} must target bone in the its own skeleton! Targeting bone in another skeleton is not supported!" , name ) ;
return false ;
}
} else {
isNodeTarget = true ;
}
BoneContext boneContext = blenderContext . getBoneByName ( subtargetName ) ;
target = boneContext . getBone ( ) ;
this . targetOMA = boneContext . getBoneOma ( ) ;
}
this . prepareTracksForApplyingConstraints ( ) ;
AnimData animData = blenderContext . getAnimData ( ownerOMA ) ;
if ( animData ! = null ) {
for ( Animation animation : animData . anims ) {
Transform ownerTransform = constraintHelper . getBoneTransform ( ownerSpace , owner ) ;
Transform targetTransform = target ! = null ? constraintHelper . getBoneTransform ( targetSpace , target ) : null ;
BoneTrack boneTrack = constraintHelper . getTrack ( owner , animData . skeleton , animation ) ;
BoneTrack targetTrack = target ! = null ? constraintHelper . getTrack ( target , animData . skeleton , animation ) : null ;
return true ;
}
@Override
public void performBakingOperation ( ) {
Bone owner = blenderContext . getBoneContext ( ownerOMA ) . getBone ( ) ;
if ( targetOMA ! = null ) {
if ( isNodeTarget ) {
Spatial target = ( Spatial ) blenderContext . getLoadedFeature ( targetOMA , LoadedFeatureDataType . LOADED_FEATURE ) ;
this . prepareTracksForApplyingConstraints ( ) ;
AnimData animData = blenderContext . getAnimData ( ownerOMA ) ;
if ( animData ! = null ) {
for ( Animation animation : animData . anims ) {
Transform ownerTransform = constraintHelper . getBoneTransform ( ownerSpace , owner ) ;
Transform targetTransform = constraintHelper . getNodeObjectTransform ( targetSpace , targetOMA , blenderContext ) ;
Track boneTrack = constraintHelper . getTrack ( owner , animData . skeleton , animation ) ;
Track targetTrack = constraintHelper . getTrack ( target , animation ) ;
constraintDefinition . bake ( ownerTransform , targetTransform , boneTrack , targetTrack , this . ipo ) ;
}
}
} else {
BoneContext boneContext = blenderContext . getBoneByName ( subtargetName ) ;
Bone target = boneContext . getBone ( ) ;
this . targetOMA = boneContext . getBoneOma ( ) ;
constraintDefinition . bake ( ownerTransform , targetTransform , boneTrack , targetTrack , this . ipo ) ;
this . prepareTracksForApplyingConstraints ( ) ;
AnimData animData = blenderContext . getAnimData ( ownerOMA ) ;
if ( animData ! = null ) {
for ( Animation animation : animData . anims ) {
Transform ownerTransform = constraintHelper . getBoneTransform ( ownerSpace , owner ) ;
Transform targetTransform = constraintHelper . getBoneTransform ( targetSpace , target ) ;
Track boneTrack = constraintHelper . getTrack ( owner , animData . skeleton , animation ) ;
Track targetTrack = constraintHelper . getTrack ( target , animData . skeleton , animation ) ;
constraintDefinition . bake ( ownerTransform , targetTransform , boneTrack , targetTrack , this . ipo ) ;
}
}
}
} else {
this . prepareTracksForApplyingConstraints ( ) ;
AnimData animData = blenderContext . getAnimData ( ownerOMA ) ;
if ( animData ! = null ) {
for ( Animation animation : animData . anims ) {
Transform ownerTransform = constraintHelper . getBoneTransform ( ownerSpace , owner ) ;
Track boneTrack = constraintHelper . getTrack ( owner , animData . skeleton , animation ) ;
constraintDefinition . bake ( ownerTransform , null , boneTrack , null , this . ipo ) ;
}
}
}
}
@ -112,21 +159,25 @@ import com.jme3.scene.plugins.ogre.AnimData;
/ * *
* The method determines if the bone has animations .
*
* @param bone OMA
* OMA of the bone
* @return < b > true < / b > if the bone has animations and < b > false < / b > otherwise
* @param animOwner OMA
* OMA of the animation ' s owner
* @return < b > true < / b > if the target has animations and < b > false < / b > otherwise
* /
protected boolean hasAnimation ( Long bone OMA) {
AnimData animData = blenderContext . getAnimData ( bone OMA) ;
protected boolean hasAnimation ( Long animOwner OMA) {
AnimData animData = blenderContext . getAnimData ( animOwner OMA) ;
if ( animData ! = null ) {
Bone bone = blenderContext . getBoneContext ( boneOMA ) . getBone ( ) ;
int boneIndex = animData . skeleton . getBoneIndex ( bone ) ;
for ( Animation animation : animData . anims ) {
for ( Track track : animation . getTracks ( ) ) {
if ( track instanceof BoneTrack & & ( ( BoneTrack ) track ) . getTargetBoneIndex ( ) = = boneIndex ) {
return true ;
if ( ! isNodeTarget ) {
Bone bone = blenderContext . getBoneContext ( animOwnerOMA ) . getBone ( ) ;
int boneIndex = animData . skeleton . getBoneIndex ( bone ) ;
for ( Animation animation : animData . anims ) {
for ( Track track : animation . getTracks ( ) ) {
if ( track instanceof BoneTrack & & ( ( BoneTrack ) track ) . getTargetBoneIndex ( ) = = boneIndex ) {
return true ;
}
}
}
} else {
return true ;
}
}
return false ;