29
loading...
This website collects cookies to deliver better user experience
scene.useRightHandedSystem
, but not after struggling with negative scaling due to coordinate conversions. In the end, I tag meshes in Blender with an object name and custom properties, export the scene to a gltf binary format with metadata, and then import the scene with a little loop to automatically attach physics to each node.const rightController = useController("right");
const [sphereRef, sphereApi] = useSphere(() => ({
mass: 0,
args: 0.1,
position: [-2, 1, -10],
}));
useFrame(({ clock }) => {
const { position, rotation } = rightController.grip;
sphereApi.position.set(position.x, position.y, position.z);
sphereApi.rotation.set(rotation.x, rotation.y, rotation.z);
})
const [boxRef, boxApi] = useBox(() => ({
mass: 0.01,
args: [0.1, 0.1, 0.1],
position: [2, 1, -10]
}));
useLockConstraint(sphereRef, boxRef);
// When grabbed
ball.setParent(controller.grip);
// When released
ball.setParent(null);
ball.physicsImposter = new PhysicsImposter(...);
ball.physicsImposter.setLinearVelocity(controllerImposter.getLinearVelocity());
const v = controllerImposter.getLinearVelocity();
const w = controllerImposter.getAngularVelocity();
const r = ball.position.subtract(controllerImposter.getObjectCenter());
ball.physicsImpostor.setLinearVelocity(v.add(w.cross(r)));
ball.physicsImpostor.setAngularVelocity(w);
// Initial frame
let lv = new Vector3(0, 0, 0);
const factor = 0.8;
// Every frame
const cv = controllerImposter.getLinearVelocity();
lv = lv + factor * (cv - lv);
function linearRegressionQuadratic(positions: number[][], frametimes: number[]): number[][] {
const X = frametimes.map((t) => [1, t, t * t]);
const Xt = math.transpose(X);
const theta = math.multiply(math.multiply(math.inv(math.multiply(Xt, X)), Xt), positions);
return theta;
}
// positions and frametimes are recorded in a circular buffer
const theta = linearRegressionQuadratic(positions, frametimes);
// the trendline is then expressed as follows
position = theta[0] + theta[1]*t + theta[2]*t*t
theta
is the velocity at t=0
, this means that I can center the entries of frametimes
around the last frame time (the moment of release) and read the velocity directly from theta[1]
, awesome!onst [vx, vy, vz] = theta[1];
const linearVelocity = new Vector3(vx, vy, vz);
ball.physicsImpostor.setLinearVelocity(linearVelocity);
ball.physicsImpostor.setAngularVelocity(controllerImposter.getAngularVelocity());
29