⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jointcontroller.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jmex.model.animation;

import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import com.jme.math.Quaternion;
import com.jme.math.TransformMatrix;
import com.jme.math.Vector3f;
import com.jme.scene.Controller;
import com.jme.system.JmeException;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;
import com.jme.util.export.Savable;
import com.jme.util.geom.BufferUtils;
import com.jmex.model.JointMesh;

/**
 * Started Date: Jun 9, 2004 <br>
 * 
 * This controller animates a Node's JointMesh children acording to the joints
 * stored inside <code>movementInfo</code>.
 * 
 * @author Jack Lindamood
 */
public class JointController extends Controller {

    private static final long serialVersionUID = 1L;

    /**
     * It is JointController's responsibility to keep changePoints sorted by
     * <code>time</code> at all times.
     */
    public int numJoints;

    /**
     * movementInfo[i] contains a float value time and an array of
     * TransformMatrix. At time <code>time</code> the joint i is at movement
     * <code>jointChange[i]</code>
     */
    public ArrayList<PointInTime> movementInfo;

    /**
     * parentIndex contains a list of who's parent a joint is. -1 indicates a
     * root joint with no parent
     */
    public int[] parentIndex;

    /**
     * Local refrence matrix that can determine a joint's position in space
     * relative to its parent.
     */
    public TransformMatrix[] localRefMatrix;

    /** Currently unused. */
    public float FPS;

    /**
     * Array of all the meshes this controller should consider animating.
     */
    public ArrayList<JointMesh> movingMeshes;

    /**
     * This controller's internal current time.
     */
    private float curTime;

    /**
     * This controller's internal current PointInTime index.
     */
    private int curTimePoint;

    /**
     * Used internally, they are updated every update(float) call to tell points
     * how to change.
     */
    private TransformMatrix[] jointMovements;

    /**
     * The inverse chain matrix of every joint. Calculated once with
     * prosessController()
     */
    private TransformMatrix[] inverseChainMatrix;

    // Internal worker classes
    private final static Quaternion unSyncbeginAngle = new Quaternion();

    private final static Vector3f unSyncbeginPos = new Vector3f();

    private final static TransformMatrix tempUnSyncd = new TransformMatrix();

    /**
     * Tells update that it should be called every <code>skipRate</code>
     * seconds
     */
    public float skipRate;

    /**
     * Used with skipRate internally.
     */
    private float currentSkip;

    /** If true, the model's bounding volume will update every frame. */
    private boolean updatePerFrame = true;

    private boolean movingForward = true;

    public JointController() {
        curTime = 0;
        curTimePoint = 1;
    }
    
    /**
     * Constructs a new JointController that will hold the given number of
     * joints.
     * 
     * @param numJoints
     *            The number of joints this jointController will have
     */
    public JointController(int numJoints) {
        this.numJoints = numJoints;
        parentIndex = new int[numJoints];
        localRefMatrix = new TransformMatrix[numJoints];
        movingMeshes = new ArrayList<JointMesh>();
        jointMovements = new TransformMatrix[numJoints];
        inverseChainMatrix = new TransformMatrix[numJoints];
        for (int i = 0; i < numJoints; i++) {
            localRefMatrix[i] = new TransformMatrix();
            jointMovements[i] = new TransformMatrix();
            inverseChainMatrix[i] = new TransformMatrix();
        }
        movementInfo = new ArrayList<PointInTime>();
        curTime = 0;
        curTimePoint = 1;
        currentSkip = 0;
        skipRate = .01f;
    }
    
    public float getCurrentTime() {
        return curTime;
    }

    /**
     * Tells JointController that at time <code>time</code> the joint
     * <code>jointNumber</code> will translate to x,y,z relative to its parent
     * 
     * @param jointNumber
     *            Index of joint to affect
     * @param time
     *            Which time the joint will take these values
     * @param x
     *            Joint's x translation
     * @param y
     *            Joint's y translation
     * @param z
     *            Joint's z translation
     */
    public void setTranslation(int jointNumber, float time, float x, float y,
            float z) {
        findUpToTime(time).setTranslation(jointNumber, x, y, z);
    }

    /**
     * Tells JointController that at time <code>time</code> the joint
     * <code>jointNumber</code> will translate to x,y,z relative to its parent
     * 
     * @param jointNumber
     *            Index of joint to affect
     * @param time
     *            Which time the joint will take these values
     * @param trans
     *            Joint's translation
     *  
     */
    public void setTranslation(int jointNumber, float time, Vector3f trans) {
        findUpToTime(time).setTranslation(jointNumber, trans);
    }

    /**
     * Tells JointController that at time <code>time</code> the joint
     * <code>jointNumber</code> will rotate acording to the euler angles x,y,z
     * relative to its parent's rotation
     * 
     * @param jointNumber
     *            Index of joint to affect
     * @param time
     *            Which time the joint will take these values
     * @param x
     *            Joint's x rotation
     * @param y
     *            Joint's y rotation
     * @param z
     *            Joint's z rotation
     */
    public void setRotation(int jointNumber, float time, float x, float y,
            float z) {
        findUpToTime(time).setRotation(jointNumber, x, y, z);
    }

    /**
     * Tells JointController that at time <code>time</code> the joint
     * <code>jointNumber</code> will rotate acording to
     * <code>Quaternion</code>.
     * 
     * @param jointNumber
     *            Index of joint to affect
     * @param time
     *            Which time the joint will take these values
     * @param quaternion
     *            The joint's new rotation
     */
    public void setRotation(int jointNumber, float time, Quaternion quaternion) {
        findUpToTime(time).setRotation(jointNumber, quaternion);
    }

    /**
     * Used with setRotation and setTranslation. This function finds a point in
     * time for given time. If one doesn't exist then a new PointInTime is
     * created and returned.
     * 
     * @param time
     * @return The PointInTime at that given time, or a new one if none exist so
     *         far.
     */
    private PointInTime findUpToTime(float time) {
        int index = 0;
        for (PointInTime point : movementInfo) {
            float curTime = point.time;
            if (curTime >= time) break;
            index++;
        }
        PointInTime storedNext = null;
        if (index == movementInfo.size()) {
            storedNext = new PointInTime(numJoints);
            movementInfo.add(storedNext);
            storedNext.time = time;
        } else {
            if (movementInfo.get(index).time == time) {
                storedNext = movementInfo.get(index);
            } else {
                storedNext = new PointInTime(numJoints);
                movementInfo.add(index, storedNext);
                storedNext.time = time;
            }
        }
        return storedNext;
    }

    /**
     * Updates the <code>movingMeshes</code> by updating their joints +=time
     * 
     * @param time
     *            Time from last update
     */
    public void update(float time) {
        if (numJoints == 0) return;
        if (movingForward)
            curTime += time * this.getSpeed();
        else
            curTime -= time * this.getSpeed();
        currentSkip += time;
        if (currentSkip >= skipRate) {
            currentSkip = 0;
        } else {
            return;
        }

        setCurTimePoint();
        PointInTime now = movementInfo.get(curTimePoint);
        PointInTime then = movementInfo.get(curTimePoint - 1);

        float delta = (curTime - then.time) / (now.time - then.time);
        createJointTransforms(delta);
        combineWithInverse();
        updateData();
    }

    private void setCurTimePoint() {

        int repeatType = getRepeatType();
        // reset if too far
        if (curTime > getMaxTime()) {
            if (repeatType == Controller.RT_WRAP)
                curTime = getMinTime();
            else if (repeatType == Controller.RT_CYCLE) {
                curTime = getMaxTime();
                movingForward = false;
            } else if (repeatType == Controller.RT_CLAMP) {
                setActive(false);
                curTime = getMaxTime();
            }
        }

        if (curTime < getMinTime()) {
            if (repeatType == Controller.RT_WRAP)
                curTime = getMaxTime();
            else if (repeatType == Controller.RT_CYCLE) {
                curTime = getMinTime();
                movingForward = true;
            } else if (repeatType == Controller.RT_CLAMP) {
                setActive(false);
                curTime = getMinTime();
            }
        }

        // if curTimePoint works then return
        PointInTime p1 = movementInfo.get(curTimePoint);
        PointInTime p2 = movementInfo.get(curTimePoint - 1);
        if (curTime <= p1.time && curTime >= p2.time) return;
        for (curTimePoint = 1; curTimePoint < movementInfo.size(); curTimePoint++) {
            p1 = movementInfo.get(curTimePoint);
            if (p1.time >= curTime) return;
        }
    }

    /**
     * Sets the frames the joint controller will animate from and to. The frames
     * are dependant upon the FPS. Remember that the first frame starts at 1,
     * <b>NOT </b>0.
     * 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -