Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PreStep support #67

Open
Splact opened this issue Apr 17, 2020 · 3 comments
Open

PreStep support #67

Splact opened this issue Apr 17, 2020 · 3 comments
Labels
enhancement New feature or request

Comments

@Splact
Copy link

Splact commented Apr 17, 2020

Is there a way to define a preStep function on a body?

const [ref, api] = useBox(
  () => ({
    args: [size[0] / 2, size[1] / 2, size[2] / 2],
    preStep: () => {
      console.log("prestep");
    },
    ...props,
  })
);

I tried passing a callback to useBox (as above) but this leads to an error on the worker.

Failed to execute 'postMessage' on 'Worker': function preStep() {
  console.log("preStep");
} could not be cloned.

My goal is to recreate gravity towards a point in space, so I'm trying to apply a constant force through that point in the preStep function. Don't know if I'm following the right approach, I'm open to suggestions.

A super nice solution to this would be having a component that defines an attractor point. An example below:

import { Physics, Attractor } from "use-cannon";

// ...

return (
  <Physics gravity={[0, 0, 0]}>
    {/* ... objects with useCannon hooks ... */}

    <Attractor position={[0, 50, -20]} mass={4} />
    <Attractor position={[0, -20, 60]} mass={6} />
  </Physics>
);
@codynova
Copy link
Member

Hey @Splact, sorry for the delayed response. The Cannon Body preStep and postStep methods are deprecated, and it's suggested that you use World events instead. However, we don't currently expose a way to add events to the world - and even if we did, we may still need to un-deprecate the Body preStep and postStep events to make the API a little more sane. This will need to be considered.

@drcmda Do you have any thoughts on this?

@codynova
Copy link
Member

We should also add a way to update world props like gravity, tolerance, allowSleep, etc. through the Provider context. I will try to find some time for this soon.

@Splact
Copy link
Author

Splact commented Apr 25, 2020

The solution I implemented with the current api is to apply a constant force in the direction of the gravity center on each frame. This is not theoretically correct, since the forces sum up on each frame, but the end result is acceptable in my case.

useFrame(() => {
  // Calculate constant force to the gravity center
  // 1. get direction vector
  force.current
    .subVectors(ref.current.position, gravityCenterVector)
    .normalize();
  // 2. get the distance to the gravity center
  const distance = ref.current.position.distanceTo(
    gravityCenterVector
  );
  // 3. get force's magnitude following a quad curve on the distance
  const forceMagnitude =
    quadOut(Math.max(1 - distance / GRAVITY_MAX_DISTANCE, 0)) *
    GRAVITY_MAX_FORCE;
  force.current.multiplyScalar(-forceMagnitude);

  // ... update the force if needed, in my case here I've a force variation logic due to pointer movement

  // Apply force
  api.applyForce(force.current.toArray(), [0, 0, 0]);
}

Here I obtain the force's magnitude in relation to the distance to the gravity center. The GRAVITY_MAX_DISTANCE is the distance in which the gravity force applied to the object is 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants