UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in

261 lines • 9.94 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { Mesh, Vector3 } from "three"; import { addComponent } from "../engine/engine_components.js"; import { serializable } from "../engine/engine_serialization_decorator.js"; import { getWorldScale } from "../engine/engine_three_utils.js"; import { validate } from "../engine/engine_util_decorator.js"; import { unwatchWrite, watchWrite } from "../engine/engine_utils.js"; import { NEEDLE_progressive } from "../engine/extensions/NEEDLE_progressive.js"; import { Behaviour } from "./Component.js"; import { Rigidbody } from "./RigidBody.js"; /** * Collider is the base class for all colliders. A collider is a physical shape that is used to detect collisions with other objects in the scene. * Colliders are used in combination with a Rigidbody to create physical interactions between objects. * Colliders are registered with the physics engine when they are enabled and removed when they are disabled. * @category Physics * @group Components */ export class Collider extends Behaviour { /** @internal */ get isCollider() { return true; } /** * The Rigidbody that this collider is attached to. */ attachedRigidbody = null; /** * When `true` the collider will not be used for collision detection but will still trigger events. */ isTrigger = false; /** * The physics material that is used for the collider. This material defines physical properties of the collider such as friction and bounciness. */ sharedMaterial; /** * The layers that the collider is assigned to. */ membership = [0]; /** * The layers that the collider will interact with. * @inheritdoc */ filter; /** @internal */ awake() { super.awake(); if (!this.attachedRigidbody) this.attachedRigidbody = this.gameObject.getComponentInParent(Rigidbody); } /** @internal */ start() { if (!this.attachedRigidbody) this.attachedRigidbody = this.gameObject.getComponentInParent(Rigidbody); } /** @internal */ onEnable() { // a rigidbody is not assigned if we export an asset if (!this.attachedRigidbody) this.attachedRigidbody = this.gameObject.getComponentInParent(Rigidbody); } /** @internal */ onDisable() { this.context.physics.engine?.removeBody(this); } /** Returns the underlying physics body from the physics engine (if any) - the component must be enabled and active in the scene */ get body() { return this.context.physics.engine?.getBody(this); } /** * Apply the collider properties to the physics engine. */ updateProperties = () => { this.context.physics.engine?.updateProperties(this); }; /** Requests an update of the physics material in the physics engine */ updatePhysicsMaterial() { this.context.physics.engine?.updatePhysicsMaterial(this); } } __decorate([ serializable(Rigidbody) ], Collider.prototype, "attachedRigidbody", void 0); __decorate([ serializable() ], Collider.prototype, "isTrigger", void 0); __decorate([ serializable() ], Collider.prototype, "sharedMaterial", void 0); __decorate([ serializable() ], Collider.prototype, "membership", void 0); __decorate([ serializable() ], Collider.prototype, "filter", void 0); /** * SphereCollider is a collider that represents a sphere shape. * @category Physics * @group Components */ export class SphereCollider extends Collider { radius = .5; center = new Vector3(0, 0, 0); onEnable() { super.onEnable(); this.context.physics.engine?.addSphereCollider(this); watchWrite(this.gameObject.scale, this.updateProperties); } onDisable() { super.onDisable(); unwatchWrite(this.gameObject.scale, this.updateProperties); } onValidate() { this.updateProperties(); } } __decorate([ validate(), serializable() ], SphereCollider.prototype, "radius", void 0); __decorate([ serializable(Vector3) ], SphereCollider.prototype, "center", void 0); /** * BoxCollider is a collider that represents a box shape. * @category Physics * @group Components */ export class BoxCollider extends Collider { static add(obj, opts) { const collider = new BoxCollider(); if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox(); const bb = obj.geometry.boundingBox; collider.size = bb.getSize(new Vector3()) || new Vector3(1, 1, 1); collider.center = bb.getCenter(new Vector3()) || new Vector3(0, 0, 0); addComponent(obj, collider); if (opts?.rigidbody === true) { addComponent(obj, Rigidbody, { isKinematic: false }); } return collider; } size = new Vector3(1, 1, 1); center = new Vector3(0, 0, 0); onEnable() { super.onEnable(); this.context.physics.engine?.addBoxCollider(this, this.size); watchWrite(this.gameObject.scale, this.updateProperties); } onDisable() { super.onDisable(); unwatchWrite(this.gameObject.scale, this.updateProperties); } onValidate() { this.updateProperties(); } } __decorate([ validate(), serializable(Vector3) ], BoxCollider.prototype, "size", void 0); __decorate([ serializable(Vector3) ], BoxCollider.prototype, "center", void 0); /** * MeshCollider is a collider that represents a mesh shape. * The mesh collider can be used to create a collider from a mesh. * @category Physics * @group Components */ export class MeshCollider extends Collider { /** * The mesh that is used for the collider. */ sharedMesh; /** When `true` the collider won't have holes or entrances. * If you wan't this mesh collider to be able to *contain* other objects this should be set to `false` */ convex = false; onEnable() { super.onEnable(); if (!this.context.physics.engine) return; if (!this.sharedMesh?.isMesh) { // HACK using the renderer mesh if (this.gameObject instanceof Mesh) { this.sharedMesh = this.gameObject; } } const LOD = 0; if (this.sharedMesh?.isMesh) { this.context.physics.engine.addMeshCollider(this, this.sharedMesh, this.convex, getWorldScale(this.gameObject)); NEEDLE_progressive.assignMeshLOD(this.sharedMesh, LOD).then(res => { if (res && this.activeAndEnabled && this.context.physics.engine && this.sharedMesh) { this.context.physics.engine.removeBody(this); this.sharedMesh.geometry = res; this.context.physics.engine.addMeshCollider(this, this.sharedMesh, this.convex, getWorldScale(this.gameObject)); } }); } else { const group = this.sharedMesh; if (group?.isGroup) { console.warn(`MeshCollider mesh is a group \"${this.sharedMesh?.name || this.gameObject.name}\", adding all children as colliders. This is currently not fully supported (colliders can not be removed from world again)`, this); const promises = new Array(); for (const ch in group.children) { const child = group.children[ch]; if (child.isMesh) { this.context.physics.engine.addMeshCollider(this, child, this.convex, getWorldScale(this.gameObject)); promises.push(NEEDLE_progressive.assignMeshLOD(child, LOD)); } } Promise.all(promises).then(res => { if (res.some(r => r) == false) return; this.context.physics.engine?.removeBody(this); const mesh = new Mesh(); for (const r of res) { if (r && this.activeAndEnabled) { mesh.geometry = r; this.context.physics.engine?.addMeshCollider(this, mesh, this.convex, getWorldScale(this.gameObject)); } } }); } } } } __decorate([ serializable(Mesh) ], MeshCollider.prototype, "sharedMesh", void 0); __decorate([ serializable() ], MeshCollider.prototype, "convex", void 0); /** * CapsuleCollider is a collider that represents a capsule shape. * @category Physics * @group Components */ export class CapsuleCollider extends Collider { center = new Vector3(0, 0, 0); radius = .5; height = 2; onEnable() { super.onEnable(); this.context.physics.engine?.addCapsuleCollider(this, this.height, this.radius); } } __decorate([ serializable(Vector3) ], CapsuleCollider.prototype, "center", void 0); __decorate([ serializable() ], CapsuleCollider.prototype, "radius", void 0); __decorate([ serializable() ], CapsuleCollider.prototype, "height", void 0); //# sourceMappingURL=Collider.js.map