Skip to content

Commit

Permalink
Kinematic rigid bodies
Browse files Browse the repository at this point in the history
  • Loading branch information
bbupton committed Aug 8, 2023
1 parent 31ee1fa commit e92cd1d
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 29 deletions.
106 changes: 90 additions & 16 deletions examples/physics/src/Models.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { ModelRoot, Actor, mix, AM_Spatial, sphericalRandom, v3_scale, v3_add, v3_sub, v3_normalize} from "@croquet/worldcore";
import { RAPIER, RapierManager, AM_RapierWorld, AM_RapierRigidBody} from "@croquet/worldcore-rapier";

import { SprayPawn, FountainPawn } from "./Views";
// import { SprayPawn, FountainPawn } from "./Views";

function rgb(r, g, b) {
return [r/255, g/255, b/255];
Expand All @@ -14,7 +14,7 @@ function rgb(r, g, b) {
//------------------------------------------------------------------------------------------

class SprayActor extends mix(Actor).with(AM_Spatial, AM_RapierRigidBody) {
get pawn() {return SprayPawn}
get pawn() {return "SprayPawn"}

get shape() {return this._shape || "cube"}
get index() { return this._index || 0 }
Expand All @@ -29,23 +29,23 @@ class SprayActor extends mix(Actor).with(AM_Spatial, AM_RapierRigidBody) {

buildCollider() {
let cd;
switch(this.shape) {
switch (this.shape) {
case "cone":
cd = RAPIER.ColliderDesc.cone(0.5, 0.5);
cd.setDensity(4)
cd.setDensity(4);
break;
case "ball":
cd = RAPIER.ColliderDesc.ball(0.5);
cd.setDensity(2)
cd.setDensity(2);
break;
case "cylinder":
cd = RAPIER.ColliderDesc.cylinder(0.5, 0.5);
cd.setDensity(1.5)
cd.setDensity(1.5);
break;
case"cube":
case "cube":
default:
cd = RAPIER.ColliderDesc.cuboid(0.5, 0.5, 0.5);
cd.setDensity(1)
cd.setDensity(1);
break;
}

Expand All @@ -56,14 +56,88 @@ class SprayActor extends mix(Actor).with(AM_Spatial, AM_RapierRigidBody) {
}
SprayActor.register('SprayActor');

//------------------------------------------------------------------------------------------
//-- BlockActor ----------------------------------------------------------------------------
//------------------------------------------------------------------------------------------

class BlockActor extends mix(Actor).with(AM_Spatial, AM_RapierRigidBody) {

get pawn() {return "SprayPawn"}

get shape() {return this._shape || "cube"}
get index() { return this._index || 0 }

init(options) {
super.init(options);

this.buildCollider();

this.subscribe("input", "zDown", this.goLeft);
this.subscribe("input", "xDown", this.goRight);
}

buildCollider() {
let cd;
switch (this.shape) {
case "cone":
cd = RAPIER.ColliderDesc.cone(0.5, 0.5);
cd.setDensity(4);
break;
case "ball":
cd = RAPIER.ColliderDesc.ball(0.5);
cd.setDensity(2);
break;
case "cylinder":
cd = RAPIER.ColliderDesc.cylinder(0.5, 0.5);
cd.setDensity(1.5);
break;
case "cube":
default:
cd = RAPIER.ColliderDesc.cuboid(0.5, 0.5, 0.5);
cd.setDensity(1);
break;
}

this.createCollider(cd);

}

// init(options) {
// super.init(options);

// console.log("new block");

// this.subscribe("input", "zDown", this.goLeft);
// this.subscribe("input", "xDown", this.goRight);
// }

goLeft() {
console.log("left");
const translation = [...this.translation];
translation[0] -= 0.1;
this.set({translation});
}

goRight() {
console.log("right");
const translation = [...this.translation];
translation[0] += 0.1;
this.set({translation});
}

}
BlockActor.register('BlockActor');



//------------------------------------------------------------------------------------------
//-- FountainActor ------------------------------------------------------------------------
//------------------------------------------------------------------------------------------

// class TestActor extends mix(Actor).with(AM_Spatial) {}

class FountainActor extends mix(Actor).with(AM_Spatial, AM_RapierWorld, AM_RapierRigidBody) {
get pawn() {return FountainPawn}
get pawn() {return "FountainPawn"}

init(options) {
super.init(options);
Expand All @@ -90,20 +164,20 @@ class FountainActor extends mix(Actor).with(AM_Spatial, AM_RapierWorld, AM_Rapie
cd.translation = new RAPIER.Vector3(0,0,-24);
this.createCollider(cd);

this.subscribe("ui", "shoot", this.doShoot)
this.subscribe("ui", "shoot", this.doShoot);

this.future(1000).spray();
}

get max() { return this._max || 50};
get max() { return this._max || 50}

spray() {
this.spawn();
if (!this.doomed) this.future(300).spray();
}

spawn() {
const type = this.random()
const type = this.random();
let shape = "cube";

if (type > 0.4) shape = "cylinder";
Expand All @@ -121,10 +195,10 @@ class FountainActor extends mix(Actor).with(AM_Spatial, AM_RapierWorld, AM_Rapie
}

doShoot(gun) {
const aim = v3_normalize(v3_sub([0,15,0], gun))
const aim = v3_normalize(v3_sub([0,15,0], gun));
const shape = "cube";
const index = Math.floor(this.random()*20);
const translation = v3_add(gun, [0,0,0])
const translation = v3_add(gun, [0,0,0]);
const bullet = SprayActor.create({parent: this, shape, index, translation, rigidBodyType: "dynamic"});
const force = v3_scale(aim, 40);
const spin = v3_scale(sphericalRandom(),Math.random() * 0.5);
Expand All @@ -151,9 +225,9 @@ export class MyModelRoot extends ModelRoot {
console.log("Start root model!!");
this.seedColors();

console.log(RapierManager);
this.fountain = FountainActor.create({gravity: [0,-9.8,0], timestep:50, translation: [0,0,0], max: 200, rigidBodyType: "static"});

this.fountain = FountainActor.create({gravity: [0,-9.8,0], timestep:15, translation: [0,0,0], max: 200, rigidBodyType: "static"});
this.block = BlockActor.create({parent: this.fountain, translation: [0,1,5], rigidBodyType: "kinematic", index: 2});
}

seedColors() {
Expand Down
9 changes: 5 additions & 4 deletions examples/physics/src/Views.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class SprayPawn extends mix(Pawn).with(PM_Smoothed, PM_ThreeInstanced) {
this.useInstance(this.actor.shape + this.actor.index);
}
}
SprayPawn.register("SprayPawn");

//------------------------------------------------------------------------------------------
//-- FountainPawn -------------------------------------------------------------------------
Expand Down Expand Up @@ -58,6 +59,7 @@ export class FountainPawn extends mix(Pawn).with(PM_Spatial, PM_ThreeVisible) {
this.setRenderObject(group);
}
}
FountainPawn.register("FountainPawn");

//------------------------------------------------------------------------------------------
//-- GodView -------------------------------------------------------------------------------
Expand All @@ -80,13 +82,12 @@ class GodView extends ViewService {
this.subscribe("input", "pointerDelta", this.doPointerDelta);
}


updateCamera() {
if (this.paused) return;
const rm = this.service("ThreeRenderManager");

const pitchMatrix = m4_rotation([1,0,0], pitch)
const yawMatrix = m4_rotation([0,1,0], yaw)
const pitchMatrix = m4_rotation([1,0,0], pitch);
const yawMatrix = m4_rotation([0,1,0], yaw);

let cameraMatrix = m4_translation([0,0,50]);
cameraMatrix = m4_multiply(cameraMatrix,pitchMatrix);
Expand Down Expand Up @@ -122,7 +123,7 @@ class GodView extends ViewService {
if (this.paused) return;
if (!this.dragging) return;
yaw += -0.01 * e.xy[0];
yaw = yaw % TAU;
yaw %= TAU;
pitch += -0.01 * e.xy[1];
pitch = Math.min(pitch, toRad(-15));
pitch = Math.max(pitch, toRad(-90));
Expand Down
29 changes: 20 additions & 9 deletions packages/rapier/src/Rapier.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export const AM_RapierWorld = superclass => class extends superclass {
this.world.free();
}

get timeStep() {return this._timeStep || 50;}
get gravity() {return this._gravity || [0,-9.8,0];}
get timeStep() {return this._timeStep || 50}
get gravity() {return this._gravity || [0,-9.8,0]}

createRigidBody(actor, rbd) {
const rb = this.world.createRigidBody(rbd);
Expand Down Expand Up @@ -131,9 +131,10 @@ export const AM_RapierRigidBody = superclass => class extends superclass {

let rbd;
switch (this.rigidBodyType) {
default:
case "dynamic": rbd = RAPIER.RigidBodyDesc.newDynamic(); break;
case "static": rbd = RAPIER.RigidBodyDesc.newStatic(); break;
case "dynamic":
default: rbd = RAPIER.RigidBodyDesc.newDynamic();
case "kinematic": rbd = RAPIER.RigidBodyDesc.newKinematicPositionBased(); break;
}
rbd.setCcdEnabled(this.ccdEnabled);
rbd.translation = new RAPIER.Vector3(...this.translation);
Expand All @@ -147,17 +148,27 @@ export const AM_RapierRigidBody = superclass => class extends superclass {
this.worldActor.destroyRigidBody(this.rigidBodyHandle);
}

get rigidBodyType() { return this._rigidBodyType || "dynamic";}
get ccdEnabled() { return this._ccdEnabled === undefined ? true : this._ccdEnabled; }
get velocity() { return this._velocity || [0,0,0];}
get acceleration() { return this._acceleration || [0,0,0];}
get hasAccelerometer() { return this._hasAccelerometer;}
get rigidBodyType() { return this._rigidBodyType || "dynamic"}
get ccdEnabled() { return this._ccdEnabled === undefined ? true : this._ccdEnabled }
get velocity() { return this._velocity || [0,0,0]}
get acceleration() { return this._acceleration || [0,0,0]}
get hasAccelerometer() { return this._hasAccelerometer}

get rigidBody() {
if (!this.worldActor) return null;
if (!this.$rigidBody) this.$rigidBody = this.worldActor.getRigidBody(this.rigidBodyHandle);
return this.$rigidBody;
}

translationSet() {
if (this.rigidBodyType !== "kinematic") return;
if (this.rigidBody) this.rigidBody.setNextKinematicTranslation(new RAPIER.Vector3(...this.translation));
}
rotationSet() {
if (this.rigidBodyType !== "kinematic") return;
if (this.rigidBody) this.rigidBody.setNextKinematicRotation(new RAPIER.Vector3(...this.rotation));
}

getWorldActor() {
let actor = this;
do {
Expand Down

0 comments on commit e92cd1d

Please sign in to comment.