React hooks for p2-es. Use this in combination with react-three-fiber.
Check out all of our examples at https://p2.pmnd.rs (coming soon)
Meanwhile look at the examples living in ./examples
import { Physics, useBox, ... } from '@react-three/p2'
1
for top-down and 2
for side-scroller like apps.<Physics normalIndex={2}>{/* Physics related objects in here please */}</Physics>
const [ref, api] = useBox(() => ({ mass: 1 }))
<mesh ref={ref} geometry={...} material={...} />
useFrame(({ clock }) => api.position.set(Math.sin(clock.getElapsedTime()) * 5, 0))
const velocity = useRef([0, 0]) useEffect(() => { const unsubscribe = api.velocity.subscribe((v) => (velocity.current = v)) return unsubscribe }, [])
Let's make a ball falling onto a box.
import { Canvas } from '@react-three/fiber' import { Physics, useBox, useCircle } from '@react-three/p2' function Box() { const [ref] = useBox(() => ({ mass: 0, position: [0, -2] })) return ( <mesh ref={ref}> <boxGeometry /> </mesh> ) } function Ball() { const [ref] = useCircle(() => ({ mass: 1, position: [0, 2] })) return ( <mesh ref={ref}> <sphereGeometry /> </mesh> ) } ReactDOM.render( <Canvas> <Physics normalIndex={2}> <Box /> <Ball /> </Physics> </Canvas>, document.getElementById('root'), )
You can debug your scene using the p2-es-debugger
. This will show you how p2 "sees" your scene. Don't forget to tell both the same normalIndex.
import { Physics, Debug } from '@react-three/cannon' ReactDOM.render( <Canvas> <Physics normalIndex={2}> <Debug color="black" scale={1.1} linewidth={0.01} normalIndex={2}> {/* children */} </Debug> </Physics> </Canvas>, document.getElementById('root'), )
function Physics({ allowSleep = false, axisIndex = 0, normalIndex = 0, broadphase = 'Naive', children, defaultContactMaterial = { contactEquationStiffness: 1e6 }, gravity = [0, -9.81, 0], isPaused = false, iterations = 5, maxSubSteps = 10, quatNormalizeFast = false, quatNormalizeSkip = 0, shouldInvalidate = true, // Maximum amount of physics objects inside your scene // Lower this value to save memory, increase if 1000 isn't enough size = 1000, solver = 'GS', stepSize = 1 / 60, tolerance = 0.001, }: React.PropsWithChildren<ProviderProps>): JSX.Element function Debug({ color = 'black', scale = 1 }: DebugProps): JSX.Element function usePlane( fn: GetByIndex<PlaneProps>, fwdRef?: React.Ref<THREE.Object3D>, deps?: React.DependencyList, ): Api function useBox( fn: GetByIndex<BoxProps>, fwdRef?: React.Ref<THREE.Object3D>, deps?: React.DependencyList, ): Api function useCircle( fn: GetByIndex<CylinderProps>, fwdRef?: React.Ref<THREE.Object3D>, deps?: React.DependencyList, ): Api function useTopDownVehicle( fn: () => RaycastVehicleProps, fwdRef?: React.Ref<THREE.Object3D>, deps: React.DependencyList[] = [], ): [React.RefObject<THREE.Object3D>, RaycastVehiclePublicApi] function useRaycastClosest( options: RayOptions, callback: (e: RayhitEvent) => void, deps: React.DependencyList = [], ): void function useRaycastAny( options: RayOptions, callback: (e: RayhitEvent) => void, deps: React.DependencyList = [], ): void function useRaycastAll( options: RayOptions, callback: (e: RayhitEvent) => void, deps: React.DependencyList = [], ): void
type WorkerApi = { [K in AtomicName]: AtomicApi<K> } & { [K in VectorName]: VectorApi } & { applyForce: (force: Triplet, worldPoint: Triplet) => void applyImpulse: (impulse: Triplet, worldPoint: Triplet) => void applyLocalForce: (force: Triplet, localPoint: Triplet) => void applyLocalImpulse: (impulse: Triplet, localPoint: Triplet) => void applyTorque: (torque: Triplet) => void quaternion: QuaternionApi rotation: VectorApi sleep: () => void wakeUp: () => void } interface PublicApi extends WorkerApi { at: (index: number) => WorkerApi } type Api = [React.RefObject<THREE.Object3D>, PublicApi] type AtomicName = | 'allowSleep' | 'angularDamping' | 'collisionGroup' | 'collisionMask' | 'collisionResponse' | 'fixedRotation' | 'isTrigger' | 'linearDamping' | 'mass' | 'material' | 'sleepSpeedLimit' | 'sleepTimeLimit' | 'userData' type AtomicApi<K extends AtomicName> = { set: (value: AtomicProps[K]) => void subscribe: (callback: (value: AtomicProps[K]) => void) => () => void } type QuaternionApi = { set: (x: number, y: number, z: number, w: number) => void copy: ({ w, x, y, z }: Quaternion) => void subscribe: (callback: (value: Quad) => void) => () => void } type VectorName = 'angularFactor' | 'angularVelocity' | 'linearFactor' | 'position' | 'velocity' type VectorApi = { set: (x: number, y: number, z: number) => void copy: ({ x, y, z }: Vector3 | Euler) => void subscribe: (callback: (value: Triplet) => void) => () => void } type ConstraintApi = [ React.RefObject<THREE.Object3D>, React.RefObject<THREE.Object3D>, { enable: () => void disable: () => void }, ] type HingeConstraintApi = [ React.RefObject<THREE.Object3D>, React.RefObject<THREE.Object3D>, { enable: () => void disable: () => void enableMotor: () => void disableMotor: () => void setMotorSpeed: (value: number) => void setMotorMaxForce: (value: number) => void }, ] type SpringApi = [ React.RefObject<THREE.Object3D>, React.RefObject<THREE.Object3D>, { setStiffness: (value: number) => void setRestLength: (value: number) => void setDamping: (value: number) => void }, ] interface RaycastVehiclePublicApi { applyEngineForce: (value: number, wheelIndex: number) => void setBrake: (brake: number, wheelIndex: number) => void setSteeringValue: (value: number, wheelIndex: number) => void sliding: { subscribe: (callback: (sliding: boolean) => void) => void } }
type InitProps = { allowSleep?: boolean axisIndex?: number broadphase?: Broadphase defaultContactMaterial?: { friction?: number restitution?: number contactEquationStiffness?: number contactEquationRelaxation?: number frictionEquationStiffness?: number frictionEquationRelaxation?: number } gravity?: Duplet iterations?: number normalIndex?: number quatNormalizeFast?: boolean quatNormalizeSkip?: number solver?: Solver tolerance?: number } export type ProviderProps = InitProps & { isPaused?: boolean maxSubSteps?: number shouldInvalidate?: boolean size?: number stepSize?: number } type AtomicProps = { allowSleep: boolean angularDamping: number collisionFilterGroup: number collisionFilterMask: number collisionResponse: number fixedRotation: boolean isTrigger: boolean linearDamping: number mass: number material: MaterialOptions sleepSpeedLimit: number sleepTimeLimit: number userData: {} } type Broadphase = 'Naive' | 'SAP' type Triplet = [x: number, y: number, z: number] type Quad = [x: number, y: number, z: number, w: number] type VectorProps = Record<VectorName, Triplet> type BodyProps<T extends any[] = unknown[]> = Partial<AtomicProps> & Partial<VectorProps> & { args?: T onCollide?: (e: CollideEvent) => void onCollideBegin?: (e: CollideBeginEvent) => void onCollideEnd?: (e: CollideEndEvent) => void quaternion?: Quad rotation?: Triplet type?: 'Dynamic' | 'Static' | 'Kinematic' } type Event = RayhitEvent | CollideEvent | CollideBeginEvent | CollideEndEvent type CollideEvent = { op: string type: 'collide' body: THREE.Object3D target: THREE.Object3D contact: { // the world position of the point of contact contactPoint: number[] // the normal of the collision on the surface of // the colliding body contactNormal: number[] // velocity of impact along the contact normal impactVelocity: number // a unique ID for each contact event id: string // these are lower-level properties from cannon: // bi: one of the bodies involved in contact bi: THREE.Object3D // bj: the other body involved in contact bj: THREE.Object3D // ni: normal of contact relative to bi ni: number[] // ri: the point of contact relative to bi ri: number[] // rj: the point of contact relative to bj rj: number[] } collisionFilters: { bodyFilterGroup: number bodyFilterMask: number targetFilterGroup: number targetFilterMask: number } } type CollideBeginEvent = { op: 'event' type: 'collideBegin' target: Object3D body: Object3D } type CollideEndEvent = { op: 'event' type: 'collideEnd' target: Object3D body: Object3D } type RayhitEvent = { op: string type: 'rayhit' body: THREE.Object3D target: THREE.Object3D } type CylinderArgs = [radiusTop?: number, radiusBottom?: number, height?: number, numSegments?: number] type SphereArgs = [radius: number] type TrimeshArgs = [vertices: ArrayLike<number>, indices: ArrayLike<number>] type HeightfieldArgs = [ data: number[][], options: { elementSize?: number; maxValue?: number; minValue?: number }, ] type ConvexPolyhedronArgs<V extends VectorTypes = VectorTypes> = [ vertices?: V[], faces?: number[][], normals?: V[], axes?: V[], boundingSphereRadius?: number, ] interface PlaneProps extends BodyProps {} interface BoxProps extends BodyProps<Triplet> {} // extents: [x, y, z] interface CylinderProps extends BodyProps<CylinderArgs> {} interface ParticleProps extends BodyProps {} interface SphereProps extends BodyProps<SphereArgs> {} interface TrimeshProps extends BodyPropsArgsRequired<TrimeshArgs> {} interface HeightfieldProps extends BodyPropsArgsRequired<HeightfieldArgs> {} interface ConvexPolyhedronProps extends BodyProps<ConvexPolyhedronArgs> {} interface CompoundBodyProps extends BodyProps { shapes: BodyProps & { type: ShapeType }[] } interface ConstraintOptns { maxForce?: number collideConnected?: boolean wakeUpBodies?: boolean } interface PointToPointConstraintOpts extends ConstraintOptns { pivotA: Triplet pivotB: Triplet } interface ConeTwistConstraintOpts extends ConstraintOptns { pivotA?: Triplet axisA?: Triplet pivotB?: Triplet axisB?: Triplet angle?: number twistAngle?: number } interface DistanceConstraintOpts extends ConstraintOptns { distance?: number } interface HingeConstraintOpts extends ConstraintOptns { pivotA?: Triplet axisA?: Triplet pivotB?: Triplet axisB?: Triplet } interface LockConstraintOpts extends ConstraintOptns {} interface SpringOptns { restLength?: number stiffness?: number damping?: number worldAnchorA?: Triplet worldAnchorB?: Triplet localAnchorA?: Triplet localAnchorB?: Triplet } interface WheelInfoOptions { radius?: number directionLocal?: Triplet suspensionStiffness?: number suspensionRestLength?: number maxSuspensionForce?: number maxSuspensionTravel?: number dampingRelaxation?: number dampingCompression?: number frictionSlip?: number rollInfluence?: number axleLocal?: Triplet chassisConnectionPointLocal?: Triplet isFrontWheel?: boolean useCustomSlidingRotationalSpeed?: boolean customSlidingRotationalSpeed?: number } interface RaycastVehicleProps { chassisBody: React.Ref<THREE.Object3D> wheels: React.Ref<THREE.Object3D>[] wheelInfos: WheelInfoOptions[] indexForwardAxis?: number indexRightAxis?: number indexUpAxis?: number }
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4