/** * This constructor reads animation data from the object structore. The stored data is the * AnimData and additional data is armature's OMA. * * @param objectStructure the structure of the object * @param modifierStructure the structure of the modifier * @param blenderContext the blender context * @throws BlenderFileException this exception is thrown when the blender file is somehow * corrupted */ public ArmatureModifier( Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { if (this.validate(modifierStructure, blenderContext)) { Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); if (pArmatureObject.isNotNull()) { ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); // read skeleton // changing bones matrices so that they fit the current object Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")) .fetchData(blenderContext.getInputStream()) .get(0); Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); List<Structure> bonesStructures = bonebase.evaluateListBase(blenderContext); for (Structure boneStructure : bonesStructures) { BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); armatureHelper.addBoneDataRoot(rootBoneTransformationData); } Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); 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); this.meshOMA = meshStructure.getOldMemoryAddress(); this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); // read animations ArrayList<Animation> animations = new ArrayList<Animation>(); List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); if (actionHeaders != null) { // it may happen that the model has armature with no actions for (FileBlockHeader header : actionHeaders) { Structure actionStructure = header.getStructure(blenderContext); String actionName = actionStructure.getName(); BoneTrack[] tracks = armatureHelper.getTracks(actionStructure, blenderContext); // determining the animation time float maximumTrackLength = 0; for (BoneTrack track : tracks) { float length = track.getLength(); if (length > maximumTrackLength) { maximumTrackLength = length; } } Animation boneAnimation = new Animation(actionName, maximumTrackLength); boneAnimation.setTracks(tracks); animations.add(boneAnimation); } } animData = new AnimData(new Skeleton(bones), animations); } } }