Three.js r90中matrixWorld使用疑问:为何clone后multiply才生效?
关于Three.js r90中applyTransform函数的疑问
我有两个applyTransform函数,核心区别在于是否克隆originObj.matrixWorld后再与transform参数相乘。第一个函数无法正常工作,但第二个可以。
我原本的认知是:Object3D的matrix和matrixWorld属性会在每一帧的renderer.render()过程中重新计算,所以直接给这两个属性赋值应该没有意义,会被后续的渲染流程覆盖。按这个逻辑,两个函数应该都能正常运行,但实际只有第二个可行,想请教下我的认知误区在哪里?
两个函数的代码对比
无法正常工作的版本
applyTransform(originObj, target, transform) { const newTransform = originObj.matrixWorld.multiply(transform); // decompose newTransformMatrix as position, rotation and scale const position = new THREE.Vector3(); const quaternion = new THREE.Quaternion(); const scale = new THREE.Vector3(); newTransform.decompose(position, quaternion, scale); target.position.copy(position); target.quaternion.copy(quaternion); target.scale.copy(scale); }
可以正常工作的版本
applyTransform(originObj, target, transform) { const newTransform = originObj.matrixWorld.clone().multiply(transform); // decompose newTransformMatrix as position, rotation and scale const position = new THREE.Vector3(); const quaternion = new THREE.Quaternion(); const scale = new THREE.Vector3(); newTransform.decompose(position, quaternion, scale); target.position.copy(position); target.quaternion.copy(quaternion); target.scale.copy(scale); }
问题根源与认知误区解析
其实问题出在Three.js中Matrix4.multiply()方法的原地修改特性上:
- 第一个版本里,
originObj.matrixWorld.multiply(transform)是直接在originObj自身的matrixWorld矩阵上进行运算,运算结果会直接覆盖原矩阵的值。而matrixWorld是Three.js内部用来维护物体世界空间变换的核心属性,你私自修改它之后,会打乱后续renderer.render()流程中自动更新矩阵的逻辑,导致变换计算出现异常。 - 第二个版本里,先通过
clone()复制了一份matrixWorld的独立副本,再在这个副本上执行乘法运算,完全不会影响原物体的内部矩阵状态,计算出的newTransform是干净的独立矩阵,用它来分解赋值给target的位置、旋转、缩放自然能正常工作。
再纠正你之前的认知误区:你说的“给.matrix或.matrixWorld赋值会被render覆盖”是有前提的——当Object3D的matrixAutoUpdate为true(默认值)时,Three.js会在每帧自动重新计算矩阵。但你直接调用multiply()这种原地修改方法,属于在自动计算前就篡改了内部状态,这和“直接赋值后被自动计算覆盖”是完全不同的场景,前者会干扰Three.js的内部逻辑,后者只是你的赋值被后续自动计算覆盖而已。
内容的提问来源于stack exchange,提问作者minami kotori
相关产品推荐
相关产品推荐

