diff --git a/js/animations/animation_mode.js b/js/animations/animation_mode.js index b3c62059..cd92d4b2 100644 --- a/js/animations/animation_mode.js +++ b/js/animations/animation_mode.js @@ -306,6 +306,18 @@ export const Animator = { }) }) + for (let mesh of Mesh.all) { + let array = mesh.getParentArray(); + let mesh_index = array.indexOf(mesh); + let rig_root = array[mesh_index+1]; + if (rig_root instanceof ArmatureBone) { + animations.forEach(animation => { + let animator = animation.getBoneAnimator(rig_root); + animator.displayMeshDeform(mesh); + }); + } + } + Animator.resetLastValues(); scene.updateMatrixWorld(); diff --git a/js/animations/timeline_animators.js b/js/animations/timeline_animators.js index 1f9c88af..dfbfa3b4 100644 --- a/js/animations/timeline_animators.js +++ b/js/animations/timeline_animators.js @@ -1,4 +1,5 @@ import Wintersky from 'wintersky'; +import { THREE } from '../../lib/libs'; export class GeneralAnimator { constructor(uuid, animation) { @@ -595,17 +596,6 @@ class ArmatureBoneAnimator extends BoneAnimator { return (this.element && this.element && this.element.mesh); } displayPosition(arr, multiplier = 1) { - } - displayRotation(arr, multiplier = 1) { - - let element = this.element; - let mesh = element.getParentArray().filter(m => m instanceof Mesh)[0]; - if (!mesh) return; - - for (let vkey of vertices) {} - - - var bone = this.element.mesh if (arr) { bone.position.x -= arr[0] * multiplier; @@ -614,19 +604,76 @@ class ArmatureBoneAnimator extends BoneAnimator { } return this; } + displayRotation(arr, multiplier = 1) { + var mesh = this.element.mesh + if (arr) { + if (arr.length === 4) { + var added_rotation = new THREE.Euler().setFromQuaternion(new THREE.Quaternion().fromArray(arr), 'ZYX') + mesh.rotation.x -= added_rotation.x * multiplier + mesh.rotation.y -= added_rotation.y * multiplier + mesh.rotation.z += added_rotation.z * multiplier + } else { + arr.forEach((n, i) => { + mesh.rotation[getAxisLetter(i)] += Math.degToRad(n) * (i == 2 ? 1 : -1) * multiplier + }) + } + } + return this; + } + displayMeshDeform(mesh) { + if (!mesh) return; + // Only gets called at the base bone of each rig + + let matrices = {}; + let bones = []; + let element = this.getElement(); + let mesh_world_matrix_inverse = new THREE.Matrix4().copy(mesh.mesh.matrixWorld).invert(); + let vertex_offsets = {}; + let vector = new THREE.Vector3(); + let vector2 = new THREE.Vector3(); + + element.parent.mesh.updateMatrixWorld(); + element.forEachChild(bone => { + let matrix = new THREE.Matrix4().multiplyMatrices(bone.mesh.matrixWorld, mesh_world_matrix_inverse); + matrices[bone.uuid] = matrix; + bones.push(bone); + + }, ArmatureBone, true); + + for (let vkey in mesh.vertices) { + + vector.fromArray(mesh.vertices[vkey]); + vector2.copy(vector2); + + for (let bone of bones) { + let matrix = matrices[bone.uuid]; + if (true) { + vector.applyMatrix4(matrix); + } + } + vector.sub(vector2); + //vector.lerpVectors(); + vertex_offsets[vkey] = vector.toArray(); + } + Mesh.preview_controller.updateGeometry(mesh, vertex_offsets); + } displayFrame(multiplier = 1) { if (!this.doRender()) return; this.getElement() if (!this.muted.position) { this.displayPosition(this.interpolate('position'), multiplier); - this.displayRotation(this.interpolate('position'), multiplier); } + if (!this.muted.rotation) { + this.displayRotation(this.interpolate('rotation'), multiplier); + } + this.displayMeshDeform(); } } ArmatureBoneAnimator.prototype.type = 'null_object'; ArmatureBoneAnimator.prototype.channels = { position: {name: tl('timeline.position'), mutable: true, transform: true, max_data_points: 2}, + rotation: {name: tl('timeline.rotation'), mutable: true, transform: true, max_data_points: 2}, } ArmatureBone.animator = ArmatureBoneAnimator; diff --git a/js/outliner/armature_bone.js b/js/outliner/armature_bone.js index 71a1473b..4cb5133e 100644 --- a/js/outliner/armature_bone.js +++ b/js/outliner/armature_bone.js @@ -185,7 +185,7 @@ export class ArmatureBone extends OutlinerElement { offset.z += this.parent.origin[2]; } } else { - offset = Reusable.vec3.fromArray(this.position); + offset = Reusable.vec3.fromArray(this.origin); } offset.applyQuaternion(q); pos.add(offset); @@ -287,6 +287,11 @@ export class ArmatureBone extends OutlinerElement { i++; } } + static behavior = { + movable: true, + rotatable: true, + hide_in_screenshot: true, + } } ArmatureBone.prototype.title = tl('data.armature_bone'); ArmatureBone.prototype.type = 'armature_bone'; @@ -313,6 +318,7 @@ OutlinerElement.registerType(ArmatureBone, 'armature_bone'); new Property(ArmatureBone, 'vector', 'origin', {default: [0, 0, 0]}); new Property(ArmatureBone, 'vector', 'rotation'); +new Property(ArmatureBone, 'object', 'vertex_weights'); new NodePreviewController(ArmatureBone, { setup(element) { @@ -320,7 +326,7 @@ new NodePreviewController(ArmatureBone, { object_3d.rotation.order = 'ZYX'; object_3d.uuid = element.uuid.toUpperCase(); object_3d.name = element.name; - object_3d.isArmatureBone = true; + object_3d.isElement = true; Project.nodes_3d[element.uuid] = object_3d; diff --git a/js/outliner/mesh.js b/js/outliner/mesh.js index 1114a687..5808e0d8 100644 --- a/js/outliner/mesh.js +++ b/js/outliner/mesh.js @@ -1051,7 +1051,7 @@ new NodePreviewController(Mesh, { this.dispatchEvent('setup', {element}); }, - updateGeometry(element) { + updateGeometry(element, vertex_offsets) { let {mesh} = element; let point_position_array = []; @@ -1063,6 +1063,16 @@ new NodePreviewController(Mesh, { mesh.outline.vertex_order.empty(); let {vertices, faces} = element; + if (vertex_offsets) { + vertices = {}; + for (let vkey in element.vertices) { + vertices[vkey] = element.vertices[vkey].slice(); + if (vertex_offsets[vkey] instanceof Array) { + vertices[vkey].V3_add(vertex_offsets[vkey]) + } + } + } + for (let key in vertices) { let vector = vertices[key]; point_position_array.push(...vector);