Exemple #1
0
  /**
   * Constructor. Creates the basic set of bone's data.
   *
   * @param boneStructure the bone's structure
   * @param parent bone's parent (null if the bone is the root bone)
   * @param objectToArmatureMatrix object-to-armature transformation matrix
   * @param bonesPoseChannels a map of pose channels for each bone OMA
   * @param blenderContext the blender context
   * @throws BlenderFileException an exception is thrown when problem with blender data reading
   *     occurs
   */
  private BoneContext(
      Structure boneStructure,
      BoneContext parent,
      Matrix4f objectToArmatureMatrix,
      final Map<Long, Structure> bonesPoseChannels,
      BlenderContext blenderContext)
      throws BlenderFileException {
    this.parent = parent;
    this.boneStructure = boneStructure;
    boneName = boneStructure.getFieldValue("name").toString();
    ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
    armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", true);

    fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
    this.computeRestMatrix(objectToArmatureMatrix);
    List<Structure> childbase =
        ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
    for (Structure child : childbase) {
      this.children.add(
          new BoneContext(child, this, objectToArmatureMatrix, bonesPoseChannels, blenderContext));
    }

    poseChannel = bonesPoseChannels.get(boneStructure.getOldMemoryAddress());

    blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
  }
  @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;
      }

      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;

        constraintDefinition.bake(
            ownerTransform, targetTransform, boneTrack, targetTrack, this.ipo);
      }
    }
  }
Exemple #3
0
  /**
   * This method builds the bone. It recursively builds the bone's children.
   *
   * @param bones a list of bones where the newly created bone will be added
   * @param boneOMAs the map between bone and its old memory address
   * @param blenderContext the blender context
   * @return newly created bone
   */
  public Bone buildBone(List<Bone> bones, Map<Bone, Long> boneOMAs, BlenderContext blenderContext) {
    Long boneOMA = boneStructure.getOldMemoryAddress();
    bone = new Bone(boneName);
    bones.add(bone);
    boneOMAs.put(bone, boneOMA);
    blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);

    Matrix4f pose = this.restMatrix.clone();
    ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);

    Vector3f poseLocation = pose.toTranslationVector();
    Quaternion rotation = pose.toRotationQuat();
    Vector3f scale = objectHelper.getScale(pose);

    bone.setBindTransforms(poseLocation, rotation, scale);
    for (BoneContext child : children) {
      bone.addChild(child.buildBone(bones, boneOMAs, blenderContext));
    }

    this.computePoseTransform();

    return bone;
  }
  /**
   * 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);
      }
    }
  }