From ea6e975792a559fd49b11f85cae665d6a1365eb3 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 1 Mar 2026 20:14:37 +0900 Subject: [PATCH] SkinnedMesh: Update "applyBoneTransform" to optionally take Vector4, support direction or position transformation (#33091) --- src/objects/SkinnedMesh.js | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/objects/SkinnedMesh.js b/src/objects/SkinnedMesh.js index 4a492b8feac447..04280944f5a68e 100644 --- a/src/objects/SkinnedMesh.js +++ b/src/objects/SkinnedMesh.js @@ -8,12 +8,12 @@ import { Ray } from '../math/Ray.js'; import { AttachedBindMode, DetachedBindMode } from '../constants.js'; import { warn } from '../utils.js'; -const _basePosition = /*@__PURE__*/ new Vector3(); +const _baseVector = /*@__PURE__*/ new Vector4(); const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); -const _vector3 = /*@__PURE__*/ new Vector3(); +const _vector4 = /*@__PURE__*/ new Vector4(); const _matrix4 = /*@__PURE__*/ new Matrix4(); const _vertex = /*@__PURE__*/ new Vector3(); @@ -309,12 +309,12 @@ class SkinnedMesh extends Mesh { /** * Applies the bone transform associated with the given index to the given - * vertex position. Returns the updated vector. + * vector. Can be used to transform positions or direction vectors by providing + * a Vector4 with 1 or 0 in the w component respectively. Returns the updated vector. * * @param {number} index - The vertex index. - * @param {Vector3} target - The target object that is used to store the method's result. - * the skinned mesh's world matrix will be used instead. - * @return {Vector3} The updated vertex position. + * @param {Vector3|Vector4} target - The target object that is used to store the method's result. + * @return {Vector3|Vector4} The updated vertex attribute data. */ applyBoneTransform( index, target ) { @@ -324,9 +324,19 @@ class SkinnedMesh extends Mesh { _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); + if ( target.isVector4 ) { + + _baseVector.copy( target ); + target.set( 0, 0, 0, 0 ); + + } else { + + _baseVector.set( ...target, 1 ); + target.set( 0, 0, 0 ); - target.set( 0, 0, 0 ); + } + + _baseVector.applyMatrix4( this.bindMatrix ); for ( let i = 0; i < 4; i ++ ) { @@ -338,12 +348,19 @@ class SkinnedMesh extends Mesh { _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - target.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); + target.addScaledVector( _vector4.copy( _baseVector ).applyMatrix4( _matrix4 ), weight ); } } + if ( target.isVector4 ) { + + // ensure the homogenous coordinate remains unchanged after vector operations + target.w = _baseVector.w; + + } + return target.applyMatrix4( this.bindMatrixInverse ); }