Closed NicolasPerl closed 2 years ago
Heyo, thank you for the kind words. Looks like you got a neat project going there.
Let us add to the existing rotation. mesh.rotation.y += clock.getElapsedTime() /10
That will rotate relatively
about the object local Y euler value, or something. Guessing you want to keep spinning around world Y axis. Multiplying quaternion adds their rotations. To rotate in an object's parent space, likely the world, quat.premultiply
The crux:
const axis = new THREE.Vector3(0, 1, 0)
const quat = new THREE.Quaternion()
useFrame((state, deltaTime) => {
quat.setFromAxisAngle(axis, deltaTime * SPEED)
ref.current.quaternion.premultiply(quat)
})
A complete example: https://codesandbox.io/s/basic-demo-forked-x785p?file=/src/App.js
Hey Paul,
Thanks for getting back to me! This worked flawlessly.
I need to get a better grasp on quaternions... they're pretty intimidating!
Feel free to share any resources you studied to help you grasp quaternions.
I don't understand quaternions =) But there are a few algebraic operations and their "geometric interpretation" (aka my mythical heuristics) that seems to cover many needs (with similar parallels to 4x4 matrix operations):
Multiplying quaternions adds one rotation to another. Order of rotations matter, hence quaternion.premultiply(quat)
and quaternion.[post]multiply(quat)
. Usepremultiply
to rotate in an objects parent coordinate system.
target = current * offset
or often in 3D graphics world = parent * child
A quaternion's conjugate is the rotation in the other direction. So quatA * quatA.conjugate() = 0 rotation
or something.
To find the rotation from one quaternion to another, the rotation offset:
target = current * offset
solve for offset by multiplying both sides by current.conjugate
current.conjugate * target = current.conjugate * current * offset
current's and its conjugate cancel each other and we have
current.conjugate * target = offset
And in three.js
offset.copy(current.conjugate())
offset.multiply(target)
For setting the world orientation of a object deep in the scene graph hierarchy, can extract the quaternion from the parent's world matrix and apply the above where "current" is the parent world quaternion.
parent.getWorldQuaternion( parentToTargetOffset ).conjugate()
parentToTargetOffset.multiply( targetQuatWorldSpace )
child.quaternion.copy( parentToTargetOffset )
Hi There,
First off, thanks so much for working on this! It works great and has been a huge help.
Question... I have a mesh that has Spin Controls attached to it as well as an auto-rotate function that rotates the mesh on its Y-axis as seen below:
useFrame(() => { mesh.rotation.y = clock.getElapsedTime() /10; })
When the user clicks to spin the mesh the auto rotation is stopped to avoid jerking the mesh. The tricky part is having the auto-rotate pick up at the rotation.y that the user left the mesh after spinning it.
In other words - the expected behavior is after the user is done spinning the mesh the auto-rotate starts where the mesh finished rotation.
Has anyone found a good way of combining an autorotation with spin controls? Using the Three.js Clock isn't optimal because it can't be reset.