diff --git a/AnimationDirector.js b/AnimationDirector.js index 724dbfa..5b9a673 100644 --- a/AnimationDirector.js +++ b/AnimationDirector.js @@ -4001,7 +4001,12 @@ const explicit = model.display?.[context]; const data = explicit || (slot === 'left' ? model.display?.thirdperson_righthand : null) || {}; const rotation = v3(data.rotation), translation = v3(data.translation), scale = v3(data.scale, 1); - if (slot === 'left' && !explicit) { translation[0] *= -1; rotation[1] *= -1; rotation[2] *= -1; } + // Minecraft mirrors the selected display transform for left-hand rendering. + if (slot === 'left') { + translation[0] = -translation[0] || 0; + rotation[1] = -rotation[1] || 0; + rotation[2] = -rotation[2] || 0; + } return { rotation, translation, scale }; } @@ -4223,8 +4228,6 @@ centered.add(new THREE.Mesh(geometry, material)); } } - // GeckoLib -> Blockbench coordinate conversion mirrors model X, including attached items. - root.scale.x = -1; return root; } catch (error) { disposePropMesh(root); throw error; } } diff --git a/test/item-props.test.js b/test/item-props.test.js index 94343f3..e1976cb 100644 --- a/test/item-props.test.js +++ b/test/item-props.test.js @@ -77,8 +77,11 @@ test('left-hand and floor transforms follow Minecraft display contexts', () => { assert.deepEqual(Array.from(left.translation),[-1,2,3]); assert.deepEqual(Array.from(h.propDisplayTransform(model,'floor').scale),[.5,.5,.5]); const handheld = h.propDisplayTransform(h.manualPropModel('handheld'),'left'); - assert.deepEqual(Array.from(handheld.rotation),[0,90,-55]); + assert.deepEqual(Array.from(handheld.rotation),[0,-90,55]); assert.deepEqual(Array.from(handheld.translation),[0,4,0.5]); + const explicit = h.propDisplayTransform({display:{thirdperson_lefthand:{rotation:[5,35,-20],translation:[2,3,4]}}},'left'); + assert.deepEqual(Array.from(explicit.rotation),[5,-35,20]); + assert.deepEqual(Array.from(explicit.translation),[-2,3,4]); }); test('3D JSON models keep elements, UVs, rotations and texture aliases', () => {