Skip to content

Commit

Permalink
[kinematic-body] Stabilize.
Browse files Browse the repository at this point in the history
Fixes #225, with various caveats.
  • Loading branch information
donmccurdy committed Nov 23, 2018
1 parent d079064 commit 2f5a652
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 25 deletions.
2 changes: 1 addition & 1 deletion examples/platforms/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<!-- Player -->
<a-entity id="rig"
movement-controls
kinematic-body
kinematic-body="enableJumps: true"
position="15 0 10"
jump-ability="maxJumps: 3;
distance: 10;">
Expand Down
35 changes: 11 additions & 24 deletions src/misc/kinematic-body.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
schema: {
mass: { default: 5 },
radius: { default: 1.3 },
userHeight: { default: 1.6 },
linearDamping: { default: 0.05 },
enableSlopes: { default: true }
enableSlopes: { default: true },
enableJumps: { default: false },
},

/*******************************************************************
Expand All @@ -43,7 +43,7 @@ module.exports = AFRAME.registerComponent('kinematic-body', {

const el = this.el,
data = this.data,
position = (new CANNON.Vec3()).copy(el.getAttribute('position'));
position = (new CANNON.Vec3()).copy(el.object3D.getWorldPosition(new THREE.Vector3()));

this.body = new CANNON.Body({
material: this.system.getMaterial('staticMaterial'),
Expand All @@ -54,7 +54,7 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
});
this.body.addShape(
new CANNON.Sphere(data.radius),
new CANNON.Vec3(0, data.radius - data.height, 0)
new CANNON.Vec3(0, data.radius, 0)
);

this.body.el = this.el;
Expand Down Expand Up @@ -90,15 +90,15 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
if (!dt) return;

const el = this.el;
const data = this.data
const body = this.body;

body.velocity.copy(el.getAttribute('velocity'));
if (!data.enableJumps) body.velocity.set(0, 0, 0);
body.position.copy(el.getAttribute('position'));
body.position.y += this.data.userHeight;
},

step: (function () {
var velocity = new THREE.Vector3(),
const velocity = new THREE.Vector3(),
normalizedVelocity = new THREE.Vector3(),
currentSurfaceNormal = new THREE.Vector3(),
groundNormal = new THREE.Vector3();
Expand Down Expand Up @@ -137,7 +137,7 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
// 2. If current trajectory attempts to move _through_ another
// object, project the velocity against the collision plane to
// prevent passing through.
velocity = velocity.projectOnPlane(currentSurfaceNormal);
velocity.projectOnPlane(currentSurfaceNormal);
} else if (currentSurfaceNormal.y > 0.5) {
// 3. If in contact with something roughly horizontal (+/- 45º) then
// consider that the current ground. Only the highest qualifying
Expand All @@ -154,7 +154,7 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
}

normalizedVelocity.copy(velocity).normalize();
if (groundBody && normalizedVelocity.y < 0.5) {
if (groundBody && (!data.enableJumps || normalizedVelocity.y < 0.5)) {
if (!data.enableSlopes) {
groundNormal.set(0, 1, 0);
} else if (groundNormal.y < 1 - EPS) {
Expand All @@ -163,28 +163,16 @@ module.exports = AFRAME.registerComponent('kinematic-body', {

// 4. Project trajectory onto the top-most ground object, unless
// trajectory is > 45º.
velocity = velocity.projectOnPlane(groundNormal);
velocity.projectOnPlane(groundNormal);

} else if (this.system.driver.world) {
// 5. If not in contact with anything horizontal, apply world gravity.
// TODO - Why is the 4x scalar necessary.
// NOTE: Does not work if physics runs on a worker.
velocity.add(this.system.driver.world.gravity.scale(dt * 4.0 / 1000));
}

// 6. If the ground surface has a velocity, apply it directly to current
// position, not velocity, to preserve relative velocity.
if (groundBody && groundBody.el && groundBody.el.components.velocity) {
const groundVelocity = groundBody.el.getAttribute('velocity');
body.position.copy({
x: body.position.x + groundVelocity.x * dt / 1000,
y: body.position.y + groundVelocity.y * dt / 1000,
z: body.position.z + groundVelocity.z * dt / 1000
});
}

body.velocity.copy(velocity);

body.position.y -= data.userHeight;
this.el.setAttribute('velocity', body.velocity);
this.el.setAttribute('position', body.position);
};
Expand All @@ -205,7 +193,6 @@ module.exports = AFRAME.registerComponent('kinematic-body', {
vFrom = this.body.position,
vTo = this.body.position.clone();

vTo.y -= this.data.height;
ray = new CANNON.Ray(vFrom, vTo);
ray._updateDirection(); // TODO - Report bug.
ray.intersectBody(groundBody);
Expand Down

0 comments on commit 2f5a652

Please sign in to comment.