Skip to content

Instantly share code, notes, and snippets.

@Sumechoo
Created July 12, 2021 08:40
Show Gist options
  • Save Sumechoo/4c6515d8825c2b7e0bb8e8c1619657fa to your computer and use it in GitHub Desktop.
Save Sumechoo/4c6515d8825c2b7e0bb8e8c1619657fa to your computer and use it in GitHub Desktop.
import { createContext, FC, useEffect, useState } from "react";
import Ammo from 'ammojs-typed';
import * as THREE from 'three';
import { useFrame } from "@react-three/fiber";
const clock = new THREE.Clock(true);
const createWorld = async () => {
const api = await Ammo();
const collisionConfiguration = new api.btDefaultCollisionConfiguration();
const dispatcher = new api.btCollisionDispatcher( collisionConfiguration );
const broadphase = new api.btDbvtBroadphase();
const solver = new api.btSequentialImpulseConstraintSolver();
const world = new api.btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
world.setGravity( new api.btVector3( 0, -9.82, 0 ) );
console.info('creating world');
return world;
}
interface AmmoContextValue {
world: Ammo.btDiscreteDynamicsWorld;
}
export const AmmoPhysicsContext = createContext<null | AmmoContextValue>(null);
export const AmmoPhysics: FC = ({ children }) => {
const [contextValue, setContextValue] = useState<AmmoContextValue | null>(null);
useFrame(() => {
if (contextValue) {
contextValue.world.stepSimulation(clock.getDelta(), 10);
}
})
useEffect(() => {
createWorld()
.then((world) => {
setContextValue({world});
});
}, []);
if (!contextValue) {
return null;
}
return (
<AmmoPhysicsContext.Provider value={contextValue}>
{children}
</AmmoPhysicsContext.Provider>
);
}
import { GameInstance } from "../../core/types";
import { AmmoPhysics } from "../../core/Ammo/AmmoPhysics";
import { FC } from "react";
import { useRigidbody } from "../../core/Ammo/hooks/useRigidbody";
const AmmoCube: FC = () => {
const [ref] = useRigidbody();
return (
<mesh
ref={ref}
>
<boxGeometry />
<meshBasicMaterial color='red' />
</mesh>
)
}
export const AmmoPlayground: GameInstance = {
Ui: () => null,
Game: () => {
return (
<AmmoPhysics>
<AmmoCube />
<AmmoCube />
</AmmoPhysics>
)
}
}
import { useFrame } from "@react-three/fiber";
import { useContext, useEffect, useRef, useState } from "react"
import * as THREE from 'three';
import Ammo from 'ammojs-typed';
import { AmmoPhysicsContext } from "../AmmoPhysics";
export const useRigidbody = () => {
const ref = useRef(new THREE.Object3D());
const [rbReference, setRbReference] = useState<Ammo.btRigidBody | null>(null);
const context = useContext(AmmoPhysicsContext);
useFrame(() => {
const motionState = rbReference?.getMotionState();
if (motionState) {
Ammo().then((api) => {
let TRANSFORM_AUX = new api.btTransform();
motionState.getWorldTransform(TRANSFORM_AUX);
var p = TRANSFORM_AUX.getOrigin();
var q = TRANSFORM_AUX.getRotation();
ref.current.position.set(p.x(), p.y(), p.z());
});
}
});
useEffect(() => {
if (rbReference === null && context) {
Ammo().then((api) => {
const mass = 1;
const tempVec = new api.btVector3(2,2,2);
const geometry = new api.btBoxShape(tempVec);
const transform = new api.btTransform();
transform.setIdentity();
transform.setOrigin(new api.btVector3(0,10,0));
transform.setRotation(new api.btQuaternion(0,0,0,0));
const motionState = new api.btDefaultMotionState(transform);
const localInertia = new api.btVector3(0,0,0);
geometry.calculateLocalInertia(mass, localInertia);
const rbConstructionInfo = new api.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
const rigidbody = new api.btRigidBody(rbConstructionInfo);
rigidbody.setActivationState(4);
rigidbody.setFriction(1);
rigidbody.setLinearVelocity(new api.btVector3(1,0,0));
context.world.addRigidBody(rigidbody);
setRbReference(rigidbody);
console.info('creating and adding rigidbody here', rigidbody);
});
}
}, [context, rbReference]);
return [ref];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment