Rotate an object around a sphere with a custom gravity

97 views Asked by At

I'm currently trying to make an object rotate around a sphere with physics in Threejs.

I'm facing issues with the orientation of the model and the control with the applyImpulse on this same model in order to make it move.

My principal problems are that i can't find a correct collider for the model since the applyImpulse i use to simulate gravity make the model explode if i use a colliders of type trimesh.

My algorithm is probably not the best one in order to make the object move around the icosahedron. If anyone have any idea or any tips about that instead of increasing position depending on the current axis values..

Finally i have troube to keep my model facing the right way, like if the fox is supposed to walk or run, he should be facing in front of him. Going down the Icosahedron make him upside down.

I've searched for example about move objects around a sphere/icosahedron pretty much everywhere i could but didn't find anything.

If anyone got ressources about how to do this or any tips that could make me think differently, it would be greatly appreciated.

Below the minimum to reproduce :


    import {
      Html,
      KeyboardControls,
      OrbitControls,
      useGLTF,
      useKeyboardControls
    } from "@react-three/drei";
    import { useFrame } from "@react-three/fiber";
    import {
      BallCollider,
      CuboidCollider,
      Physics,
      RigidBody,
      useRapier,
      vec3
    } from "@react-three/rapier";
    import { useEffect, useRef, useState } from "react";
    import * as THREE from "three";
    import Model from "./Fox/Fox";
    
    const Experience = () => {
      const [subscribeKeys, getKeys] = useKeyboardControls();
      const cap = useRef();
      const modelRef = useRef();
    
      useFrame((state, delta) => {
        /**
         * Controls
         */
        const { forward, backward, leftward, rightward } = getKeys();
    
        // prepare before because sometimes we can press 2 keys at the same time
        const impulse = { x: 0, y: 0, z: 0 };
    
        // these variables will be used to adjust fps difference (apply the same for everyone w/e the fps number)
        const impulseStrength = 70 * delta;
    
        const positions = cap.current?.translation();
        if (forward) {
          if (positions.y > 0) impulse.z -= impulseStrength;
          else impulse.z += impulseStrength;
        }
        if (rightward) {
          if (positions.y > 0) impulse.x += impulseStrength;
          else impulse.x -= impulseStrength;
        }
        if (backward) {
          if (positions.y > 0) impulse.z += impulseStrength;
          else impulse.z -= impulseStrength;
        }
        if (leftward) {
          if (positions.y > 0) impulse.x -= impulseStrength;
          else impulse.x += impulseStrength;
        }
    
        cap.current.applyImpulse(impulse);
    
        const myForce = vec3().subVectors(
          vec3({ x: 0, y: 0, z: 0 }),
          vec3(positions)
        );
        const myDirection = vec3().subVectors(
          vec3(positions),
          vec3({ x: 0, y: 0, z: 0 })
        );
        modelRef.current.lookAt(myDirection);
        cap.current?.applyImpulse(myForce.normalize());
      });
    
      return (
        <>
          <OrbitControls makeDefault />
    
          <Physics gravity={[0, 0, 0]} debug>
            <RigidBody
              position={[0, 16, 0]}
              canSleep={false}
              friction={1}
              type="dynamic"
              colliders="ball"
              ref={cap}
              linearDamping={0.5}
              angularDamping={1}
            >
              <mesh ref={modelRef}>
          <sphereGeometry args={[1, 10, 10]} />
          <meshBasicMaterial color="greenyellow" />
        </mesh>
            </RigidBody>
            <RigidBody
              type="fixed"
              colliders="ball"
              position={[0, 0, 0]}
              friction={1}
            >
              <mesh>
                <icosahedronGeometry args={[15.0, 3]} />
                <meshBasicMaterial color="mediumpurple" wireframe />
              </mesh>
            </RigidBody>
          </Physics>
          <ambientLight />
        </>
      );
    };
    
    export default Experience;

Here's the full code : https://codesandbox.io/s/laughing-poincare-wzngx3?file=/src/Experience.jsx

Thanks in advance,

0

There are 0 answers