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