js/base/Bone.js
'use strict'
import Vector3 from './Vector3'
import Vector4 from './Vector4'
import Matrix from './Matrix'
import ObjectAssign from '../etc/ObjectAssign'
/**
* Bone basic class
* @access public
*/
export default class Bone {
/**
* constructor
* @access public
* @constructor
*/
constructor() {
/** @type {string} */
this.name = ''
/** @type {string} */
this.englishName = ''
/** @type {int} */
this.parentNo = -1
/** @type {int} */
this.childNo = -1
/** @type {int} */
this.type = 0
/** @type {int} */
this.ikTarget = -1
/** @type {Vector3} */
this.position = new Vector3()
/** @type {Bone} */
this.parentBone = null
/** @type {Array<Bone>} */
this.childBoneArray = []
/** @type {Matrix} */
this.localMatrix = new Matrix()
/** @type {Vector4} */
this.rotate = new Vector4()
/** @type {Vector3} */
this.scale = new Vector3(1.0, 1.0, 1.0)
/** @type {Matrix} */
this.scaleMatrix = new Matrix()
/** @type {Vector3} */
this.bonePosition = new Vector3()
/** @type {Vector3} */
this.offset = new Vector3()
/** @type {Matrix} */
this.offsetMatrix = new Matrix()
/** @type {Matrix} */
this.inflMatrix = new Matrix()
/** @type {Vector3} */
this.blendPosition = new Vector3()
/** @type {Vector4} */
this.blendRotation = new Vector4()
/** @type {boolean} */
this.isKnee = false
}
/**
* initialize bone data
* @access public
* @returns {void}
*/
initBoneData() {
this.localMatrix.identity()
this.localMatrix.m41 = this.bonePosition.x
this.localMatrix.m42 = this.bonePosition.y
this.localMatrix.m43 = this.bonePosition.z
if(this.parentBone){
this.offset.sub(this.bonePosition, this.parentBone.bonePosition)
}else{
this.offset.setValue(this.bonePosition)
}
this.offsetMatrix.identity()
this.offsetMatrix.m41 = -this.bonePosition.x
this.offsetMatrix.m42 = -this.bonePosition.y
this.offsetMatrix.m43 = -this.bonePosition.z
this.reset()
}
/**
* copy bone data
* @access public
* @returns {Bone} new Bone object
*/
clone() {
//const newBone = Object.assign(new Bone(), this)
const newBone = ObjectAssign(new Bone(), this)
newBone.position = this.position.clone()
newBone.localMatrix = this.localMatrix.clone()
newBone.rotate = this.rotate.clone()
newBone.bonePosition = this.bonePosition.clone()
newBone.offset = this.offset.clone()
newBone.offsetMatrix = this.offsetMatrix.clone()
newBone.inflMatrix = this.inflMatrix.clone()
newBone.blendPosition = this.blendPosition.clone()
newBone.blendRotation = this.blendRotation.clone()
return newBone
}
/**
* add child bone
* @access public
* @param {Bone} childBone -
* @returns {void}
*/
addChild(childBone) {
if(childBone.parentBone){
childBone.parentBone.removeChild(childBone)
}
this.childBoneArray.push(childBone)
childBone.parentBone = this
}
/**
* remove child bone
* @access public
* @param {Bone} childBone -
* @returns {void}
*/
removeChild(childBone) {
if(childBone.parentBone === this){
//this.childBoneArray = this.childBoneArray.without(childBone)
this.childBoneArray = this.childBoneArray.filter((bone) => { return bone !== childBone })
childBone.parentBone = null
}
}
/**
* reset bone position
* @access public
* @returns {void}
*/
reset() {
this.position.x = this.position.y = this.position.z = 0.0
this.rotate.x = this.rotate.y = this.rotate.z = 0.0
this.rotate.w = 1.0
this.localMatrix.identity()
this.localMatrix.m41 = this.bonePosition.x
this.localMatrix.m42 = this.bonePosition.y
this.localMatrix.m43 = this.bonePosition.z
}
/**
*
* @access public
* @returns {void}
*/
updateMatrix() {
const mat = this.localMatrix
mat.matrixFromQuaternion(this.rotate)
if(this.scale.x !== 1.0 || this.scale.y !== 1.0 || this.scale.z !== 1.0){
this.scaleMatrix.m11 = this.scale.x
this.scaleMatrix.m22 = this.scale.y
this.scaleMatrix.m33 = this.scale.z
mat.multiplyMatrix(this.scaleMatrix, mat)
}
mat.m41 = this.position.x + this.offset.x
mat.m42 = this.position.y + this.offset.y
mat.m43 = this.position.z + this.offset.z
if(this.parentBone){
mat.multiplyMatrix(mat, this.parentBone.localMatrix)
}
this.updateInflMatrix()
}
/**
*
* @access public
* @returns {void}
*/
updateInflMatrix() {
this.inflMatrix.multiplyMatrix(this.offsetMatrix, this.localMatrix)
}
/**
*
* @access public
* @returns {void}
*/
updateMatrixRecursive() {
this.updateMatrix()
this.childBoneArray.forEach((childBone) => {
childBone.updateMatrixRecursive()
})
}
/**
*
* @access public
* @returns {void}
*/
setBlendValue() {
this.blendPosition.setValue(this.position)
this.blendRotation.setValue(this.rotate)
}
/**
*
* @access public
* @returns {void}
*/
setBlendValueRecursive() {
this.setBlendValue()
this.childBoneArray.forEach((childBone) => {
childBone.setBlendValueRecursive()
})
}
}
// static values
// bone types
Bone.prototype.BONE_TYPE_ROT = 0
Bone.prototype.BONE_TYPE_TRANS = 1
Bone.prototype.BONE_TYPE_IK = 2
Bone.prototype.BONE_TYPE_UNKNOWN = 3
Bone.prototype.BONE_TYPE_IK_CHILD = 4
Bone.prototype.BONE_TYPE_IK_ROT = 5
Bone.prototype.BONE_TYPE_IK_ROOT = 6
Bone.prototype.BONE_TYPE_HIDDEN = 7
Bone.prototype.BONE_TYPE_TWIST = 8
Bone.prototype.BONE_TYPE_ROLL = 9