Automatic loading of both bone and object animations (no need to specify animations in blender key any more).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8305 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent ce259299e2
commit 0b274b3c1b
  1. 127
      engine/src/blender/com/jme3/asset/BlenderKey.java
  2. 38
      engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java
  3. 120
      engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java
  4. 39
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  5. 72
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java

@ -33,12 +33,8 @@ package com.jme3.asset;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.Collidable;
@ -66,13 +62,6 @@ import com.jme3.texture.Texture;
public class BlenderKey extends ModelKey {
protected static final int DEFAULT_FPS = 25;
/**
* Animation definitions. The key is the object name that owns the animation. The value is a map between animation
* name and its start and stop frames. Blender stores a pointer for animation within object. Therefore one object
* can only have one animation at the time. We want to be able to switch between animations for one object so we
* need to map the object name to animation names the object will use.
*/
protected Map<String, Map<String, int[]>> animations;
/**
* FramesPerSecond parameter describe how many frames there are in each second. It allows to calculate the time
* between the frames.
@ -126,76 +115,6 @@ public class BlenderKey extends ModelKey {
super(name);
}
/**
* This method adds an animation definition. If a definition already eixists in the key then it is replaced.
* @param objectName
* the name of animation's owner
* @param name
* the name of the animation
* @param start
* the start frame of the animation
* @param stop
* the stop frame of the animation
*/
public synchronized void addAnimation(String objectName, String name, int start, int stop) {
if (objectName == null) {
throw new IllegalArgumentException("Object name cannot be null!");
}
if (name == null) {
throw new IllegalArgumentException("Animation name cannot be null!");
}
if (start > stop) {
throw new IllegalArgumentException("Start frame cannot be greater than stop frame!");
}
if (animations == null) {
animations = new HashMap<String, Map<String, int[]>>();
animations.put(objectName, new HashMap<String, int[]>());
}
Map<String, int[]> objectAnimations = animations.get(objectName);
if (objectAnimations == null) {
objectAnimations = new HashMap<String, int[]>();
animations.put(objectName, objectAnimations);
}
objectAnimations.put(name, new int[] { start, stop });
}
/**
* This method returns the animation frames boundaries.
* @param objectName
* the name of animation's owner
* @param name
* animation name
* @return animation frame boundaries in a table [start, stop] or null if animation of the given name does not
* exists
*/
public int[] getAnimationFrames(String objectName, String name) {
Map<String, int[]> objectAnimations = animations == null ? null : animations.get(objectName);
int[] frames = objectAnimations == null ? null : objectAnimations.get(name);
return frames == null ? null : frames.clone();
}
/**
* This method returns the animation names for the given object name.
* @param objectName
* the name of the object
* @return an array of animations for this object
*/
public Set<String> getAnimationNames(String objectName) {
Map<String, int[]> objectAnimations = animations == null ? null : animations.get(objectName);
return objectAnimations == null ? null : objectAnimations.keySet();
}
/**
* This method returns the animations map.
* The key is the animated spatial name. The value is a map where the key
* is the animation name and the value is 2-element array of int that has
* start and stop frame of the animation.
* @return the animations map
*/
public Map<String, Map<String, int[]>> getAnimations() {
return animations;
}
/**
* This method returns frames per second amount. The default value is BlenderKey.DEFAULT_FPS = 25.
* @return the frames per second amount
@ -424,22 +343,6 @@ public class BlenderKey extends ModelKey {
public void write(JmeExporter e) throws IOException {
super.write(e);
OutputCapsule oc = e.getCapsule(this);
// saving animations
oc.write(animations == null ? 0 : animations.size(), "anim-size", 0);
if (animations != null) {
int objectCounter = 0;
for (Entry<String, Map<String, int[]>> animEntry : animations.entrySet()) {
oc.write(animEntry.getKey(), "animated-object-" + objectCounter, null);
int animsAmount = animEntry.getValue().size();
oc.write(animsAmount, "anims-amount-" + objectCounter, 0);
for (Entry<String, int[]> animsEntry : animEntry.getValue().entrySet()) {
oc.write(animsEntry.getKey(), "anim-name-" + objectCounter, null);
oc.write(animsEntry.getValue(), "anim-frames-" + objectCounter, null);
}
++objectCounter;
}
}
// saving the rest of the data
oc.write(fps, "fps", DEFAULT_FPS);
oc.write(generatedTextureWidth, "generated-texture-width", 20);
oc.write(generatedTextureHeight, "generated-texture-height", 20);
@ -458,28 +361,6 @@ public class BlenderKey extends ModelKey {
public void read(JmeImporter e) throws IOException {
super.read(e);
InputCapsule ic = e.getCapsule(this);
// reading animations
int animSize = ic.readInt("anim-size", 0);
if (animSize > 0) {
if (animations == null) {
animations = new HashMap<String, Map<String, int[]>>(animSize);
} else {
animations.clear();
}
for (int i = 0; i < animSize; ++i) {
String objectName = ic.readString("animated-object-" + i, null);
int animationsAmount = ic.readInt("anims-amount-" + i, 0);
Map<String, int[]> objectAnimations = new HashMap<String, int[]>(animationsAmount);
for (int j = 0; j < animationsAmount; ++j) {
String animName = ic.readString("anim-name-" + i, null);
int[] animFrames = ic.readIntArray("anim-frames-" + i, null);
objectAnimations.put(animName, animFrames);
}
animations.put(objectName, objectAnimations);
}
}
// reading the rest of the data
fps = ic.readInt("fps", DEFAULT_FPS);
generatedTextureWidth = ic.readInt("generated-texture-width", 20);
generatedTextureHeight = ic.readInt("generated-texture-height", 20);
@ -498,7 +379,6 @@ public class BlenderKey extends ModelKey {
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (animations == null ? 0 : animations.hashCode());
result = prime * result + (assetRootPath == null ? 0 : assetRootPath.hashCode());
result = prime * result + (defaultMaterial == null ? 0 : defaultMaterial.hashCode());
result = prime * result + (faceCullMode == null ? 0 : faceCullMode.hashCode());
@ -526,13 +406,6 @@ public class BlenderKey extends ModelKey {
return false;
}
BlenderKey other = (BlenderKey) obj;
if (animations == null) {
if (other.animations != null) {
return false;
}
} else if (!animations.equals(other.animations)) {
return false;
}
if (assetRootPath == null) {
if (other.assetRootPath != null) {
return false;

@ -39,7 +39,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.Track;
import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
@ -320,20 +320,16 @@ public class ArmatureHelper extends AbstractBlenderHelper {
* the structure containing the tracks
* @param blenderContext
* the blender context
* @param objectName
* the name of the object that will use these tracks
* @param animationName
* the animation name
* @return a list of tracks for the specified animation
* @throws BlenderFileException
* an exception is thrown when there are problems with the blend
* file
*/
public BoneTrack[] getTracks(Structure actionStructure, BlenderContext blenderContext, String objectName, String animationName) throws BlenderFileException {
public Track<?>[] getTracks(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
if (blenderVersion < 250) {
return this.getTracks249(actionStructure, blenderContext, objectName, animationName);
return this.getTracks249(actionStructure, blenderContext);
} else {
return this.getTracks250(actionStructure, blenderContext, objectName, animationName);
return this.getTracks250(actionStructure, blenderContext);
}
}
@ -344,26 +340,21 @@ public class ArmatureHelper extends AbstractBlenderHelper {
* the structure containing the tracks
* @param blenderContext
* the blender context
* @param objectName
* the name of the object that will use these tracks
* @param animationName
* the animation name
* @return a list of tracks for the specified animation
* @throws BlenderFileException
* an exception is thrown when there are problems with the blend
* file
*/
private BoneTrack[] getTracks250(Structure actionStructure, BlenderContext blenderContext, String objectName, String animationName) throws BlenderFileException {
private Track<?>[] getTracks250(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
LOGGER.log(Level.INFO, "Getting tracks!");
int fps = blenderContext.getBlenderKey().getFps();
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, animationName);
Structure groups = (Structure) actionStructure.getFieldValue("groups");
List<Structure> actionGroups = groups.evaluateListBase(blenderContext);//bActionGroup
if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
}
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
List<Track<?>> tracks = new ArrayList<Track<?>>();
for (Structure actionGroup : actionGroups) {
String name = actionGroup.getFieldValue("name").toString();
Integer boneIndex = bonesMap.get(name);
@ -389,10 +380,10 @@ public class ArmatureHelper extends AbstractBlenderHelper {
}
Ipo ipo = new Ipo(bezierCurves);
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
tracks.add(ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps));
}
}
return tracks.toArray(new BoneTrack[tracks.size()]);
return tracks.toArray(new Track<?>[tracks.size()]);
}
/**
@ -402,26 +393,21 @@ public class ArmatureHelper extends AbstractBlenderHelper {
* the structure containing the tracks
* @param blenderContext
* the blender context
* @param objectName
* the name of the object that will use these tracks
* @param animationName
* the animation name
* @return a list of tracks for the specified animation
* @throws BlenderFileException
* an exception is thrown when there are problems with the blend
* file
*/
private BoneTrack[] getTracks249(Structure actionStructure, BlenderContext blenderContext, String objectName, String animationName) throws BlenderFileException {
private Track<?>[] getTracks249(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
LOGGER.log(Level.INFO, "Getting tracks!");
IpoHelper ipoHelper = blenderContext.getHelper(IpoHelper.class);
int fps = blenderContext.getBlenderKey().getFps();
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, animationName);
Structure chanbase = (Structure) actionStructure.getFieldValue("chanbase");
List<Structure> actionChannels = chanbase.evaluateListBase(blenderContext);//bActionChannel
if (actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
}
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
List<Track<?>> tracks = new ArrayList<Track<?>>();
for (Structure bActionChannel : actionChannels) {
String name = bActionChannel.getFieldValue("name").toString();
Integer boneIndex = bonesMap.get(name);
@ -430,11 +416,11 @@ public class ArmatureHelper extends AbstractBlenderHelper {
if (!p.isNull()) {
Structure ipoStructure = p.fetchData(blenderContext.getInputStream()).get(0);
Ipo ipo = ipoHelper.createIpo(ipoStructure, blenderContext);
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
tracks.add(ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps));
}
}
}
return tracks.toArray(new BoneTrack[tracks.size()]);
return tracks.toArray(new Track<?>[tracks.size()]);
}
/**

@ -1,6 +1,8 @@
package com.jme3.scene.plugins.blender.animations;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.SpatialTrack;
import com.jme3.animation.Track;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.curves.BezierCurve;
@ -28,7 +30,7 @@ public class Ipo {
/** A list of bezier curves for this interpolation object. */
private BezierCurve[] bezierCurves;
/** Each ipo contains one bone track. */
private BoneTrack calculatedTrack;
private Track<?> calculatedTrack;
/**
* Constructor. Stores the bezier curves.
@ -105,8 +107,9 @@ public class Ipo {
/**
* This method calculates the value of the curves as a bone track between the specified frames.
* @param boneIndex
* the index of the bone for which the method calculates the tracks
* @param targetIndex
* the index of the target for which the method calculates the tracks
* IMPORTANT! Aet to -1 (or any negative number) if you want to load spatial animation.
* @param startFrame
* the firs frame of tracks (inclusive)
* @param stopFrame
@ -115,63 +118,68 @@ public class Ipo {
* frame rate (frames per second)
* @return bone track for the specified bone
*/
public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps) {
//preparing data for track
int framesAmount = stopFrame - startFrame;
float start = (startFrame - 1.0f) / fps;
float timeBetweenFrames = 1.0f / fps;
public Track<?> calculateTrack(int targetIndex, int startFrame, int stopFrame, int fps) {
if(calculatedTrack == null) {
//preparing data for track
int framesAmount = stopFrame - startFrame;
float start = (startFrame - 1.0f) / fps;
float timeBetweenFrames = 1.0f / fps;
float[] times = new float[framesAmount + 1];
Vector3f[] translations = new Vector3f[framesAmount + 1];
float[] translation = new float[3];
Quaternion[] rotations = new Quaternion[framesAmount + 1];
float[] quaternionRotation = new float[4];
float[] objectRotation = new float[3];
boolean bObjectRotation = false;
Vector3f[] scales = new Vector3f[framesAmount + 1];
float[] scale = new float[3];
float[] times = new float[framesAmount + 1];
Vector3f[] translations = new Vector3f[framesAmount + 1];
float[] translation = new float[3];
Quaternion[] rotations = new Quaternion[framesAmount + 1];
float[] quaternionRotation = new float[4];
float[] objectRotation = new float[3];
boolean bSpatialTrack = targetIndex < 0;
Vector3f[] scales = new Vector3f[framesAmount + 1];
float[] scale = new float[3];
//calculating track data
for (int frame = startFrame; frame <= stopFrame; ++frame) {
int index = frame - startFrame;
times[index] = start + (frame - 1) * timeBetweenFrames;
for (int j = 0; j < bezierCurves.length; ++j) {
double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
switch (bezierCurves[j].getType()) {
case AC_LOC_X:
case AC_LOC_Y:
case AC_LOC_Z:
translation[bezierCurves[j].getType() - 1] = (float) value;
break;
case OB_ROT_X:
case OB_ROT_Y:
case OB_ROT_Z:
objectRotation[bezierCurves[j].getType() - 7] = (float) value;
bObjectRotation = true;
break;
case AC_SIZE_X:
case AC_SIZE_Y:
case AC_SIZE_Z:
scale[bezierCurves[j].getType() - 13] = (float) value;
break;
case AC_QUAT_W:
quaternionRotation[3] = (float) value;
break;
case AC_QUAT_X:
case AC_QUAT_Y:
case AC_QUAT_Z:
quaternionRotation[bezierCurves[j].getType() - 26] = (float) value;
break;
default:
//TODO: error? info? warning?
//calculating track data
for (int frame = startFrame; frame <= stopFrame; ++frame) {
int index = frame - startFrame;
times[index] = start + (frame - 1) * timeBetweenFrames;
for (int j = 0; j < bezierCurves.length; ++j) {
double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
switch (bezierCurves[j].getType()) {
case AC_LOC_X:
case AC_LOC_Y:
case AC_LOC_Z:
translation[bezierCurves[j].getType() - 1] = (float) value;
break;
case OB_ROT_X:
case OB_ROT_Y:
case OB_ROT_Z:
objectRotation[bezierCurves[j].getType() - 7] = (float) value;
break;
case AC_SIZE_X:
case AC_SIZE_Y:
case AC_SIZE_Z:
scale[bezierCurves[j].getType() - 13] = (float) value;
break;
case AC_QUAT_W:
quaternionRotation[3] = (float) value;
break;
case AC_QUAT_X:
case AC_QUAT_Y:
case AC_QUAT_Z:
quaternionRotation[bezierCurves[j].getType() - 26] = (float) value;
break;
default:
//TODO: error? info? warning?
}
}
translations[index] = new Vector3f(translation[0], translation[1], translation[2]);
rotations[index] = bSpatialTrack ? new Quaternion().fromAngles(objectRotation)
: new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
}
translations[index] = new Vector3f(translation[0], translation[1], translation[2]);
rotations[index] = bObjectRotation ? new Quaternion().fromAngles(objectRotation)
: new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
}
calculatedTrack = new BoneTrack(boneIndex, times, translations, rotations, scales);
if(bSpatialTrack) {
calculatedTrack = new SpatialTrack(times, translations, rotations, scales);
} else {
calculatedTrack = new BoneTrack(targetIndex, times, translations, rotations, scales);
}
}
return calculatedTrack;
}
}

@ -6,7 +6,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -15,6 +14,7 @@ import com.jme3.animation.Animation;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.animation.SkeletonControl;
import com.jme3.animation.Track;
import com.jme3.math.Matrix4f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
@ -116,28 +116,27 @@ import com.jme3.util.BufferUtils;
this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext);
//read animations
String objectName = objectStructure.getName();
Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName);
System.out.println("Loaded animation " + objectName);
if (animationNames != null && animationNames.size() > 0) {
ArrayList<Animation> animations = new ArrayList<Animation>();
List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
for (FileBlockHeader header : actionHeaders) {
Structure actionStructure = header.getStructure(blenderContext);
String actionName = actionStructure.getName();
if (animationNames.contains(actionName)) {
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName);
int fps = blenderContext.getBlenderKey().getFps();
float start = (float) animationFrames[0] / (float) fps;
float stop = (float) animationFrames[1] / (float) fps;
Animation boneAnimation = new Animation(actionName, stop - start);
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName));
animations.add(boneAnimation);
ArrayList<Animation> animations = new ArrayList<Animation>();
List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
for (FileBlockHeader header : actionHeaders) {
Structure actionStructure = header.getStructure(blenderContext);
String actionName = actionStructure.getName();
Track<?>[] tracks = armatureHelper.getTracks(actionStructure, blenderContext);
//determining the animation time
float maximumTrackLength = 0;
for(Track<?> track : tracks) {
float length = track.getLength();
if(length > maximumTrackLength) {
maximumTrackLength = length;
}
}
animData = new AnimData(new Skeleton(bones), animations);
Animation boneAnimation = new Animation(actionName, maximumTrackLength);
boneAnimation.setTracks(tracks);
animations.add(boneAnimation);
}
animData = new AnimData(new Skeleton(bones), animations);
}
}
}

@ -1,10 +1,22 @@
package com.jme3.scene.plugins.blender.modifiers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.animation.AnimControl;
import com.jme3.animation.Animation;
import com.jme3.animation.Track;
import com.jme3.scene.Node;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.animations.IpoHelper;
import com.jme3.scene.plugins.blender.constraints.Constraint;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
@ -41,13 +53,12 @@ import com.jme3.scene.plugins.ogre.AnimData;
*/
public ObjectAnimationModifier(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
LOGGER.warning("Object animation modifier not yet implemented!");
/*
Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
if (pIpo.isNotNull()) {
// check if there is an action name connected with this ipo
String objectAnimationName = null;
List<FileBlockHeader> actionBlocks = blenderContext
.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
List<FileBlockHeader> actionBlocks = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
for (FileBlockHeader actionBlock : actionBlocks) {
Structure action = actionBlock.getStructure(blenderContext);
List<Structure> actionChannels = ((Structure) action.getFieldValue("chanbase")).evaluateListBase(blenderContext);
@ -68,38 +79,51 @@ import com.jme3.scene.plugins.ogre.AnimData;
IpoHelper ipoHelper = blenderContext.getHelper(IpoHelper.class);
Structure ipoStructure = pIpo.fetchData(blenderContext.getInputStream()).get(0);
Ipo ipo = ipoHelper.createIpo(ipoStructure, blenderContext);
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, objectAnimationName);
if (animationFrames == null) {// if the name was created here there are no frames set for the animation
animationFrames = new int[] { 1, ipo.getLastFrame() };
}
int fps = blenderContext.getBlenderKey().getFps();
float start = (float) animationFrames[0] / (float) fps;
float stop = (float) animationFrames[1] / (float) fps;
// calculating track for the only bone in this skeleton
BoneTrack[] tracks = new BoneTrack[1];
tracks[0] = ipo.calculateTrack(0, animationFrames[0], animationFrames[1], fps);
BoneAnimation boneAnimation = new BoneAnimation(objectAnimationName, stop - start);
boneAnimation.setTracks(tracks);
Track<?> track = ipo.calculateTrack(-1, 0, ipo.getLastFrame(), fps);
Animation animation = new Animation(objectAnimationName, ipo.getLastFrame() / fps);
animation.setTracks(new Track<?>[] { track });
ArrayList<Animation> animations = new ArrayList<Animation>(1);
animations.add(boneAnimation);
// preparing the object's bone
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Transform t = objectHelper.getTransformation(objectStructure, blenderContext);
Bone bone = new Bone(null);
bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
animations.add(animation);
animData = new AnimData(new Skeleton(new Bone[] { bone }), animations);
animData = new AnimData(null, animations);
objectOMA = objectStructure.getOldMemoryAddress();
}
*/
}
@Override
public Node apply(Node node, BlenderContext blenderContext) {
LOGGER.warning("Object animation modifier not yet implemented!");
if(invalid) {
LOGGER.log(Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName());
}//if invalid, animData will be null
if(animData == null) {
return node;
}
ArrayList<Animation> animList = animData.anims;
if (animList != null && animList.size() > 0) {
List<Constraint> constraints = blenderContext.getConstraints(this.objectOMA);
HashMap<String, Animation> anims = new HashMap<String, Animation>();
for (int i = 0; i < animList.size(); ++i) {
Animation animation = (Animation) animList.get(i).clone();
// baking constraints into animations
if (constraints != null && constraints.size() > 0) {
for (Constraint constraint : constraints) {
constraint.affectAnimation(animation, 0);
}
}
anims.put(animation.getName(), animation);
}
AnimControl control = new AnimControl(null);
control.setAnimations(anims);
node.addControl(control);
}
return node;
}

Loading…
Cancel
Save