159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.animation;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.*;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Node;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>Bone</code> describes a bone in the bone-weight skeletal animation
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * system. A bone contains a name and an index, as well as relevant
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * transformation data.
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Kirill Vainer
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic final class Bone implements Savable {
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String name;
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Bone parent;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final ArrayList<Bone> children = new ArrayList<Bone>();
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * If enabled, user can control bone transform with setUserTransforms.
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Animation transforms are not applied to this bone when enabled.
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean userControl = false;
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The attachment node.
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Node attachNode;
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Initial transform is the local bind transform of this bone.
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * PARENT SPACE -> BONE SPACE
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f initialPos;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion initialRot;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f initialScale;
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The inverse world bind transform.
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * BONE SPACE -> MODEL SPACE
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldBindInversePos;
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion worldBindInverseRot;
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldBindInverseScale;
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The local animated transform combined with the local bind transform and parent world transform
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f localPos = new Vector3f();
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion localRot = new Quaternion();
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f localScale = new Vector3f(1.0f, 1.0f, 1.0f);
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * MODEL SPACE -> BONE SPACE (in animated state)
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldPos = new Vector3f();
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion worldRot = new Quaternion();
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldScale = new Vector3f();
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //used for getCombinedTransform
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Transform tmpTransform = new Transform();
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Creates a new bone with the given name.
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param name Name to give to this bone
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Bone(String name) {
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (name == null)
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException("Name cannot be null");
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.name = name;
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialPos = new Vector3f();
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialRot = new Quaternion();
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialScale = new Vector3f(1, 1, 1);
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInversePos = new Vector3f();
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseRot = new Quaternion();
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseScale = new Vector3f();
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Special-purpose copy constructor.
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Only copies the name and bind pose from the original.
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * WARNING: Local bind pose and world inverse bind pose transforms shallow
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * copied. Modifying that data on the original bone will cause it to
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * be recomputed on any cloned bones.
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The rest of the data is <em>NOT</em> copied, as it will be
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * generated automatically when the bone is animated.
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param source The bone from which to copy the data.
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    Bone(Bone source) {
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.name = source.name;
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        userControl = source.userControl;
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialPos = source.initialPos;
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialRot = source.initialRot;
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialScale = source.initialScale;
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInversePos = source.worldBindInversePos;
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseRot = source.worldBindInverseRot;
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseScale = source.worldBindInverseScale;
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // parent and children will be assigned manually..
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Serialization only. Do not use.
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Bone() {
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the name of the bone, set in the constructor.
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The name of the bone, set in the constructor.
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public String getName() {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return name;
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns parent bone of this bone, or null if it is a root bone.
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The parent bone of this bone, or null if it is a root bone.
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Bone getParent() {
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return parent;
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns all the children bones of this bone.
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return All the children bones of this bone.
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public ArrayList<Bone> getChildren() {
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return children;
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the local position of the bone, relative to the parent bone.
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The local position of the bone, relative to the parent bone.
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getLocalPosition() {
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return localPos;
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the local rotation of the bone, relative to the parent bone.
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The local rotation of the bone, relative to the parent bone.
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Quaternion getLocalRotation() {
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return localRot;
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the local scale of the bone, relative to the parent bone.
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The local scale of the bone, relative to the parent bone.
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getLocalScale() {
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return localScale;
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the position of the bone in model space.
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The position of the bone in model space.
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getModelSpacePosition() {
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldPos;
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the rotation of the bone in model space.
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The rotation of the bone in model space.
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Quaternion getModelSpaceRotation() {
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldRot;
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the scale of the bone in model space.
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The scale of the bone in model space.
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getModelSpaceScale() {
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldScale;
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the inverse world bind pose position.
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the inverse world bind pose position.
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldBindInversePosition() {
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldBindInversePos;
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the inverse world bind pose rotation.
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the inverse world bind pose rotation.
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Quaternion getWorldBindInverseRotation() {
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldBindInverseRot;
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the inverse world bind pose scale.
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the inverse world bind pose scale.
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldBindInverseScale() {
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldBindInverseScale;
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the world bind pose position.
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the world bind pose position.
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldBindPosition() {
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return initialPos;
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the world bind pose rotation.
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the world bind pose rotation.
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Quaternion getWorldBindRotation() {
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return initialRot;
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the world bind pose scale.
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The bind pose transform of the bone is its "default"
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * transform with no animation applied.
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the world bind pose scale.
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldBindScale() {
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return initialScale;
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * If enabled, user can control bone transform with setUserTransforms.
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Animation transforms are not applied to this bone when enabled.
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setUserControl(boolean enable) {
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        userControl = enable;
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Add a new child to this bone. Shouldn't be used by user code.
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Can corrupt skeleton.
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bone The bone to add
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addChild(Bone bone) {
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        children.add(bone);
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bone.parent = this;
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Updates the world transforms for this bone, and, possibly the attach node
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * if not null.
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <p>
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The world transform of this bone is computed by combining the parent's
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * world transform with this bones' local transform.
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public final void updateWorldVectors() {
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (parent != null) {
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //rotation
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            parent.worldRot.mult(localRot, worldRot);
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //scale
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //For scale parent scale is not taken into account!
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // worldScale.set(localScale);
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            parent.worldScale.mult(localScale, worldScale);
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //translation
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //scale and rotation of parent affect bone position
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            parent.worldRot.mult(localPos, worldPos);
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPos.multLocal(parent.worldScale);
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPos.addLocal(parent.worldPos);
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldRot.set(localRot);
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPos.set(localPos);
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldScale.set(localScale);
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (attachNode != null) {
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setLocalTranslation(worldPos);
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setLocalRotation(worldRot);
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setLocalScale(worldScale);
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Updates world transforms for this bone and it's children.
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    final void update() {
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.updateWorldVectors();
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = children.size() - 1; i >= 0; i--) {
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            children.get(i).update();
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Saves the current bone state as its binding pose, including its children.
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    void setBindingPose() {
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialPos.set(localPos);
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialRot.set(localRot);
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialScale.set(localScale);
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (worldBindInversePos == null) {
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldBindInversePos = new Vector3f();
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldBindInverseRot = new Quaternion();
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldBindInverseScale = new Vector3f();
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Save inverse derived position/scale/orientation, used for calculate offset transform later
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInversePos.set(worldPos);
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInversePos.negateLocal();
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseRot.set(worldRot);
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseRot.inverseLocal();
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseScale.set(Vector3f.UNIT_XYZ);
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldBindInverseScale.divideLocal(worldScale);
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Bone b : children) {
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            b.setBindingPose();
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Reset the bone and it's children to bind pose.
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    final void reset() {
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!userControl) {
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localPos.set(initialPos);
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localRot.set(initialRot);
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localScale.set(initialScale);
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = children.size() - 1; i >= 0; i--) {
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            children.get(i).reset();
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     /**
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Stores the skinning transform in the specified Matrix4f.
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The skinning transform applies the animation of the bone to a vertex.
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This assumes that the world transforms for the entire bone hierarchy
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * have already been computed, otherwise this method will return undefined
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * results.
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param outTransform
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    void getOffsetTransform(Matrix4f outTransform, Quaternion tmp1, Vector3f tmp2, Vector3f tmp3, Matrix3f tmp4) {
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Computing scale
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f scale = worldScale.mult(worldBindInverseScale, tmp3);
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Computing rotation
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Quaternion rotate = worldRot.mult(worldBindInverseRot, tmp1);
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Computing translation
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Translation depend on rotation and scale
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f translate = worldPos.add(rotate.mult(scale.mult(worldBindInversePos, tmp2), tmp2), tmp2);
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Populating the matrix
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        outTransform.loadIdentity();
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        outTransform.setTransform(translate, scale, rotate.toRotationMatrix(tmp4));
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets user transform.
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setUserTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!userControl) {
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalStateException("User control must be on bone to allow user transforms");
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.set(initialPos);
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot.set(initialRot);
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localScale.set(initialScale);
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.addLocal(translation);
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot = localRot.mult(rotation);
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localScale.multLocal(scale);
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Must update all bones in skeleton for this to work.
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param translation
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param rotation
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setUserTransformsWorld(Vector3f translation, Quaternion rotation) {
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!userControl) {
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalStateException("User control must be on bone to allow user transforms");
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // TODO: add scale here ???
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPos.set(translation);
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldRot.set(rotation);
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //if there is an attached Node we need to set it's local transforms too.
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if(attachNode != null){
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setLocalTranslation(translation);
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setLocalRotation(rotation);
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the local transform of this bone combined with the given position and rotation
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param position a position
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param rotation a rotation
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Transform getCombinedTransform(Vector3f position, Quaternion rotation) {
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position);
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tmpTransform.setRotation(rotation).getRotation().multLocal(localRot);
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return tmpTransform;
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the attachment node.
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Attach models and effects to this node to make
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * them follow this bone's motions.
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    Node getAttachmentsNode() {
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (attachNode == null) {
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode = new Node(name + "_attachnode");
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            attachNode.setUserData("AttachedBone", this);
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return attachNode;
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Used internally after model cloning.
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param attachNode
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    void setAttachmentsNode(Node attachNode) {
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.attachNode = attachNode;
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets the local animation transform of this bone.
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Bone is assumed to be in bind pose when this is called.
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    void setAnimTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (userControl) {
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        localPos.addLocal(translation);
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        localRot.multLocal(rotation);
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //localRot = localRot.mult(rotation);
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.set(initialPos).addLocal(translation);
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot.set(initialRot).multLocal(rotation);
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (scale != null) {
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localScale.set(initialScale).multLocal(scale);
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    void blendAnimTransforms(Vector3f translation, Quaternion rotation, Vector3f scale, float weight) {
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (userControl) {
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        assert vars.lock();
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f tmpV = vars.vect1;
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f tmpV2 = vars.vect2;
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Quaternion tmpQ = vars.quat1;
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //location
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tmpV.set(initialPos).addLocal(translation);
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.interpolate(tmpV, weight);
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //rotation
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tmpQ.set(initialRot).multLocal(rotation);
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot.nlerp(tmpQ, weight);
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //scale
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (scale != null) {
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tmpV2.set(initialScale).multLocal(scale);
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localScale.interpolate(tmpV2, weight);
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets local bind transform for bone.
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Call setBindingPose() after all of the skeleton bones' bind transforms are set to save them.
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setBindTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialPos.set(translation);
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialRot.set(rotation);
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //ogre.xml can have null scale values breaking this if the check is removed
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (scale != null) {
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            initialScale.set(scale);
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.set(translation);
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot.set(rotation);
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (scale != null) {
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            localScale.set(scale);
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String toString(int depth) {
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        StringBuilder sb = new StringBuilder();
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < depth; i++) {
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sb.append('-');
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        sb.append(name).append(" bone\n");
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Bone child : children) {
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sb.append(child.toString(depth + 1));
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return sb.toString();
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public String toString() {
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return this.toString(0);
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @SuppressWarnings("unchecked")
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter im) throws IOException {
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule input = im.getCapsule(this);
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        name = input.readString("name", null);
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialPos = (Vector3f) input.readSavable("initialPos", null);
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialRot = (Quaternion) input.readSavable("initialRot", null);
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialScale = (Vector3f) input.readSavable("initialScale", new Vector3f(1.0f, 1.0f, 1.0f));
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        attachNode = (Node) input.readSavable("attachNode", null);
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localPos.set(initialPos);
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        localRot.set(initialRot);
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ArrayList<Bone> childList = input.readSavableArrayList("children", null);
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = childList.size() - 1; i >= 0; i--) {
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            this.addChild(childList.get(i));
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // NOTE: Parent skeleton will call update() then setBindingPose()
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // after Skeleton has been de-serialized.
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Therefore, worldBindInversePos and worldBindInverseRot
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // will be reconstructed based on that information.
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter ex) throws IOException {
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule output = ex.getCapsule(this);
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.write(name, "name", null);
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.write(attachNode, "attachNode", null);
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.write(initialPos, "initialPos", null);
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.write(initialRot, "initialRot", null);
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.write(initialScale, "initialScale", new Vector3f(1.0f, 1.0f, 1.0f));
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        output.writeSavableArrayList(children, "children", null);
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
629