@enable3d/ammo-physics
Version:
Physics Plugin for three.js
164 lines • 6.45 kB
JavaScript
/**
* @author Yannick Deubel (https://github.com/yandeu)
* @copyright Copyright (c) 2020 Yannick Deubel; Project Url: https://github.com/enable3d/enable3d
* @description This is a modified version of the original code from Kevin Lee
*/
/**
* @author Kevin Lee (https://github.com/InfiniteLee)
* @copyright Copyright (c) 2019 Kevin Lee; Project Url: https://github.com/InfiniteLee/ammo-debug-drawer
* @license {@link https://github.com/InfiniteLee/ammo-debug-drawer/blob/master/LICENSE|MPL-2.0}
*/
import { BufferAttribute, BufferGeometry, LineBasicMaterial, LineSegments, StaticDrawUsage } from 'three';
const AmmoDebugConstants = {
NoDebug: 0,
DrawWireframe: 1,
DrawAabb: 2,
DrawFeaturesText: 4,
DrawContactPoints: 8,
NoDeactivation: 16,
NoHelpText: 32,
DrawText: 64,
ProfileTimings: 128,
EnableSatComparison: 256,
DisableBulletLCP: 512,
EnableCCD: 1024,
DrawConstraints: 1 << 11, //2048
DrawConstraintLimits: 1 << 12, //4096
FastWireframe: 1 << 13, //8192
DrawNormals: 1 << 14, //16384
DrawOnTop: 1 << 15, //32768
MAX_DEBUG_DRAW_MODE: 0xffffffff
};
/**
* An implementation of the btIDebugDraw interface in Ammo.js, for debug rendering of Ammo shapes
*/
class DebugDrawer {
scene;
world;
options;
debugDrawMode;
geometry;
index;
mesh;
enabled;
debugDrawer;
warnedOnce;
constructor(scene, world, options = {}) {
this.scene = scene;
this.world = world;
this.options = options;
this.debugDrawMode = options.debugDrawMode || AmmoDebugConstants.DrawWireframe;
const drawOnTop = this.debugDrawMode & AmmoDebugConstants.DrawOnTop || false;
const maxBufferSize = options.maxBufferSize || 1000000;
this.geometry = new BufferGeometry();
const vertices = new Float32Array(maxBufferSize * 3);
const colors = new Float32Array(maxBufferSize * 3);
/*
I do not know the difference, just using the first one.
export const StaticDrawUsage: Usage;
export const DynamicDrawUsage: Usage;
export const StreamDrawUsage: Usage;
export const StaticReadUsage: Usage;
export const DynamicReadUsage: Usage;
export const StreamReadUsage: Usage;
export const StaticCopyUsage: Usage;
export const DynamicCopyUsage: Usage;
export const StreamCopyUsage: Usage;
*/
this.geometry.setAttribute('position', new BufferAttribute(vertices, 3).setUsage(StaticDrawUsage));
this.geometry.setAttribute('color', new BufferAttribute(colors, 3).setUsage(StaticDrawUsage));
this.index = 0;
const material = new LineBasicMaterial({
vertexColors: true,
depthTest: !drawOnTop
});
this.mesh = new LineSegments(this.geometry, material);
if (drawOnTop)
this.mesh.renderOrder = 999;
this.mesh.frustumCulled = false;
this.enabled = false;
this.debugDrawer = new Ammo.DebugDrawer();
this.debugDrawer.drawLine = this.drawLine.bind(this);
this.debugDrawer.drawContactPoint = this.drawContactPoint.bind(this);
this.debugDrawer.reportErrorWarning = this.reportErrorWarning.bind(this);
this.debugDrawer.draw3dText = this.draw3dText.bind(this);
this.debugDrawer.setDebugMode = this.setDebugMode.bind(this);
this.debugDrawer.getDebugMode = this.getDebugMode.bind(this);
this.world.setDebugDrawer(this.debugDrawer);
}
enable() {
this.enabled = true;
this.scene.add(this.mesh);
}
disable() {
this.enabled = false;
this.scene.remove(this.mesh);
}
update() {
if (!this.enabled) {
return;
}
if (this.index != 0) {
this.geometry.attributes.position.needsUpdate = true;
this.geometry.attributes.color.needsUpdate = true;
}
this.index = 0;
this.world.debugDrawWorld();
this.geometry.setDrawRange(0, this.index);
}
drawLine(from, to, color) {
const heap = Ammo.HEAPF32;
const r = heap[(color + 0) / 4];
const g = heap[(color + 4) / 4];
const b = heap[(color + 8) / 4];
const fromX = heap[(from + 0) / 4];
const fromY = heap[(from + 4) / 4];
const fromZ = heap[(from + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, fromX, fromY, fromZ);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
const toX = heap[(to + 0) / 4];
const toY = heap[(to + 4) / 4];
const toZ = heap[(to + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, toX, toY, toZ);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
}
//TODO: figure out how to make lifeTime work
drawContactPoint(pointOnB, normalOnB, distance, _lifeTime, color) {
const heap = Ammo.HEAPF32;
const r = heap[(color + 0) / 4];
const g = heap[(color + 4) / 4];
const b = heap[(color + 8) / 4];
const x = heap[(pointOnB + 0) / 4];
const y = heap[(pointOnB + 4) / 4];
const z = heap[(pointOnB + 8) / 4];
this.geometry.attributes.position.setXYZ(this.index, x, y, z);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
const dx = heap[(normalOnB + 0) / 4] * distance;
const dy = heap[(normalOnB + 4) / 4] * distance;
const dz = heap[(normalOnB + 8) / 4] * distance;
this.geometry.attributes.position.setXYZ(this.index, x + dx, y + dy, z + dz);
this.geometry.attributes.color.setXYZ(this.index++, r, g, b);
}
reportErrorWarning(warningString) {
// eslint-disable-next-line no-prototype-builtins
if (Ammo.hasOwnProperty('Pointer_stringify')) {
console.warn(Ammo.Pointer_stringify(warningString));
}
else if (!this.warnedOnce) {
this.warnedOnce = true;
console.warn("Cannot print warningString, please rebuild Ammo.js using 'debug' flag");
}
}
draw3dText(_location, _textString) {
//TODO
console.warn('TODO: draw3dText');
}
setDebugMode(debugMode) {
this.debugDrawMode = debugMode;
}
getDebugMode() {
return this.debugDrawMode;
}
}
export default DebugDrawer;
//# sourceMappingURL=debugDrawer.js.map