123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import { PhysicsBody } from "./physicsBody.js";
- import { PhysicsShape } from "./physicsShape.js";
- import { Logger } from "../../Misc/logger.js";
- import { Quaternion, TmpVectors, Vector3 } from "../../Maths/math.vector.js";
- import { Scalar } from "../../Maths/math.scalar.js";
- import { PhysicsMotionType, PhysicsShapeType } from "./IPhysicsEnginePlugin.js";
- import { BoundingBox } from "../../Culling/boundingBox.js";
- /**
- * Helper class to create and interact with a PhysicsAggregate.
- * This is a transition object that works like Physics Plugin V1 Impostors.
- * This helper instanciate all mandatory physics objects to get a body/shape and material.
- * It's less efficient that handling body and shapes independently but for prototyping or
- * a small numbers of physics objects, it's good enough.
- */
- export class PhysicsAggregate {
- constructor(
- /**
- * The physics-enabled object used as the physics aggregate
- */
- transformNode,
- /**
- * The type of the physics aggregate
- */
- type, _options = { mass: 0 }, _scene) {
- this.transformNode = transformNode;
- this.type = type;
- this._options = _options;
- this._scene = _scene;
- this._disposeShapeWhenDisposed = true;
- //sanity check!
- if (!this.transformNode) {
- Logger.Error("No object was provided. A physics object is obligatory");
- return;
- }
- const m = transformNode;
- if (this.transformNode.parent && this._options.mass !== 0 && m.hasThinInstances) {
- Logger.Warn("A physics body has been created for an object which has a parent and thin instances. Babylon physics currently works in local space so unexpected issues may occur.");
- }
- // Legacy support for old syntax.
- if (!this._scene && transformNode.getScene) {
- this._scene = transformNode.getScene();
- }
- if (!this._scene) {
- return;
- }
- //default options params
- this._options.mass = _options.mass === void 0 ? 0 : _options.mass;
- this._options.friction = _options.friction === void 0 ? 0.2 : _options.friction;
- this._options.restitution = _options.restitution === void 0 ? 0.2 : _options.restitution;
- const motionType = this._options.mass === 0 ? PhysicsMotionType.STATIC : PhysicsMotionType.DYNAMIC;
- const startAsleep = this._options.startAsleep ?? false;
- this.body = new PhysicsBody(transformNode, motionType, startAsleep, this._scene);
- this._addSizeOptions();
- if (type.getClassName && type.getClassName() === "PhysicsShape") {
- this.shape = type;
- this._disposeShapeWhenDisposed = false;
- }
- else {
- this.shape = new PhysicsShape({ type: type, parameters: this._options }, this._scene);
- }
- if (this._options.isTriggerShape) {
- this.shape.isTrigger = true;
- }
- this.material = { friction: this._options.friction, restitution: this._options.restitution };
- this.body.shape = this.shape;
- this.shape.material = this.material;
- this.body.setMassProperties({ mass: this._options.mass });
- this._nodeDisposeObserver = this.transformNode.onDisposeObservable.add(() => {
- this.dispose();
- });
- }
- _getObjectBoundingBox() {
- if (this.transformNode.getRawBoundingInfo) {
- return this.transformNode.getRawBoundingInfo().boundingBox;
- }
- else {
- return new BoundingBox(new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, 0.5, 0.5));
- }
- }
- _hasVertices(node) {
- return node?.getTotalVertices() > 0;
- }
- _addSizeOptions() {
- this.transformNode.computeWorldMatrix(true);
- const bb = this._getObjectBoundingBox();
- const extents = TmpVectors.Vector3[0];
- extents.copyFrom(bb.extendSize);
- extents.scaleInPlace(2);
- extents.multiplyInPlace(this.transformNode.scaling);
- // In case we had any negative scaling, we need to take the absolute value of the extents.
- extents.x = Math.abs(extents.x);
- extents.y = Math.abs(extents.y);
- extents.z = Math.abs(extents.z);
- const min = TmpVectors.Vector3[1];
- min.copyFrom(bb.minimum);
- min.multiplyInPlace(this.transformNode.scaling);
- if (!this._options.center) {
- const center = new Vector3();
- center.copyFrom(bb.center);
- center.multiplyInPlace(this.transformNode.scaling);
- this._options.center = center;
- }
- switch (this.type) {
- case PhysicsShapeType.SPHERE:
- if (!this._options.radius && Scalar.WithinEpsilon(extents.x, extents.y, 0.0001) && Scalar.WithinEpsilon(extents.x, extents.z, 0.0001)) {
- this._options.radius = extents.x / 2;
- }
- else if (!this._options.radius) {
- Logger.Warn("Non uniform scaling is unsupported for sphere shapes. Setting the radius to the biggest bounding box extent.");
- this._options.radius = Math.max(extents.x, extents.y, extents.z) / 2;
- }
- break;
- case PhysicsShapeType.CAPSULE:
- {
- const capRadius = extents.x / 2;
- this._options.radius = this._options.radius ?? capRadius;
- this._options.pointA = this._options.pointA ?? new Vector3(0, min.y + capRadius, 0);
- this._options.pointB = this._options.pointB ?? new Vector3(0, min.y + extents.y - capRadius, 0);
- }
- break;
- case PhysicsShapeType.CYLINDER:
- {
- const capRadius = extents.x / 2;
- this._options.radius = this._options.radius ?? capRadius;
- this._options.pointA = this._options.pointA ?? new Vector3(0, min.y, 0);
- this._options.pointB = this._options.pointB ?? new Vector3(0, min.y + extents.y, 0);
- }
- break;
- case PhysicsShapeType.MESH:
- case PhysicsShapeType.CONVEX_HULL:
- if (!this._options.mesh && this._hasVertices(this.transformNode)) {
- this._options.mesh = this.transformNode;
- }
- else if (!this._options.mesh || !this._hasVertices(this._options.mesh)) {
- throw new Error("No valid mesh was provided for mesh or convex hull shape parameter. Please provide a mesh with valid geometry (number of vertices greater than 0).");
- }
- break;
- case PhysicsShapeType.BOX:
- this._options.extents = this._options.extents ?? new Vector3(extents.x, extents.y, extents.z);
- this._options.rotation = this._options.rotation ?? Quaternion.Identity();
- break;
- }
- }
- /**
- * Releases the body, shape and material
- */
- dispose() {
- if (this._nodeDisposeObserver) {
- this.body.transformNode.onDisposeObservable.remove(this._nodeDisposeObserver);
- this._nodeDisposeObserver = null;
- }
- this.body.dispose();
- if (this._disposeShapeWhenDisposed) {
- this.shape.dispose();
- }
- }
- }
- //# sourceMappingURL=physicsAggregate.js.map
|