Strange artifact when rotating around pivot

Hi,

I’m trying to rotate around a pivot point, according to this SO answer.

The problem is that the rotation is going in one direction and then the other, as can be seen in the attached video.

I’m using this code:

    const axis = new THREE.Vector3(1, 0, 0);
    const angle  = time;
    const pivot = new THREE.Vector3(+DX, -DY, -DZF);

    wheelFR.position.sub(pivot);
    wheelFR.position.applyAxisAngle(axis, angle);
    wheelFR.position.add(pivot);
    wheelFR.rotateOnAxis(axis, angle);

Any clues? Thanks!

You’re running both rotateOnAxis and applyAxisAngle, try running applyAxisAngle once as it will be recursively adding to the rotation angle then just run rotateOnAxis in the loop…

Sorry, I don’t understand. How can I run applyAxisAngle() once outside of the loop if it needs the angle as input?

can you provide a working live environment on codepen / jsfiddle so it’s easier to debug, find and show you the solution?

Sorry, I checked a few codepen-like solutions, but could not find any that allows assets uploading for free. I do need to upload my gltf model, as I can’t think of another minimal test case right now…

FWIW, the model is here and the standalone html file is here.

ok, because “time” is accumulative in your provided example you’re rotating by incremental amounts each run of update… try like this…

    wheelFR.position.sub(pivot);
    wheelFR.position.applyAxisAngle(axis, 0.05);
    wheelFR.position.add(pivot);
    wheelFR.rotateOnAxis(axis, 0.05);

this basically rotates the wheel by 0.05 radians each time update is run, instead of rotating by an accumalative number “time” as you had before…

Thank you forerunrun!

I need now to rotate the wheel on the Y axis as well, but it becomes much complicated because quaternions are necessary in order to avoid gimbal lock.

Anyway, I’m stuck again, with the following not working:

  function update(time) {
    const pivot = new THREE.Vector3(+DX, -DY, -DZF);

    const xAxis = new THREE.Vector3(1, 0, 0);
    const xRot = time;
    const xQuaternion = new THREE.Quaternion();
    xQuaternion.setFromAxisAngle( xAxis, xRot );

    const yAxis = new THREE.Vector3(0, 1, 0);
    const yRot = -Math.PI / 6.0;
    const yQuaternion = new THREE.Quaternion();
    yQuaternion.setFromAxisAngle( yAxis, yRot );

    var tmp = new THREE.Quaternion();
    tmp.multiplyQuaternions(xQuaternion, yQuaternion);

    wheelFR.position.sub(pivot);
    wheelFR.position.applyQuaternion(tmp);
    wheelFR.position.add(pivot);

    wheelFR.quaternion.set(tmp.x, tmp.y, tmp.z, tmp.w);
  }

no problem @arielm ,
it’s quite bad practice to recursively create new objects inside a loop, you’ll be creating somewhat of a memory leak in that there’s only so many new vectors and quaternions you can create before reaching a memory limit, i would create these objects as global references to reuse and update as needed…
there’s likely a clever solution to applying the quaternion to the position to prevent gimbal lock but have you considered using a simple object hierarchy to achieve the same? i’ve attached a pen where simply adding a new object3D to add the wheel to and translating the geometry of the original wheel object to a 0 origin you can control the x rotation from the wheel object and the y rotation from the new containing object…

otherwise, if applying quaternions is essential let me know.

Wow, perfect! Thank you very much, that’s exactly the kind of solution I was looking for.

By the way, cool of you to have created this codepen. So you own “3dpk” and have CORS enabled on the test folder?

No problem :beers:

Yeah, I prefer to keep cors on * and only lock out certain resources, all 3D resources can be scraped anyway so hey