Giter Club home page Giter Club logo

use-cannon's Introduction

Build Status Discord Shield

Imgur

Monorepo for cannon-es web worker packages.

Package Description
@react-three/cannon React hooks for cannon-es. Use this in combination with react-three-fiber.
@pmndrs/cannon-worker-api Web worker api for cannon-es. Used by @react-three/cannon.
@react-three/cannon-examples Examples for @react-three/cannon

use-cannon Documentation

Please see the @react-three/cannon README documentation and getting started guide for using the react hooks and jsx interface.

Demos

Check out all of our @react-three/cannon examples at https://cannon.pmnd.rs

The code for the examples lives in ./packages/react-three-cannon-examples

use-cannon's People

Contributors

a-type avatar age2pierre avatar aunyks avatar bjornstar avatar brunnolou avatar chnicoloso avatar codynova avatar david-beale avatar dependabot[bot] avatar donalffons avatar drcmda avatar dreammonkey avatar github-actions[bot] avatar glavin001 avatar hazem3500 avatar isaac-mason avatar kbooz avatar krispya avatar marcofugaro avatar marklinovy avatar nevernotsean avatar nwpointer avatar patreeceeo avatar platane avatar skuteli avatar sniok avatar soham1803 avatar stephencorwin avatar stockhuman avatar tcannon686 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

use-cannon's Issues

Update Physics provider's default allowSleep property from true to false

I noticed that for some reason allowSleep was set to true by default, which i guess was a typo. it creates situations where objects get stuck, which are hard to explain for beginners. i think we should set them up for success. also in react it's better to always make affirmative props false by default so that the user can do:

<Physics allowSleep />

Since we're still at 0.x (experimental) i have made the change, hope it's alright, but i thought it probably won't cause breakage, the worst case is that some objects wobble around a little on the ground.

Utility to easily make "Cloth" out of an array of Particle bodies

From the Cloth demo from Cannon...

Setting up a piece of cloth involves setting up many Particle bodies and connecting each Particle to its adjacent neighbor. Would be cool to include a utility method that does this.

I have my old "useCloth.js" that I used for this demo I.
I could use some insight on where the heck I would put this. Does this belong in use-cannon at all?

presets

      <Physics
        defaultContactMaterial={{
          friction: 0.9,
          restitution: 0.7,
          contactEquationStiffness: 1e7,
          contactEquationRelaxation: 1,
          frictionEquationStiffness: 1e7,
          frictionEquationRelaxation: 2,
        }}

would it be a good idea to introduce presets for stuff like this? bouncy, crude, slippery, whatever name would make sense. for react-spring we had 4 or 5, so that users dont need to remember what damping and tension are, but here it seems even more critical, because it's probably harder to understand what these values actually mean.

Enable adding new ContactMaterial to World

Adding multiple ContactMaterials to the World is useful for unique contact equation properties between two specific Materials

const material1 = new CANNON.Material({ name: 'ElasticMaterial1', friction: 0, restitution: 1 })
const material2 = new CANNON.Material({ name: 'ElasticMaterial2', friction: 0.2, restitution: 0.9 })
const contactMaterial = new CANNON.ContactMaterial(material1, material2, {})
world.addContactMaterial(contactMaterial)
world.addBody(new CANNON.Body({
    // ...props
    material1
}))
world.addBody(new CANNON.Body({
    // ...props
    material2
}))

Invalid path to type declarations in package.json

The "types" field in package.json point to dist/types.d.ts rather than dist/index.d.ts.

Unrelated, but the type declarations for the Physics component return a React.ReactNode - but I believe it should be returning a JSX.Element.

Feature request: Reading velocity

I saw that in #31 @bvkimball asked

Also is it possible to get the velocity from the worker?

and @drcmda replied:

Reading isn't possible atm and would have to be async, you'd get a promise back.

I would like to say that I'd appreciate a reading feature very much!

Proposal: Replace api.setPosition and api.setRotation to api.set(obj)

Taking a page from RTF, making a shorthand set would have the same functionality as setting position and rotation, but open up any other property to be changed with the api too. E.g. I need to set the velocity to 0. Instead of creating new worker operators and api methods, just use { velocity: [0,0,0] } as the set parameter. Adding types to the worker may make this easier to reason about.

Will work on a PR today to try this out.

Add hook to Cannon world instance

With RTF, there is a "useThree" hook thats lets us reach into a ThreeJS instance, it would be very handy to have something similar to the Cannon world instance. We could clearForces as needed, raycast bodies and getMaterials for re-use.

Expose CannonJS Ray with hook

Ray's are used in Cannon similarly to THREE's rays, but contain special collision data when it hits. I think a "useRay" hook would be nice for this.

Add collision filter groups and masks

This will let us define certain groups of bodies and limit what groups can collide with eachother.
Cannon demo here: http://schteppe.github.io/cannon.js/demos/collisionFilter.html
Source: https://github.com/schteppe/cannon.js/blob/master/demos/collisionFilter.html

In the example, we have a scene with a box, a sphere and a cylinder, with boxes ignoring collisions with the cylinder.

Layers are defined as bitwise operations (integers with a power of two)

We could use these layers in new 'collisionFilterGroup' and 'collisionFilterMask' arguments in useBody.

In the long run, some helper methods that solve using multiple groups on a single body would be super helpful and easy to implement. This concepts are similar in Unity's "LayerMasks" class and doing checks on them involve bitwise operators, if that helps.

Create hooks and ops for adding and removing Constraints and Springs

Connecting two rigidbodies together can be done with Constraints and Springs. If I understand CANNONjs correctly, Constraints are rather rigid (a set distance apart) while Springs can stretch and expand with forces.

Currently the worker can add and remove bodies as well as initiate the world, what we should add is addConstraint, removeConstraint, addSpring, removeSpring operations which handle constraints in a similar way to bodies. Then, new useConstraint and useSpring hooks would accept two bodies as arguments (plus whatever options are needed).

This could lead to some really cool results such as physics driven Ragdolls, Rope/Cables/Hair, Cloth, Vehicle physics, etc.

Adding multiple bodies to a single mesh

For some cases attaching multiple cannon bodies to a single mesh is necessary. As of now, use-cannon only lets you pass the ref from a single mesh or an instanced mesh.

For #6 , a single THREE.PlaneBufferGeometry would get widthSegments * heightSegments CANNON.Particle bodies. For Ragdoll physics, a single THREE.SkinnedMesh would get a body for each THREE.Bone.

In both examples, bodies would change the positions of certain vertex groups.

How could we add an option to link multiple bodies to a single mesh? Similarly to how THREE.InstancedMesh is handled?

At the moment, I am creating an example that uses an extra THREE.InstancedMesh to 'trick' use-cannon into creating multiple bodies, then copying the position and rotation data over to the vertex groups.

confusing rotation param in compound shapes

When using compound bodies, the rotation param is meant to be in quaternion form.

https://github.com/react-spring/use-cannon/blob/e9712e26d6323c5a47701d465d4111d2ed5950ba/src/worker.js#L159

afaik everywhere else it is supposed to be in euler form. For example for the compound root:
https://github.com/react-spring/use-cannon/blob/e9712e26d6323c5a47701d465d4111d2ed5950ba/src/worker.js#L169

This is a bit confusing. Is it unintentional ? If so I can PR

awesome work btw ๐Ÿ‘

RFP: How should shape-specific APIs be exposed?

Some functions are specific to a shape class - for example, Cannon's ConvexPolyhedron shape has a transformAllPoints function which can be used to adjust the alignment axes for the shape. This function is useful for orienting physics bodies and meshes into the same axes.

I'm requesting proposals on how use-cannon should expose these shape-specific APIs? We can continue to add all available APIs to the object returned from useBody, but some (many?) of those will not actually be valid depending on which hook you are using.

Maybe we could have a generic API object with methods which are valid for all physics bodies, and spread spread that into a second API object that's generated based on the type of the shape (and maybe a third based on the body type if necessary)?

Collision Events

Expose collision handler. An "onCollide" argument would be easy, with the worker adding and removing the handler on mount/unmount.

Returned API incomplete? (setVelocity etc.)

Hi, I like your project a lot and currently play around with it, but now I've come across a problem.

In my little game I want to throw a ball. The "How it works" section says:

You can interact with [the object] by using the api, which lets you apply positions and rotations.

But, when I scroll down, the docs promise more:

type WorkerApi = AtomicProps & {
  position: WorkerVec
  rotation: WorkerVec
  velocity: WorkerVec
  angularVelocity: WorkerVec
  applyForce: (force: number[], worldPoint: number[]) => void
  applyImpulse: (impulse: number[], worldPoint: number[]) => void
  applyLocalForce: (force: number[], localPoint: number[]) => void
  applyLocalImpulse: (impulse: number[], localPoint: number[]) => void
}

Setting positions works perfectly, but there seems to be no e.g. setVelocity or applyImpulse. But for my use case I need these functions. (Don't I?)

Are they not implemented yet or am I missing something? (Before this project I have never done anything with React or Three.js, so sorry if my question is stupid... I use react-three-fiber and build upon Paul Henschel's pingpong mini-game.)

Thanks for your work!

Blob is not defined

When using SSR, 'Blob is not defined' error occurs. Perhaps you use blobs in the packaging, can you remove them for SSR?

Feature request: pass ref to useBody args callback

Sorry to raise another feature request - and I'm not even sure if this is a valid idea.

use-cannon has been awesome, and my rolling die react component is working really well. The current class looks something like

function Die(props) {
   const geometry = useMemo(() => (buildGeometry(props.dieType)), [props.dieType]);
   const [ref] = useConvexPolyhedron(() => ({ args: geometry }));
   return (<mesh geometry={geometry} ref={ref} />);
}

Sometimes however I want to render the dice without physics, so I figured I might have one component which is just the mesh, and wrap it with another component which has the physics. Something like

function DieObject(props) {
   const geometry = useMemo(() => (buildGeometry(props.dieType)), [props.dieType]);
   return (<mesh geometry={geometry} ref={props.physicsRef} />);
}

function Die(props) {
   const [ref] = useConvexPolyhedron(() => ({ args: /* TODO */ }));
   return (<DieObject physicsRef={ref}  {...props} />);
}

As you can see, I don't have the geometry of the mesh available to initialise the body.

However, it occurs to me that the ref function gets the the mesh object, which has access to the geometry. If the ref was passed as a parameter to the args callback (after it has been initialised), then the Die component could be

function Die(props) {
   const [ref] = useConvexPolyhedron((ref) => ({ args: ref.current.geometry }));
   return (<DieObject physicsRef={ref} {...props} />);
}

Does this seem like it would be possible? Is it a good idea?

Typescript error on import

I just included use-cannon in my project, and I'm immediately seeing a Typescript error:

TypeScript error in /path/to/node_modules/use-cannon/dist/hooks.d.ts(1,13):
'=' expected.  TS1005

  > 1 | import type { MaterialOptions, RayOptions } from 'cannon-es';
      |             ^
    2 | import type { Event } from './index';
    3 | import * as THREE from 'three';
    4 | import React from 'react';

Provide way to query if the simulation is sleeping, or add invalidateFrameloop prop

My app uses <Canvas invalidateFrameloop={true}/> in react-three-fiber to avoid rendering every frame, because most of the time the scene is static (it's a virtual gaming space for tabletop roleplaying games, and if no-one is moving anything around, there's no need to consume power by re-rendering the scene).

I'm adding physics-based dice rolling using use-cannon, but obviously when the physics simulation is running the app needs to re-render every frame. At the moment, the dice's render() methods call useFrame(({invalidate}) => {invalidate();}); so they cause the app to render every frame while they are mounted.

use-cannon defaults to useSleep={true}, so presumably when the die/dice settle, the physics simulation goes to sleep. However, I can't find a way to query the sleep state of the simulation from user-land, so my useFrame call can stop calling invalidate(). If such a getter is not available, I'd like to request that it be added (presumably to the WorkerAPI).

Given that your physics state is hidden away in the workers, it might be hard to make a getter of the sleep status available through the API. As an alternative, since invalidateFrameloop is a standard (if seldom used) feature of react-three-fiber, perhaps a similar prop could be added to <Physics/>, defaulting to false, but if true, use-cannon itself could call invalidate() each frame that the physics sim is not sleeping, and stop calling it when it sleeps.

Can't resolve 'worker_thread'

Starting from v0.45, the following error occurs during initial loading.

warn  - ./node_modules/use-cannon/dist/Provider-ff1cad56.js
Module not found: Can't resolve 'worker_threads' in './node_modules/use-cannon/dist'

PreStep support

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>
);

Improve TypeScript support

TypeScript is already supported in some capacity, and many type declarations already exist. However there is room for improvement and an even better developer experience. ๐Ÿ˜บ

Convert the webworker to TypeScript and improve typings across all modules (minimize type assertions, improve event types with discriminated unions, etc.)

Implement Compound collider bodies

From the example here: http://schteppe.github.io/cannon.js/demos/compound.html

A Compound shape is a shape built out of other shapes called child-shapes.
You can see it as a holder of a group of other shapes.
Use the compound shape to build rigid bodies that have more complex geometry.
For example, you can build concave shapes. When a child shape is added to
the Compound shape, a transform consisting of a position and a quaternion is
needed. This enables you to add child shapes at any position, rotated however
you like inside the local coordinate system of the Compound shape.

This might be best suited for 2.0

Add ability to debug physics bodies with wireframes

I laid the groundwork for the ability to debug most types of physics bodies with wireframes in commit 7f8ce66. This was based on schteppe's original CannonDebugRenderer and my earlier rough pass in TS. I haven't tested this code at all, or seen it working - but my previous TS version works great for all the shapes that I have tested.

@drcmda This code requires references to all of the bodies in the Cannon.World on initialization. It should also be possible to add the option for individual wireframes to each of the shape hooks - although I would want to discuss the api. I'm wondering what is the most ergonomic way to retrieve the bodies from the worker?

Can't pass instanced bodies to useConstraint

Creating constraints between instanced meshes isn't possible at the moment.

From #48 @drcmda

we could maybe learn from react-springs playbook here, esp useSprings: https://www.react-spring.io/docs/hooks/use-springs

const [refs, api] = useDistanceConstraints(10000, () => ({ ... }))
return data.map((id, index) => <mesh key={id} ref={refs[index]} ... />

I think this would be a good pattern for constraints on instanced bodies. An iterator function that returns an array of two indexes could attach a standard mesh to instanced meshes or instanced mesh to instanced mesh.

const [bodyA] = useBox({...})
const [bodyB] = useSphere({...}) // ref for instancedMesh

useDistanceConstraints(count, bodyA, bodyB, fn: (i) => [0, i], options, deps]) // where fn returns [bodyAIndex, bodyBIndex]

ForwardRef and body hooks

What's the best practice when a component with forwardRef needs to use a body hook like useBox?

const` Model = forwardRef((props, ref) => {
  // ...
  const [cannonRef, api] = useBox(() => ({ mass: 1 }));
  // ...

  // How can I use cannonRef while I need to use ref coming from forwardRef?
  
  return (
    <mesh ref={ref}>
      {/* ... */}
    </mesh>
  );
});

Is there a way to pass an initial ref to useBox()?

eg.

const [cannonRef, api] = useBox(() => ({ mass: 1, ref }));

Option to set Cannon body to "Kinematic"

In PHYSX and Unity, rigid bodies have an option called "isKinematic".

From the PhysX docs:
https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/RigidBodyDynamics.html#kinematic-actors

Each simulation step PhysX moves the actor to its target position, regardless of external forces, gravity, collision, etc. The actor will appear to have infinite mass and will push regular dynamic actors out of the way.

Example use case: I have a sphere that I want to animate with an animation loop (e.g. move position) and push away a bunch of boxes. Trying to do so with a Cannon body will mean the animation may be fighting against other forces. Turning off the Cannon Body would turn off the collisions. Setting a parameter such as isKinematic to true would solve both problems.

Does anyone else think this would be a good addition?

Update useBox args to use extents instead of halfExtents

i think it's a terrible idea to deviate from args in general, the api could be so easy to use and understand, but by throwing in wrenches like that we make it hard for beginners.

i went ahead and made it full extents, so that the mesh and the cannon-box can share the same args. ideally this would come from cannon-es, though.

implement RaycastVehicle

I'd like to know if there are plans to implement cannon's RaycastVehicle in this library ?
Maybe there is someone already working on it? I guess it would be an awesome feature ...

Great work BTW !

Maybe an onCollide event bug?

I think there is a bug in related to onCollide event.

The collision between two bodies works perfectly, the same can be said for the collisionFilters, but the onCollide event always returns as body and target the same object.
The same obviously applies to the collisionFilters of the event, filtergroup and filtermask of body and target are always the same.

In particular:

  • bodyA collides with bodyB
  • onCollide event of bodyA has body = target = bodyA
  • onCollide event of bodyB has body = target = bodyB

Questions: How much should worker handle CANNON related tasks?

This is an open question, I'm looking for a better understanding on everyones opinions on the worker. Should the worker behave as an automated creator of all the CANNON related classes other than just the bodies? Or should those class instances be the responsibility of the React component?

For instance, another class from Cannon is a physics material that can be customized to have different friction/slippery-ness. The way I see it, adding this ability could be either:

A) I am able to use a hook (i.e. useMaterial) in my component which 1. creates a new Cannon material, 2. adds it to the world list of materials then 3. applies that material to the specified body. The benefit here is that the developer doesn't have to mess with any Cannon classes, just the hooks.

B) In my project, I create a Cannon Material that adds itself to the Cannon world on init. Then in my component, I refer to that Cannon Material when creating a new Body. The benefit here is that I can create Materials in a separate file and refer to it in the world material list for re-use.

Some other classes would be Springs, Constraints, and ContactMaterials.

I'm just open to discussion and hearing what you guys think.
I think option B would be ready with #15, but option A would take managing of these lists off of the developer.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.