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

📄 jointcontroller.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
     * @param start
     *            The starting frame number.
     * @param end
     *            The ending frame number.
     */
    public void setTimes(int start, int end) {
        if (start < 0
                || start > end
                || movementInfo.get(movementInfo.size() - 1).time < end
                        / FPS) {
            String message = "Malformed times: start="
                    + start
                    + " end="
                    + end
                    + " start limit: 0 End limit: "
                    + movementInfo.get(movementInfo.size() - 1).time
                    * FPS;
            throw new JmeException(message);
        }
        setMinTime(start / FPS);
        setMaxTime(end / FPS);
        curTime = getMinTime();
        curTimePoint = 1;
        movingForward = true;
    }

    /**
     * Used with update(float). <code>updateData</code> moves every normal and
     * vertex acording to its jointIndex
     */
    private void updateData() {
        for (int currentGroup = 0; currentGroup < movingMeshes.size(); currentGroup++) {
            JointMesh updatingGroup = movingMeshes
                    .get(currentGroup);
            int currentBoneIndex;
            FloatBuffer verts = updatingGroup.getVertexBuffer();
            FloatBuffer normals = updatingGroup.getNormalBuffer();
            int j;
            for (j = 0; j < updatingGroup.jointIndex.length; j++) {
                currentBoneIndex = updatingGroup.jointIndex[j];
                if (currentBoneIndex == -1) continue;
                unSyncbeginPos.set(updatingGroup.originalVertex[j]);
                BufferUtils.setInBuffer(jointMovements[currentBoneIndex]
                                                       .multPoint(unSyncbeginPos), verts, j);
                unSyncbeginPos.set(updatingGroup.originalNormal[j]);
                BufferUtils.setInBuffer(jointMovements[currentBoneIndex]
                                                       .multNormal(unSyncbeginPos), normals, j);
            }
            if (j != 0) {
                if (updatePerFrame) updatingGroup.updateModelBound();
            }
        }
    }

    /**
     * Used with update(float) to combine joints with their inverse to properly
     * translate points.
     */
    private void combineWithInverse() {
        for (int i = 0; i < numJoints; i++)
            jointMovements[i].multLocal(inverseChainMatrix[i], unSyncbeginPos);
    }

    /**
     * Processes a JointController by filling holes and creating inverse
     * matrixes. Should only be called once per JointController object lifetime
     */
    public void processController() {
        if (movementInfo.size() == 1) { // IE no times were added or only time 0
            // was added
            movementInfo.add(0, new PointInTime(0));
        }
        setMinTime(movementInfo.get(0).time);
        setMaxTime(movementInfo.get(movementInfo.size() - 1).time);
        curTime = getMinTime();
        invertWithParents();
        fillHoles();
    }

    /**
     * If true, the model's bounding volume will be updated every frame. If
     * false, it will not.
     * 
     * @param update
     *            The new update model volume per frame value.
     */
    public void setModelUpdate(boolean update) {
        updatePerFrame = update;
    }

    /**
     * Returns true if the model's bounding volume is being updated every frame.
     * 
     * @return True if bounding volume is updating.
     */
    public boolean getModelUpdate() {
        return updatePerFrame;
    }

    /**
     * Inverts joints with their parents. Only called once per JointController
     * lifetime during processing.
     */
    private void invertWithParents() {
        for (int i = 0; i < numJoints; i++) {
            inverseChainMatrix[i] = new TransformMatrix(localRefMatrix[i]);
            inverseChainMatrix[i].inverse();
            if (parentIndex[i] != -1)
                    inverseChainMatrix[i].multLocal(
                            inverseChainMatrix[parentIndex[i]], unSyncbeginPos);
        }
    }

    /**
     * Called with update to create the needed joint transforms for that point
     * in time.
     * 
     * @param changeAmnt
     *            The % diffrence (from 0-1) between two points in time
     */
    private void createJointTransforms(float changeAmnt) {
        PointInTime now = movementInfo.get(curTimePoint);
        PointInTime then = movementInfo.get(curTimePoint - 1);
        for (int index = 0; index < numJoints; index++) {
            int theParentIndex = parentIndex[index];

            unSyncbeginAngle.set(then.jointRotation[index]);
            unSyncbeginPos.set(then.jointTranslation[index]);

            unSyncbeginAngle.slerp(now.jointRotation[index], changeAmnt);
            unSyncbeginPos.interpolate(now.jointTranslation[index], changeAmnt);

            tempUnSyncd.set(unSyncbeginAngle, unSyncbeginPos);
            jointMovements[index].set(localRefMatrix[index]);
            jointMovements[index].multLocal(tempUnSyncd, unSyncbeginPos);
            if (theParentIndex != -1) {
                tempUnSyncd.set(jointMovements[index]);
                jointMovements[index].set(jointMovements[theParentIndex]);
                jointMovements[index].multLocal(tempUnSyncd, unSyncbeginPos);
            }
        }
    }

    /**
     * Fills null rotations and translations for any joint at any point in time.
     */
    private void fillHoles() {
        fillRots();
        fillTrans();
    }

    /**
     * Gives every PointInTime for every joint a valid rotation.
     */
    private void fillRots() {
        for (int joint = 0; joint < numJoints; joint++) {
            // 1) Find first non-null rotation of joint <code>joint</code>
            int start;
            for (start = 0; start < movementInfo.size(); start++) {
                if (movementInfo.get(start).jointRotation[joint] != null)
                        break;
            }
            if (start == movementInfo.size()) { // if they are all null then
                // fill with identity
                for (int i = 0; i < movementInfo.size(); i++)
                    movementInfo.get(i).jointRotation[joint] = new Quaternion();
                continue; // we're done with this joint so lets continue
            }
            if (start != 0) { // if there -are- null elements at the begining,
                // then fill with first non-null
                unSyncbeginAngle
                        .set(movementInfo.get(start).jointRotation[joint]);
                for (int i = 0; i < start; i++)
                    movementInfo.get(i).jointRotation[joint] = new Quaternion(
                            unSyncbeginAngle);
            }
            int lastgood = start;
            boolean allGood = true;
            for (int i = start + 2; i < movementInfo.size(); i++) {
                if (movementInfo.get(i).jointRotation[joint] != null) {
                    fillQuats(joint, lastgood, i); // fills gaps
                    lastgood = i;
                    allGood = false;
                }
            }
            if (!allGood && lastgood != movementInfo.size() - 1) { // fills tail
                movementInfo.get(movementInfo.size() - 1).jointRotation[joint] = new Quaternion(
                        movementInfo.get(lastgood).jointRotation[joint]);
                fillQuats(joint, lastgood, movementInfo.size() - 1); // fills
                // tail
            }
        }
    }

    /**
     * Gives every PointInTime for every joint a valid translation.
     */
    private void fillTrans() {
        for (int joint = 0; joint < numJoints; joint++) {
            // 1) Find first non-null translation of joint <code>joint</code>
            int start;
            for (start = 0; start < movementInfo.size(); start++) {
                if (movementInfo.get(start).jointTranslation[joint] != null)
                        break;
            }
            if (start == movementInfo.size()) { // if they are all null then
                // fill with identity
                for (int i = 0; i < movementInfo.size(); i++)
                    movementInfo.get(i).jointTranslation[joint] = new Vector3f(
                            0, 0, 0);
                continue; // we're done with this joint so lets continue
            }
            if (start != 0) { // if there -are- null elements at the begining,
                // then fill with first non-null
                unSyncbeginPos
                        .set(movementInfo.get(start).jointTranslation[joint]);
                for (int i = 0; i < start; i++)
                    movementInfo.get(i).jointTranslation[joint] = new Vector3f(
                            unSyncbeginPos);
            }
            int lastgood = start;
            boolean allGood = true;
            for (int i = start + 2; i < movementInfo.size(); i++) {
                if (movementInfo.get(i).jointTranslation[joint] != null) {
                    fillPos(joint, lastgood, i); // fills gaps
                    lastgood = i;
                    allGood = false;
                }
            }
            if (!allGood && lastgood != movementInfo.size() - 1) { // fills tail
                movementInfo.get(movementInfo.size() - 1).jointTranslation[joint] = new Vector3f(
                        movementInfo.get(lastgood).jointTranslation[joint]);
                fillPos(joint, lastgood, movementInfo.size() - 1); // fills tail
            }
        }
    }

    /**
     * Interpolates missing quats that weren't specified to the JointController.
     * 
     * @param jointIndex
     *            Index of the joint that has missing quats
     * @param startRotIndex
     *            Begining index of a valid non-null quat
     * @param endRotIndex
     *            Ending index of a valid non-null quat
     */
    private void fillQuats(int jointIndex, int startRotIndex, int endRotIndex) {
        unSyncbeginAngle
                .set(movementInfo.get(startRotIndex).jointRotation[jointIndex]);
        for (int i = startRotIndex + 1; i < endRotIndex; i++) {
            movementInfo.get(i).jointRotation[jointIndex] = new Quaternion(
                    unSyncbeginAngle);
            movementInfo.get(i).jointRotation[jointIndex]
                    .slerp(
                            movementInfo.get(endRotIndex).jointRotation[jointIndex],
                            ((float) i - startRotIndex)
                                    / (endRotIndex - startRotIndex));
        }
    }

    /**
     * Interpolates missing vector that weren't specified to the
     * JointController.
     * 
     * @param jointIndex
     *            Index of the joint that has missing vector
     * @param startPosIndex
     *            Begining index of a valid non-null vector
     * @param endPosIndex
     *            Ending index of a valid non-null vector
     */
    private void fillPos(int jointIndex, int startPosIndex, int endPosIndex) {
        unSyncbeginPos
                .set(movementInfo.get(startPosIndex).jointTranslation[jointIndex]);
        for (int i = startPosIndex + 1; i < endPosIndex; i++) {
            movementInfo.get(i).jointTranslation[jointIndex] = new Vector3f(
                    unSyncbeginPos);
            movementInfo.get(i).jointTranslation[jointIndex]
                    .interpolate(
                            movementInfo.get(endPosIndex).jointTranslation[jointIndex],
                            ((float) i - startPosIndex)
                                    / (endPosIndex - startPosIndex));
        }
    }

    /**
     * Adds a jointmesh for this JointController to consider animating.
     * 
     * @param child
     *            Child JointMesh to consider
     */
    public void addJointMesh(JointMesh child) {
        movingMeshes.add(child);
    }

    public void write(JMEExporter e) throws IOException {
        super.write(e);
        OutputCapsule capsule = e.getCapsule(this);
        capsule.write(numJoints, "numJoints", 0);
        capsule.writeSavableArrayList(movementInfo, "movementInfo", new ArrayList<PointInTime>());
        capsule.write(parentIndex, "parentIndex", new int[numJoints]);
        capsule.write(localRefMatrix, "localRefMatrix", new TransformMatrix[numJoints]);
        capsule.write(FPS, "FPS", 0);
        capsule.writeSavableArrayList(movingMeshes, "movingMeshes", new ArrayList<JointMesh>());
        capsule.write(jointMovements, "jointMovements", new TransformMatrix[numJoints]);
        capsule.write(skipRate, "skipRate", 0);
        capsule.write(updatePerFrame, "updatePerFrame", false);
        capsule.write(movingForward, "movingForward", false);
    }
    
    @SuppressWarnings("unchecked")
	public void read(JMEImporter e) throws IOException {
        super.read(e);
        InputCapsule capsule = e.getCapsule(this);
        numJoints = capsule.readInt("numJoints", 0);
        movementInfo = capsule.readSavableArrayList("movementInfo", new ArrayList<PointInTime>());
        parentIndex = capsule.readIntArray("parentIndex", new int[numJoints]);
        
        Savable[] savs = capsule.readSavableArray("localRefMatrix", new TransformMatrix[numJoints]);
        if (savs == null)
            localRefMatrix = null;
        else {
            localRefMatrix = new TransformMatrix[savs.length];
            for (int x = 0; x < savs.length; x++) {
                localRefMatrix[x] = (TransformMatrix)savs[x];
            }
        }
        
        savs = capsule.readSavableArray("jointMovements", new TransformMatrix[numJoints]);
        if (savs == null)
            jointMovements = null;
        else {
            jointMovements = new TransformMatrix[savs.length];
            for (int x = 0; x < savs.length; x++) {
                jointMovements[x] = (TransformMatrix)savs[x];
            }
        }
        
        FPS = capsule.readFloat("FPS", 0);
        movingMeshes = capsule.readSavableArrayList("movingMeshes", new ArrayList<JointMesh>());
        skipRate = capsule.readFloat("skipRate", 0);
        updatePerFrame = capsule.readBoolean("updatePerFrame", false);
        movingForward = capsule.readBoolean("movingForward", false);
        
        
        inverseChainMatrix = new TransformMatrix[numJoints];
        for (int i = 0; i < numJoints; i++) {
            inverseChainMatrix[i] = new TransformMatrix();
        }
        processController();
    }
}

⌨️ 快捷键说明

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