Instance transformations stuck at 90 degrees when rotating

I’m trying to do a basic instance animation where each object simply rotates around a single axis. (in this case the Y) This works as expected, then for whatever reason it’s getting stuck whenever it gets to 90 degrees.

The way I’m doing it is pulling the matrix of the instance in a loop, pushing the matrix to a dummy object, doing the rotation (like you would a regular Object3D), updating the Object Matrix, then pushing the matrix back on the instance.

This is the method almost every other example uses… however, most examples use their own math or data points to push the transform using setMatrixAt() and don’t use the instance’s own existing matrix with getMatrixAt() in their calculations.

Here is my for loop for the animation:

for (let i = 0; i < count; i++) {
            // get the items current position
            meshRef.current.getMatrixAt(i, currentMatrix);
            /*console.log("item: ", i, "currentMatrix: ", currentMatrix.toArray()); */

            // set the temp objects position using this matrix
            //threejs doesn't let you set the matrix directly
            currentMatrix.decompose(
                tempObject.position,
                tempObject.quaternion,
                tempObject.scale
            );
            // do the transformation to the temp object
            console.log("Rotation: ", tempObject.rotation.y);

            tempObject.rotation.y -= Math.random() * 0.01;
            tempObject.updateMatrix();
            //push the change back to the instance
            meshRef.current.setMatrixAt(i, tempObject.matrix);
            meshRef.current.instanceMatrix.needsUpdate = true;
        }

And here is a running Code Sandbox

This example is running in R3F but it also happens in vanilla which this snippet mostly is anyway.

I know it’s got something to do with the matrix, decompose, Euler, quaternion voodoo going on but I wanted to see if folks here may have an easy solution before I dived into all that.

My ideal scenario would be just copying the matrix onto a basic Object3D so I can to standard type transforms, then pushing the matrix back on the instance. However something’s not letting that happen…

Using Euler angles is like crossing a street. Before crossing you look left and right for speeding vehicles. Twice. After crossing you look again left and right for vehicles.

When switching from Eulers to quaternions and then back to Eulers, you should not expect to get the same triplet of rotation angles. Although the overall orientation should be the same, the numeric values may differ.

Here is a version that uses matrices to do rotations of instances around their local Y axes (rotation is in lines 74-85):

https://codepen.io/boytchev/full/eYXJjEe

image

Thank you for this!
It’s a neat example and I like your position initialization code. I also appreciate the code to use a matrix transform directly on the matrix from the instance.

What I’m wondering is, what is happening in my original when I apply the matrix values to the Object3D like that? I’m not trying to pass a specific rotation angle and it’s not matching, I’m just trying to increment what’s already there…

In many many usecases and examples it’s useful to use the same animation methods and language like position setting, rotation, etc on regular meshes and instances alike. I’d like to be able to understand why it’s not working to either file/fix a bug or understand my mistake.

I got one version to work where I overwrite or copy() the matrix from the instance onto the object, however, it strips out the position data back to [0,0,0] for no obvious reason…

If I do a Vector3.setFromMatrixPosition() before the copy() then reapply it works as expected but this is a weird behavior too…

So now I have two odd behaviors’. One the matrix gets stuck at 90deg. for no apparent reason, two, when copying a matrix it’s not copying ALL the matrix data…

A simple use case for this would be like in your example having all of the objects point to the mouse cursor, or an object like a sphere floating through the area and the arrows pointing at it.

With an object3D I could easily use the LookAt() method etc but I’m worried that they would have similar matrix issues and get frozen or worse drop their position data…