123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- import { PhysicsShapeType } from "./IPhysicsEnginePlugin.js";
- import { Matrix, Vector3, Quaternion, TmpVectors } from "../../Maths/math.vector.js";
- /**
- * PhysicsShape class.
- * This class is useful for creating a physics shape that can be used in a physics engine.
- * A Physic Shape determine how collision are computed. It must be attached to a body.
- */
- export class PhysicsShape {
- /**
- * Constructs a new physics shape.
- * @param options The options for the physics shape. These are:
- * * type: The type of the shape. This can be one of the following: SPHERE, BOX, CAPSULE, CYLINDER, CONVEX_HULL, MESH, HEIGHTFIELD, CONTAINER
- * * parameters: The parameters of the shape.
- * * pluginData: The plugin data of the shape. This is used if you already have a reference to the object on the plugin side.
- * You need to specify either type or pluginData.
- * @param scene The scene the shape belongs to.
- *
- * This code is useful for creating a new physics shape with the given type, options, and scene.
- * It also checks that the physics engine and plugin version are correct.
- * If not, it throws an error. This ensures that the shape is created with the correct parameters and is compatible with the physics engine.
- */
- constructor(options, scene) {
- /**
- * V2 Physics plugin private data for single shape
- */
- this._pluginData = undefined;
- this._isTrigger = false;
- this._isDisposed = false;
- if (!scene) {
- return;
- }
- const physicsEngine = scene.getPhysicsEngine();
- if (!physicsEngine) {
- throw new Error("No Physics Engine available.");
- }
- if (physicsEngine.getPluginVersion() != 2) {
- throw new Error("Plugin version is incorrect. Expected version 2.");
- }
- const physicsPlugin = physicsEngine.getPhysicsPlugin();
- if (!physicsPlugin) {
- throw new Error("No Physics Plugin available.");
- }
- this._physicsPlugin = physicsPlugin;
- if (options.pluginData !== undefined && options.pluginData !== null) {
- this._pluginData = options.pluginData;
- this._type = this._physicsPlugin.getShapeType(this);
- }
- else if (options.type !== undefined && options.type !== null) {
- this._type = options.type;
- const parameters = options.parameters ?? {};
- this._physicsPlugin.initShape(this, options.type, parameters);
- }
- }
- /**
- * Returns the string "PhysicsShape".
- * @returns "PhysicsShape"
- */
- getClassName() {
- return "PhysicsShape";
- }
- /**
- * Returns the type of the physics shape.
- * @returns The type of the physics shape.
- */
- get type() {
- return this._type;
- }
- /**
- * Set the membership mask of a shape. This is a bitfield of arbitrary
- * "categories" to which the shape is a member. This is used in combination
- * with the collide mask to determine if this shape should collide with
- * another.
- *
- * @param membershipMask Bitfield of categories of this shape.
- */
- set filterMembershipMask(membershipMask) {
- this._physicsPlugin.setShapeFilterMembershipMask(this, membershipMask);
- }
- /**
- * Get the membership mask of a shape.
- * @returns Bitmask of categories which this shape is a member of.
- */
- get filterMembershipMask() {
- return this._physicsPlugin.getShapeFilterMembershipMask(this);
- }
- /**
- * Sets the collide mask of a shape. This is a bitfield of arbitrary
- * "categories" to which this shape collides with. Given two shapes,
- * the engine will check if the collide mask and membership overlap:
- * shapeA.filterMembershipMask & shapeB.filterCollideMask
- *
- * If this value is zero (i.e. shapeB only collides with categories
- * which shapeA is _not_ a member of) then the shapes will not collide.
- *
- * Note, the engine will also perform the same test with shapeA and
- * shapeB swapped; the shapes will not collide if either shape has
- * a collideMask which prevents collision with the other shape.
- *
- * @param collideMask Bitmask of categories this shape should collide with
- */
- set filterCollideMask(collideMask) {
- this._physicsPlugin.setShapeFilterCollideMask(this, collideMask);
- }
- /**
- *
- * @returns Bitmask of categories that this shape should collide with
- */
- get filterCollideMask() {
- return this._physicsPlugin.getShapeFilterCollideMask(this);
- }
- /**
- *
- * @param material
- */
- set material(material) {
- this._physicsPlugin.setMaterial(this, material);
- this._material = material;
- }
- /**
- * Returns the material of the physics shape.
- * @returns The material of the physics shape.
- */
- get material() {
- if (!this._material) {
- this._material = this._physicsPlugin.getMaterial(this);
- }
- return this._material;
- }
- /**
- * Sets the density of the physics shape.
- * @param density The density of the physics shape.
- */
- set density(density) {
- this._physicsPlugin.setDensity(this, density);
- }
- /**
- * Returns the density of the physics shape.
- * @returns The density of the physics shape.
- */
- get density() {
- return this._physicsPlugin.getDensity(this);
- }
- /**
- * Utility to add a child shape to this container,
- * automatically computing the relative transform between
- * the container shape and the child instance.
- *
- * @param parentTransform The transform node associated with this shape
- * @param newChild The new PhysicsShape to add
- * @param childTransform The transform node associated with the child shape
- */
- addChildFromParent(parentTransform, newChild, childTransform) {
- const childToWorld = childTransform.computeWorldMatrix(true);
- const parentToWorld = parentTransform.computeWorldMatrix(true);
- const childToParent = TmpVectors.Matrix[0];
- childToWorld.multiplyToRef(Matrix.Invert(parentToWorld), childToParent);
- const translation = TmpVectors.Vector3[0];
- const rotation = TmpVectors.Quaternion[0];
- const scale = TmpVectors.Vector3[1];
- childToParent.decompose(scale, rotation, translation);
- this._physicsPlugin.addChild(this, newChild, translation, rotation, scale);
- }
- /**
- * Adds a child shape to a container with an optional transform
- * @param newChild The new PhysicsShape to add
- * @param translation Optional position of the child shape relative to this shape
- * @param rotation Optional rotation of the child shape relative to this shape
- * @param scale Optional scale of the child shape relative to this shape
- */
- addChild(newChild, translation, rotation, scale) {
- this._physicsPlugin.addChild(this, newChild, translation, rotation, scale);
- }
- /**
- * Removes a child shape from this shape.
- * @param childIndex The index of the child shape to remove
- */
- removeChild(childIndex) {
- this._physicsPlugin.removeChild(this, childIndex);
- }
- /**
- * Returns the number of children of a physics shape.
- * @returns The number of children of a physics shape.
- */
- getNumChildren() {
- return this._physicsPlugin.getNumChildren(this);
- }
- /**
- * Returns the bounding box of the physics shape.
- * @returns The bounding box of the physics shape.
- */
- getBoundingBox() {
- return this._physicsPlugin.getBoundingBox(this);
- }
- set isTrigger(isTrigger) {
- if (this._isTrigger === isTrigger) {
- return;
- }
- this._isTrigger = isTrigger;
- this._physicsPlugin.setTrigger(this, isTrigger);
- }
- get isTrigger() {
- return this._isTrigger;
- }
- /**
- * Dispose the shape and release its associated resources.
- */
- dispose() {
- if (this._isDisposed) {
- return;
- }
- this._physicsPlugin.disposeShape(this);
- this._isDisposed = true;
- }
- }
- /**
- * Helper object to create a sphere shape
- */
- export class PhysicsShapeSphere extends PhysicsShape {
- /**
- * Constructor for the Sphere Shape
- * @param center local center of the sphere
- * @param radius radius
- * @param scene scene to attach to
- */
- constructor(center, radius, scene) {
- super({ type: PhysicsShapeType.SPHERE, parameters: { center: center, radius: radius } }, scene);
- }
- /**
- * Derive an approximate sphere from the mesh.
- * @param mesh node from which to derive the sphere shape
- * @returns PhysicsShapeSphere
- */
- static FromMesh(mesh) {
- const bounds = mesh.getBoundingInfo();
- const centerLocal = bounds.boundingSphere.center;
- const he = bounds.boundingBox.extendSize;
- const radius = Math.max(he.x, he.y, he.z);
- return new PhysicsShapeSphere(centerLocal, radius, mesh.getScene());
- }
- }
- /**
- * Helper object to create a capsule shape
- */
- export class PhysicsShapeCapsule extends PhysicsShape {
- /**
- *
- * @param pointA Starting point that defines the capsule segment
- * @param pointB ending point of that same segment
- * @param radius radius
- * @param scene scene to attach to
- */
- constructor(pointA, pointB, radius, scene) {
- super({ type: PhysicsShapeType.CAPSULE, parameters: { pointA: pointA, pointB: pointB, radius: radius } }, scene);
- }
- /**
- * Derive an approximate capsule from the mesh. Note, this is
- * not the optimal bounding capsule.
- * @param mesh Node from which to derive a cylinder shape
- * @returns Physics Shape Capsule
- */
- static FromMesh(mesh) {
- const boundsLocal = mesh.getBoundingInfo();
- const radius = boundsLocal.boundingBox.extendSize.x;
- const pointFromCenter = new Vector3(0, boundsLocal.boundingBox.extendSize.y - radius, 0);
- const pointA = boundsLocal.boundingBox.center.add(pointFromCenter);
- const pointB = boundsLocal.boundingBox.center.subtract(pointFromCenter);
- return new PhysicsShapeCapsule(pointA, pointB, radius, mesh.getScene());
- }
- }
- /**
- * Helper object to create a cylinder shape
- */
- export class PhysicsShapeCylinder extends PhysicsShape {
- /**
- *
- * @param pointA Starting point that defines the cylinder segment
- * @param pointB ending point of that same segment
- * @param radius radius
- * @param scene scene to attach to
- */
- constructor(pointA, pointB, radius, scene) {
- super({ type: PhysicsShapeType.CYLINDER, parameters: { pointA: pointA, pointB: pointB, radius: radius } }, scene);
- }
- /**
- * Derive an approximate cylinder from the mesh. Note, this is
- * not the optimal bounding cylinder.
- * @param mesh Node from which to derive a cylinder shape
- * @returns Physics Shape Cylinder
- */
- static FromMesh(mesh) {
- const boundsLocal = mesh.getBoundingInfo();
- const radius = boundsLocal.boundingBox.extendSize.x;
- const pointFromCenter = new Vector3(0, boundsLocal.boundingBox.extendSize.y, 0);
- const pointA = boundsLocal.boundingBox.center.add(pointFromCenter);
- const pointB = boundsLocal.boundingBox.center.subtract(pointFromCenter);
- return new PhysicsShapeCylinder(pointA, pointB, radius, mesh.getScene());
- }
- }
- /**
- * Helper object to create a box shape
- */
- export class PhysicsShapeBox extends PhysicsShape {
- /**
- *
- * @param center local center of the box
- * @param rotation local orientation
- * @param extents size of the box in each direction
- * @param scene scene to attach to
- */
- constructor(center, rotation, extents, scene) {
- super({ type: PhysicsShapeType.BOX, parameters: { center: center, rotation: rotation, extents: extents } }, scene);
- }
- /**
- *
- * @param mesh
- * @returns PhysicsShapeBox
- */
- static FromMesh(mesh) {
- const bounds = mesh.getBoundingInfo();
- const centerLocal = bounds.boundingBox.center;
- const extents = bounds.boundingBox.extendSize.scale(2.0); //<todo.eoin extendSize seems to really be half-extents?
- return new PhysicsShapeBox(centerLocal, Quaternion.Identity(), extents, mesh.getScene());
- }
- }
- /**
- * Helper object to create a convex hull shape
- */
- export class PhysicsShapeConvexHull extends PhysicsShape {
- /**
- *
- * @param mesh the mesh to be used as topology infos for the convex hull
- * @param scene scene to attach to
- */
- constructor(mesh, scene) {
- super({ type: PhysicsShapeType.CONVEX_HULL, parameters: { mesh: mesh } }, scene);
- }
- }
- /**
- * Helper object to create a mesh shape
- */
- export class PhysicsShapeMesh extends PhysicsShape {
- /**
- *
- * @param mesh the mesh topology that will be used to create the shape
- * @param scene scene to attach to
- */
- constructor(mesh, scene) {
- super({ type: PhysicsShapeType.MESH, parameters: { mesh: mesh } }, scene);
- }
- }
- /**
- * A shape container holds a variable number of shapes. Use AddChild to append to newly created parent container.
- */
- export class PhysicsShapeContainer extends PhysicsShape {
- /**
- * Constructor of the Shape container
- * @param scene scene to attach to
- */
- constructor(scene) {
- super({ type: PhysicsShapeType.CONTAINER, parameters: {} }, scene);
- }
- }
- //# sourceMappingURL=physicsShape.js.map
|