Limit rotation of ferris wheel wagon's 🎡

hey(fixed)
i was woundring why the limit rotation’s i applied on the wagons of my ferris wheel does not work in three js ?
it suppossed to be like this


not like this

heres the model it self
perfection.blend (1.2 MB)

here’s how i fixed it

“”"
import React, { useRef, useEffect } from ‘react’;
import { useFrame } from ‘@react-three/fiber’;
import { useGLTF } from ‘@react-three/drei’;
import * as THREE from ‘three’;

function FerrisWheel() {
const groupRef = useRef();
const { scene } = useGLTF(‘/ferris.glb’);

const cylinderRef = useRef();
const cabins = useRef();

// We’ll reuse this quaternion for performance
const inverseQuat = new THREE.Quaternion();

useEffect(() => {
// Get the wheel
cylinderRef.current = scene.getObjectByName(‘Cylinder’);

// Get cabins v001 to v010
for (let i = 1; i <= 10; i++) {
  const name = `v${i.toString().padStart(3, '0')}`;
  const cabin = scene.getObjectByName(name);
  if (cabin) {
    cabins.current.push(cabin);
  }
}

// Add scene to group
groupRef.current.add(scene);

}, [scene]);

useFrame(() => {
if (cylinderRef.current) {
// Rotate the wheel
cylinderRef.current.rotation.y += 0.01;

  // Get the wheel's **world quaternion**
  cylinderRef.current.getWorldQuaternion(inverseQuat);
  inverseQuat.invert(); // Inverse of the wheel's rotation

  // Apply inverse rotation to cabins so they stay upright
  cabins.current.forEach((cabin) => {
    cabin.quaternion.copy(inverseQuat);
  });
}

});

return ;
}

export default FerrisWheel;

“”"

Why This Works

:white_check_mark: cylinderRef.current.getWorldQuaternion() gets the wheel’s full rotation in world space.
:white_check_mark: inverseQuat.invert() flips it, so when applied to the cabins, they cancel out the inherited rotation.
:white_check_mark: cabin.quaternion.copy(inverseQuat) forces cabins to stay upright in world space!

Made this just for fun.
When carts are children of the wheel itself, then their rotation is negative rotation of the wheel.

  update(t){
    this.ferrisFrame.rotation.z = t;
    this.carts.forEach(cart => {cart.rotation.z = -t});
  }

Video:

Demo: https://codepen.io/prisoner849/full/GgJRdvY

6 Likes

Could even add a subtle sway with a slight tweak…

this.carts.forEach(cart => {cart.rotation.z = -t + (Math.sin(t * 20) *0.1)});
4 Likes

I knew it! That someone will be tempted to do it :smile: :handshake:

2 Likes