|
|
@ -7,6 +7,8 @@ import java.util.HashMap; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
import java.util.logging.Level; |
|
|
|
|
|
|
|
import java.util.logging.Logger; |
|
|
|
|
|
|
|
|
|
|
|
import com.jme3.animation.AnimControl; |
|
|
|
import com.jme3.animation.AnimControl; |
|
|
|
import com.jme3.animation.Animation; |
|
|
|
import com.jme3.animation.Animation; |
|
|
@ -43,6 +45,7 @@ import com.jme3.util.BufferUtils; |
|
|
|
* @author Marcin Roguski (Kaelthas) |
|
|
|
* @author Marcin Roguski (Kaelthas) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
/* package */class ArmatureModifier extends Modifier { |
|
|
|
/* package */class ArmatureModifier extends Modifier { |
|
|
|
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(ArmatureModifier.class.getName()); |
|
|
|
private static final int MAXIMUM_WEIGHTS_PER_VERTEX = 4; // have no idea why 4, could someone please explain ?
|
|
|
|
private static final int MAXIMUM_WEIGHTS_PER_VERTEX = 4; // have no idea why 4, could someone please explain ?
|
|
|
|
|
|
|
|
|
|
|
|
/** Loaded animation data. */ |
|
|
|
/** Loaded animation data. */ |
|
|
@ -80,53 +83,55 @@ import com.jme3.util.BufferUtils; |
|
|
|
* corrupted |
|
|
|
* corrupted |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { |
|
|
|
public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { |
|
|
|
Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); |
|
|
|
if(this.validate(modifierStructure, blenderContext)) { |
|
|
|
if (pArmatureObject.isNotNull()) { |
|
|
|
Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); |
|
|
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); |
|
|
|
if (pArmatureObject.isNotNull()) { |
|
|
|
ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); |
|
|
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); |
|
|
|
|
|
|
|
ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); |
|
|
|
Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
|
|
|
|
this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); |
|
|
|
Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
|
|
|
|
this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); |
|
|
|
//read skeleton
|
|
|
|
|
|
|
|
// changing bones matrices so that they fit the current object
|
|
|
|
//read skeleton
|
|
|
|
Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
// changing bones matrices so that they fit the current object
|
|
|
|
Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); |
|
|
|
Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
List<Structure> bonesStructures = bonebase.evaluateListBase(blenderContext); |
|
|
|
Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); |
|
|
|
for (Structure boneStructure : bonesStructures) { |
|
|
|
List<Structure> bonesStructures = bonebase.evaluateListBase(blenderContext); |
|
|
|
BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); |
|
|
|
for (Structure boneStructure : bonesStructures) { |
|
|
|
armatureHelper.addBoneDataRoot(rootBoneTransformationData); |
|
|
|
BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); |
|
|
|
} |
|
|
|
armatureHelper.addBoneDataRoot(rootBoneTransformationData); |
|
|
|
Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); |
|
|
|
} |
|
|
|
Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); |
|
|
|
Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); |
|
|
|
Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); |
|
|
|
Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); |
|
|
|
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); |
|
|
|
Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); |
|
|
|
|
|
|
|
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); |
|
|
|
//read mesh indexes
|
|
|
|
|
|
|
|
Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
//read mesh indexes
|
|
|
|
this.meshOMA = meshStructure.getOldMemoryAddress(); |
|
|
|
Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); |
|
|
|
this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); |
|
|
|
this.meshOMA = meshStructure.getOldMemoryAddress(); |
|
|
|
|
|
|
|
this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); |
|
|
|
//read animations
|
|
|
|
|
|
|
|
String objectName = objectStructure.getName(); |
|
|
|
//read animations
|
|
|
|
Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName); |
|
|
|
String objectName = objectStructure.getName(); |
|
|
|
if (animationNames != null && animationNames.size() > 0) { |
|
|
|
Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName); |
|
|
|
ArrayList<Animation> animations = new ArrayList<Animation>(); |
|
|
|
if (animationNames != null && animationNames.size() > 0) { |
|
|
|
List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); |
|
|
|
ArrayList<Animation> animations = new ArrayList<Animation>(); |
|
|
|
for (FileBlockHeader header : actionHeaders) { |
|
|
|
List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); |
|
|
|
Structure actionStructure = header.getStructure(blenderContext); |
|
|
|
for (FileBlockHeader header : actionHeaders) { |
|
|
|
String actionName = actionStructure.getName(); |
|
|
|
Structure actionStructure = header.getStructure(blenderContext); |
|
|
|
if (animationNames.contains(actionName)) { |
|
|
|
String actionName = actionStructure.getName(); |
|
|
|
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName); |
|
|
|
if (animationNames.contains(actionName)) { |
|
|
|
int fps = blenderContext.getBlenderKey().getFps(); |
|
|
|
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName); |
|
|
|
float start = (float) animationFrames[0] / (float) fps; |
|
|
|
int fps = blenderContext.getBlenderKey().getFps(); |
|
|
|
float stop = (float) animationFrames[1] / (float) fps; |
|
|
|
float start = (float) animationFrames[0] / (float) fps; |
|
|
|
BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); |
|
|
|
float stop = (float) animationFrames[1] / (float) fps; |
|
|
|
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName)); |
|
|
|
BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); |
|
|
|
animations.add(boneAnimation); |
|
|
|
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName)); |
|
|
|
|
|
|
|
animations.add(boneAnimation); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
animData = new AnimData(new Skeleton(bones), animations); |
|
|
|
} |
|
|
|
} |
|
|
|
animData = new AnimData(new Skeleton(bones), animations); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -134,6 +139,9 @@ import com.jme3.util.BufferUtils; |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
public Node apply(Node node, BlenderContext blenderContext) { |
|
|
|
public Node apply(Node node, BlenderContext blenderContext) { |
|
|
|
|
|
|
|
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) { |
|
|
|
if(animData == null) { |
|
|
|
return node; |
|
|
|
return node; |
|
|
|
} |
|
|
|
} |
|
|
|