@hology/core 0.0.21 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
+ export declare const projectConfigFileName = "hology.config.json";
1
2
  export interface ProjectConfig {
3
+ name: string;
2
4
  dataPath: string;
3
5
  shadersPath: string;
4
6
  actorsPath: string;
@@ -1,4 +1,4 @@
1
- export{};
1
+ export const projectConfigFileName="hology.config.json";
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
package/dist/csm.js CHANGED
@@ -1,4 +1,4 @@
1
- import*as e from"three";const a=e.Object3D.prototype.add,n=new WeakMap,t=new WeakMap;export const CSMUtil={renderingView:null,onBeforeCompile(e,a){e.defines=e.defines||{},e.defines.USE_CSM=1,e.defines.CSM_CASCADES=this.renderingView.csm.cascades;const n=Math.min(this.renderingView.camera.far,this.renderingView.csm.maxFar),t=[];this.renderingView.csm.getExtendedBreaks(t),a.uniforms.CSM_cascades={value:t},a.uniforms.cameraNear={value:this.renderingView.camera.near},a.uniforms.shadowFar={value:n}},patchThreeAdd(){const r=this.renderingView;n.set(r.scene,r.csm),e.Object3D.prototype.add=function(...r){let i=this;for(;null!=i.parent;)i=i.parent;const s=i,d=n.get(s);if(null==d)return a.apply(this,arguments),this;t.has(s)||t.set(s,new WeakSet);const o=t.get(s);return r.forEach((a=>null==a?void 0:a.traverse((a=>{(a instanceof e.Mesh||a instanceof e.SkinnedMesh)&&a.material&&!o.has(a.material)&&(o.add(a.material),null==d||d.setupMaterial(a.material))})))),a.apply(this,arguments),this}}};
1
+ import*as e from"three";const n=e.Object3D.prototype.add,t=new WeakMap,a=new WeakMap;export const CSMUtil={renderingView:null,onBeforeCompile(e,n){e.defines=e.defines||{},e.defines.USE_CSM=1,e.defines.CSM_CASCADES=this.renderingView.csm.cascades;const t=Math.min(this.renderingView.camera.far,this.renderingView.csm.maxFar),a=[];this.renderingView.csm.getExtendedBreaks(a),n.uniforms.CSM_cascades={value:a},n.uniforms.cameraNear={value:this.renderingView.camera.near},n.uniforms.shadowFar={value:t}},patchThreeAdd(){const r=this.renderingView;t.set(r.scene,r.csm),e.Object3D.prototype.add=function(...r){let i=this;for(;null!=i.parent;)i=i.parent;const s=i,o=t.get(s);if(null==o)return n.apply(this,arguments),this;a.has(s)||a.set(s,new WeakSet);const c=a.get(s);function d(e){e&&!c.has(e)&&(c.add(e),null==o||o.setupMaterial(e))}return r.forEach((n=>null==n?void 0:n.traverse((n=>{if(n instanceof e.Mesh||n instanceof e.SkinnedMesh)if(n.material instanceof Array)for(const e of n.material)d(e);else d(n.material)})))),n.apply(this,arguments),this}}};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as s}from"tslib";import{PhysicsBodyType as i,PhysicsSystem as e}from"../../../../gameplay/services/physics/physics-system";import{AssetMeshInstance as o}from"../../../../scene/asset-resource-loader";import{PhysicalShapeMesh as n}from"../../../../";import{Parameter as r}from"../../../../shader/parameter";import{Euler as c,Vector3 as h}from"three";import{ActorComponent as p,Component as a}from"../../component";import{firstValueFrom as l}from"rxjs";const m={friction:.1,mass:0,bodyType:i.static,continousCollisionDetection:!1};let y=class extends p{constructor(t){super(),this.physicsSystem=t,this.position=new h,this.rotation=new c,this.scale=new h(1,1,1),this.mass=m.mass,this.friction=m.friction,this.bodyType=i.static,this.continousCollisionDetection=m.continousCollisionDetection}onInit(){null!=this.object&&(this.currentMesh=this.object,this.updateMesh()),l(this.disposed).then((()=>{this.physicsSystem.removeActor(this.actor)}))}setObject(t){null!=this.currentMesh&&this.actor.object.remove(this.currentMesh),this.object=this.currentMesh=t,this.updateMesh()}updateMesh(){this.currentMesh.position.copy(this.position),this.currentMesh.rotation.copy(this.rotation),this.currentMesh.scale.copy(this.scale);const t=this.getCollisionShapes();t.length>0&&this.physicsSystem.addActor(this.actor,t,Object.assign(Object.assign({},m),{isTrigger:!1,mass:this.mass,friction:this.friction,type:this.bodyType,continousCollisionDetection:this.continousCollisionDetection})),this.actor.object.add(this.currentMesh)}getCollisionShapes(){return this.currentMesh instanceof o?this.currentMesh.collisionShapes:this.currentMesh instanceof n?[this.currentMesh.collisionShape]:"collisionShape"in this.currentMesh?(console.error("Could not understand wehre to get collision shapes from. This is likely due to an import issue"),[this.currentMesh.collisionShape]):[]}};t([r(),s("design:type",Object)],y.prototype,"object",void 0),t([r(),s("design:type",h)],y.prototype,"position",void 0),t([r(),s("design:type",c)],y.prototype,"rotation",void 0),t([r(),s("design:type",h)],y.prototype,"scale",void 0),t([r(),s("design:type",Number)],y.prototype,"mass",void 0),t([r(),s("design:type",Number)],y.prototype,"friction",void 0),t([r({options:[{name:"Static",value:i.static},{name:"Dynamic",value:i.dynamic}]}),s("design:type",Number)],y.prototype,"bodyType",void 0),y=t([a({inEditor:!0}),s("design:paramtypes",[e])],y);export{y as MeshComponent};
1
+ import{__decorate as t,__metadata as s}from"tslib";import{PhysicsBodyType as i,PhysicsSystem as e}from"../../../../gameplay/services/physics/physics-system";import{AssetMeshInstance as o}from"../../../../scene/asset-resource-loader";import{PhysicalShapeMesh as n}from"../../../../";import{Parameter as r}from"../../../../shader/parameter";import{Euler as c,Object3D as h,Vector3 as p}from"three";import{ActorComponent as a,Component as l}from"../../component";import{firstValueFrom as m}from"rxjs";const y={friction:.1,mass:0,bodyType:i.static,continousCollisionDetection:!1};let d=class extends a{constructor(t){super(),this.physicsSystem=t,this.position=new p,this.rotation=new c,this.scale=new p(1,1,1),this.mass=y.mass,this.friction=y.friction,this.bodyType=i.static,this.continousCollisionDetection=y.continousCollisionDetection}onInit(){null!=this.object&&(this.currentMesh=this.object,this.updateMesh()),m(this.disposed).then((()=>{this.physicsSystem.removeActor(this.actor)}))}setObject(t){null!=this.currentMesh&&this.actor.object.remove(this.currentMesh),this.object=this.currentMesh=t,this.updateMesh()}updateMesh(){this.currentMesh.position.copy(this.position),this.currentMesh.rotation.copy(this.rotation),this.currentMesh.scale.copy(this.scale);const t=this.getCollisionShapes();t.length>0&&this.physicsSystem.addActor(this.actor,t,Object.assign(Object.assign({},y),{isTrigger:!1,mass:this.mass,friction:this.friction,type:this.bodyType,continousCollisionDetection:this.continousCollisionDetection})),this.actor.object.add(this.currentMesh)}getCollisionShapes(){return this.currentMesh instanceof o?this.currentMesh.collisionShapes:this.currentMesh instanceof n?[this.currentMesh.collisionShape]:"collisionShape"in this.currentMesh?(console.error("Could not understand wehre to get collision shapes from. This is likely due to an import issue"),[this.currentMesh.collisionShape]):[]}};t([r({type:h}),s("design:type",Object)],d.prototype,"object",void 0),t([r(),s("design:type",p)],d.prototype,"position",void 0),t([r(),s("design:type",c)],d.prototype,"rotation",void 0),t([r(),s("design:type",p)],d.prototype,"scale",void 0),t([r(),s("design:type",Number)],d.prototype,"mass",void 0),t([r(),s("design:type",Number)],d.prototype,"friction",void 0),t([r({options:[{name:"Static",value:i.static},{name:"Dynamic",value:i.dynamic}]}),s("design:type",Number)],d.prototype,"bodyType",void 0),d=t([l({inEditor:!0}),s("design:paramtypes",[e])],d);export{d as MeshComponent};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -5,7 +5,7 @@ export declare class SpawnPointMesh extends ActorComponent {
5
5
  onInit(): void | Promise<void>;
6
6
  }
7
7
  export declare class SpawnPoint extends BaseActor {
8
- mesh: SpawnPointMesh;
8
+ private mesh;
9
9
  private readonly world;
10
10
  spawnActor<T extends BaseActor>(type: Type<T>): Promise<T>;
11
11
  }
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as o}from"tslib";import{EdgesGeometry as e,ArrowHelper as r,Vector3 as i,BoxGeometry as n,Euler as s}from"three";import{Actor as p,BaseActor as c}from"../actor";import{Component as m,ActorComponent as a,Attach as d}from"../component";import{World as l}from"../../../gameplay/services/world";import{inject as w}from"../../../gameplay/inject";import{createLineSphere as h}from"../../../utils/three/line-sphere";let f=class extends a{onInit(){const t=new n(1,1,1),o=(new e(t),h(1));this.actor.object.add(o);this.actor.object.getWorldDirection(new i);const s=new r(new i(0,0,1),new i,1,16773120);this.actor.object.add(s)}};f=t([m({inEditor:!0,editorOnly:!0})],f);export{f as SpawnPointMesh};let y=class extends c{constructor(){super(...arguments),this.world=w(l)}spawnActor(t){return this.world.spawnActor(t,this.position,new s(0,this.rotation.y,0,"XYZ"))}};t([d(),o("design:type",f)],y.prototype,"mesh",void 0),y=t([p()],y);export{y as SpawnPoint};
1
+ import{__decorate as t,__metadata as o}from"tslib";import{ArrowHelper as r,Vector3 as e,Euler as i}from"three";import{Actor as s,BaseActor as n}from"../actor";import{Component as p,ActorComponent as m,Attach as c}from"../component";import{World as a}from"../../../gameplay/services/world";import{inject as d}from"../../../gameplay/inject";import{createLineSphere as l}from"../../../utils/three/line-sphere";let h=class extends m{onInit(){const t=l(1);this.actor.object.add(t);const o=new r(new e(0,0,1),new e,1,1268122,.3,.3);this.actor.object.add(o)}};h=t([p({inEditor:!0,editorOnly:!0})],h);export{h as SpawnPointMesh};let w=class extends n{constructor(){super(...arguments),this.world=d(a)}spawnActor(t){return this.world.spawnActor(t,this.position,new i(0,this.rotation.y,0,"XYZ"))}};t([c(),o("design:type",h)],w.prototype,"mesh",void 0),w=t([s()],w);export{w as SpawnPoint};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as s}from"tslib";import{EdgesGeometry as i,LineSegments as e,LineBasicMaterial as o,Vector3 as r,BoxGeometry as n,Mesh as c,MeshBasicMaterial as h,Group as p}from"three";import{Actor as a,BaseActor as d}from"../actor";import{Component as m,ActorComponent as y,Attach as l}from"../component";import{PhysicsSystem as v}from"../../services/physics/physics-system";import{BoxCollisionShape as g}from"../../../scene/collision/collision-shape";import{firstValueFrom as w}from"rxjs";let A=class extends y{constructor(){super(...arguments),this.dimensions=new r(1,1,1)}onInit(){const t=new n(this.dimensions.x,this.dimensions.y,this.dimensions.z),s=new i(t),r=new e(s,new o({color:16777215})),a=(new c(t,new h({color:16777215,transparent:!0,opacity:.3,visible:!1})),new p);a.add(r),this.actor.object.add(a)}};A=t([m({inEditor:!0,editorOnly:!0})],A);export{A as TriggerVolumeMesh};let O=class extends y{constructor(t){super(),this.physicsSystem=t,this.dimensions=new r(1,1,1)}onInit(){this.editorMesh=this.attach(A),console.log("add actor",this.actor),this.physicsSystem.addActor(this.actor,[new g(this.dimensions)],{isTrigger:!0}),w(this.disposed).then((()=>{this.physicsSystem.removeActor(this.actor)}))}onBeginOverlapWithActor(t){return this.physicsSystem.onBeginOverlapWithActor(this.actor,t)}onEndOverlapWithActor(t){return this.physicsSystem.onEndOverlapWithActor(this.actor,t)}onBeginOverlapWithActorType(t){return this.physicsSystem.onBeginOverlapWithActorType(this.actor,t)}onEndOverlapWithActorType(t){return this.physicsSystem.onEndOverlapWithActorType(this.actor,t)}};O=t([m({inEditor:!0,editorOnly:!1}),s("design:paramtypes",[v])],O);export{O as TriggerVolumeComponent};let u=class extends d{};t([l(),s("design:type",O)],u.prototype,"trigger",void 0),u=t([a()],u);export{u as TriggerVolume};
1
+ import{__decorate as t,__metadata as s}from"tslib";import{EdgesGeometry as i,LineSegments as e,LineBasicMaterial as o,Vector3 as r,BoxGeometry as n,Mesh as c,MeshBasicMaterial as h,Group as p}from"three";import{Actor as m,BaseActor as a}from"../actor";import{Component as d,ActorComponent as y,Attach as l}from"../component";import{PhysicsSystem as v}from"../../services/physics/physics-system";import{BoxCollisionShape as g}from"../../../scene/collision/collision-shape";import{firstValueFrom as w}from"rxjs";let A=class extends y{constructor(){super(...arguments),this.dimensions=new r(1,1,1)}onInit(){const t=new n(this.dimensions.x,this.dimensions.y,this.dimensions.z),s=new i(t),r=new e(s,new o({color:16777215})),m=(new c(t,new h({color:16777215,transparent:!0,opacity:.3,visible:!1})),new p);m.add(r),this.actor.object.add(m)}};A=t([d({inEditor:!0,editorOnly:!0})],A);export{A as TriggerVolumeMesh};let O=class extends y{constructor(t){super(),this.physicsSystem=t,this.dimensions=new r(1,1,1)}onInit(){this.editorMesh=this.attach(A),this.physicsSystem.addActor(this.actor,[new g(this.dimensions)],{isTrigger:!0}),w(this.disposed).then((()=>{this.physicsSystem.removeActor(this.actor)}))}onBeginOverlapWithActor(t){return this.physicsSystem.onBeginOverlapWithActor(this.actor,t)}onEndOverlapWithActor(t){return this.physicsSystem.onEndOverlapWithActor(this.actor,t)}onBeginOverlapWithActorType(t){return this.physicsSystem.onBeginOverlapWithActorType(this.actor,t)}onEndOverlapWithActorType(t){return this.physicsSystem.onEndOverlapWithActorType(this.actor,t)}};O=t([d({inEditor:!0,editorOnly:!1}),s("design:paramtypes",[v])],O);export{O as TriggerVolumeComponent};let u=class extends a{};t([l(),s("design:type",O)],u.prototype,"trigger",void 0),u=t([m()],u);export{u as TriggerVolume};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{__awaiter as t,__decorate as e,__metadata as s}from"tslib";import{ActorComponent as i,Component as o,Attach as n}from"../component";import{CameraComponent as h}from"./camera-component";import{Vector3 as a}from"three";import{ViewController as r}from"../../services/render";import{DecimalInput as c,RestrictedRotationInput as m}from"../../input";import{PhysicsSystem as d,RayTestResult as l}from"../../services/physics/physics-system";import{clamp as u,lerp as p}from"three/src/math/MathUtils";let f=class extends i{constructor(t,e){super(),this.viewController=t,this.physicsSystem=e,this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=5,this.collisionCheckRadius=.5,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new m(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new a,this.lookAtOffset=new a(this.offsetX,0,this.offsetZ),this.isMouseLocked=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{null!=document.pointerLockElement||null!=document.mozPointerLockElement||this.showCursor()}}onInit(){return t(this,void 0,void 0,(function*(){this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.autoActivate&&this.viewController.setCamera(this.camera.instance),this.physicsSystem.beforeStep.subscribe((t=>{this.setFromRotation(t)}));const t=this.element;t.addEventListener("mousedown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.disposed.subscribe((()=>{t.removeEventListener("mousedown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1)}))}))}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&(this.canvas.requestPointerLock(),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){const e=u(Math.min(this.restrictedDistance,this.distance),this.minDistance,Math.max(this.distance*this.zoomInput.value,this.minDistance)),s=Math.cos(this.rotationInput.rotation.x)*e;this.offset.x=Math.sin(this.rotationInput.rotation.y)*s,this.offset.y=Math.sin(this.rotationInput.rotation.x)*e+2,this.offset.z=Math.cos(this.rotationInput.rotation.y)*-s,this.offset.add(this.lookAtOffset),this.updateCameraPosition(),this.checkForCollision(t)}checkForCollision(t){const e=this.getLookAtPosition(),s=v;let i=!1,o=this.distance;const n=new l,h=this.camera.instance.getWorldPosition(y);for(let t=-1;t<=1;t++){const a=w.subVectors(h,e);s.copy(h).add(a.multiplyScalar(1.2)),s.x+=t*this.collisionCheckRadius,this.physicsSystem.rayTest(e,s,n,{debugLifetime:0}),n.hasHit&&n.distance<this.distance&&(o=Math.min(n.distance,o),i||(i=n.hasHit))}i||(this.restrictedDistance=p(this.restrictedDistance,this.distance,this.bounceBackSpeed*t))}getLookAtPosition(){const t=k;return t.set(0,0,0),t.y=this.height,t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(){this.camera.instance.position.copy(this.offset);const t=this.getLookAtPosition();this.camera.instance.lookAt(t)}};e([n(),s("design:type",h)],f.prototype,"camera",void 0),f=e([o(),s("design:paramtypes",[r,d])],f);export{f as ThirdPartyCameraComponent};const k=new a,v=new a,w=(new a,new a),y=new a;
1
+ import{__awaiter as t,__decorate as s,__metadata as e}from"tslib";import{ActorComponent as i,Component as o,Attach as n}from"../component";import{CameraComponent as h}from"./camera-component";import{Vector3 as a}from"three";import{ViewController as r}from"../../services/render";import{DecimalInput as c,RestrictedRotationInput as m}from"../../input";import{PhysicsSystem as d,RayTestResult as l}from"../../services/physics/physics-system";import{clamp as u,lerp as p}from"three/src/math/MathUtils";let f=class extends i{constructor(t,s){super(),this.viewController=t,this.physicsSystem=s,this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=5,this.collisionCheckRadius=.5,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new m(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new c(1,0,1),this.offset=new a,this.lookAtOffset=new a(this.offsetX,0,this.offsetZ),this.isMouseLocked=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{null!=document.pointerLockElement||null!=document.mozPointerLockElement||this.showCursor()}}onInit(){return t(this,void 0,void 0,(function*(){this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.autoActivate&&this.viewController.setCamera(this.camera.instance),this.physicsSystem.afterStep.subscribe((t=>{this.setFromRotation(t)}));const t=this.element;t.addEventListener("mousedown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.disposed.subscribe((()=>{t.removeEventListener("mousedown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1)}))}))}get element(){return this.viewController.htmlElement}hideCursor(){null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&(this.canvas.requestPointerLock(),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){const s=u(Math.min(this.restrictedDistance,this.distance),this.minDistance,Math.max(this.distance*this.zoomInput.value,this.minDistance)),e=Math.cos(this.rotationInput.rotation.x)*s;this.offset.x=Math.sin(this.rotationInput.rotation.y)*e,this.offset.y=Math.sin(this.rotationInput.rotation.x)*s+2,this.offset.z=Math.cos(this.rotationInput.rotation.y)*-e,this.offset.add(this.lookAtOffset),this.updateCameraPosition(),this.checkForCollision(t)}checkForCollision(t){const s=this.getLookAtPosition(),e=v;let i=!1,o=this.distance;const n=new l,h=this.camera.instance.getWorldPosition(y);for(let t=-1;t<=1;t++){const a=w.subVectors(h,s);e.copy(h).add(a.multiplyScalar(1.2)),e.x+=t*this.collisionCheckRadius,this.physicsSystem.rayTest(s,e,n,{debugLifetime:0}),n.hasHit&&n.distance<this.distance&&(o=Math.min(n.distance,o),i||(i=n.hasHit))}i||(this.restrictedDistance=p(this.restrictedDistance,this.distance,this.bounceBackSpeed*t))}getLookAtPosition(){const t=k;return t.set(0,0,0),t.y=this.height,t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(){this.camera.instance.position.copy(this.offset);const t=this.getLookAtPosition();this.camera.instance.lookAt(t)}};s([n(),e("design:type",h)],f.prototype,"camera",void 0),f=s([o(),e("design:paramtypes",[r,d])],f);export{f as ThirdPartyCameraComponent};const k=new a,v=new a,w=(new a,new a),y=new a;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -35,6 +35,7 @@ export declare class HologyRuntime<T_Game = unknown> {
35
35
  private containerInstance;
36
36
  status: HologyRuntimeStatus;
37
37
  gameInstance?: T_Game;
38
+ isShutdown: boolean;
38
39
  private _resolver;
39
40
  /**
40
41
  * A promise that you can await on to delay some logic until the runtime has finished loading
@@ -1,4 +1,4 @@
1
- import{__awaiter as e}from"tslib";import t from"typedi";import{loadScene as n}from"../scene/bootstrap";import{ActorFactory as o}from"./actors/factory";import{World as s}from"./services/world";import{ViewController as r}from"./services/render";import{RenderingView as i}from"../rendering";import{PhysicsSystem as a}from"./services/physics/physics-system";import{MeshComponent as c}from"./actors/builtin/components/mesh-component";import{activeContainerInstance as m}from"./actors/internal/container-map";import{InputService as l}from"./input";import{RuntimeBackendService as p}from"../scene/runtime-backend-service";import{RuntimeAssetsService as d}from"../scene/runtime-asset-service";import{AssetResourceLoader as h}from"../scene/asset-resource-loader";import{AssetLoader as f}from"./services/asset-loader";export function initiateGame(l,u){if(0!=u.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;t.has(r);const g=t.of("default"),w=new HologyRuntime(g),v=new o(g,{inEditor:!1});var y;t.set(o,v),y=u.element,Object.assign(y.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"});const I=new i(u.element);I.renderer.shadowMap.autoUpdate=!0,t.set(i,I);const S=new r(I);t.set(r,S);const b=new s(t.get(o));t.set(s,b);const D=new p(u.dataDir),x=new d(D),G=new h;G.setDataDir(u.dataDir);const H=new f(G,x);return t.set(f,H),(()=>{e(this,void 0,void 0,(function*(){const e=t.get(a);yield e.start();const{scene:o,actors:s}=yield n(I,u.sceneName,u.dataDir,u.shaders,u.actors,v,D,x,G);b.scene=o,t.import([c]);for(const e of s)b.addActor(e);e.addFromScene(o),I.loop((e=>{})),w.status=5,m.value=g,g.remove(l),g.set({id:l,type:l});const r=g.get(l);m.value=null,w.gameInstance=r,r instanceof GameInstance&&r.onStart(),w._resolver(!0)}))})(),w}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.ready=new Promise((e=>{this._resolver=e}))}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const e=this.containerInstance.get(i);null==e||e.stop();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.reset()}}
1
+ import{__awaiter as t}from"tslib";import e from"typedi";import{loadScene as n}from"../scene/bootstrap";import{ActorFactory as o}from"./actors/factory";import{World as s}from"./services/world";import{ViewController as r}from"./services/render";import{RenderingView as i}from"../rendering";import{PhysicsSystem as a}from"./services/physics/physics-system";import{MeshComponent as c}from"./actors/builtin/components/mesh-component";import{activeContainerInstance as m}from"./actors/internal/container-map";import{InputService as d}from"./input";import{RuntimeBackendService as l}from"../scene/runtime-backend-service";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service";import{AssetResourceLoader as h}from"../scene/asset-resource-loader";import{AssetLoader as u}from"./services/asset-loader";export function initiateGame(d,f){if(0!=f.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(r);const g=e.of("default"),w=new HologyRuntime(g),v=new o(g,{inEditor:!1});var y;e.set(o,v),y=f.element,Object.assign(y.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"});const I=new i(f.element);I.renderer.shadowMap.autoUpdate=!0,e.set(i,I);const S=new r(I);e.set(r,S);const b=new s(e.get(o));e.set(s,b);const D=new l(f.dataDir),x=new p(D),G=new h;G.setDataDir(f.dataDir);const H=new u(G,x);return e.set(u,H),(()=>{t(this,void 0,void 0,(function*(){const t=e.get(a);if(yield t.start(),w.isShutdown)return;const{scene:o,actors:s}=yield n(I,f.sceneName,f.dataDir,f.shaders,f.actors,v,D,x,G);if(b.scene=o,w.isShutdown)return void I.stop();e.import([c]);for(const t of s)b.addActor(t);t.addFromScene(o),I.loop((t=>{})),w.status=5,m.value=g,g.remove(d),g.set({id:d,type:d});const r=g.get(d);m.value=null,w.gameInstance=r,r instanceof GameInstance&&r.onStart(),w._resolver(!0)}))})(),w}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(t){this.containerInstance=t,this.status=0,this.isShutdown=!1,this.ready=new Promise((t=>{this._resolver=t}))}getWorld(){return this.containerInstance.get(s)}getService(t){return this.containerInstance.get(t)}shutdown(){this.isShutdown=!0,this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(d).stop();const t=this.containerInstance.get(i);null==t||t.stop();for(const t of this.getWorld().actors)this.getWorld().removeActor(t);this.containerInstance.get(a).stop(),this.containerInstance.reset()}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -4,11 +4,10 @@ import { Observable, Subject } from "rxjs";
4
4
  import * as THREE from "three";
5
5
  import { ColorRepresentation, Object3D, Vector3 } from "three";
6
6
  import { CollisionShape } from "../../../";
7
- import { Type } from "../../../utils/type";
8
- import { BaseActor } from "../../actors/actor";
7
+ import { AbstractType } from "../../../utils/type";
8
+ import { BaseActor } from '../../actors/actor';
9
9
  import { ViewController } from "../render";
10
10
  import { World } from "../world";
11
- import { CollisionContact } from "./collision-contact";
12
11
  export declare class RayTestResult {
13
12
  _internal: RayColliderIntersection;
14
13
  actor: BaseActor;
@@ -49,6 +48,7 @@ export declare class PhysicsSystem {
49
48
  private actorBodies;
50
49
  private bodyActors;
51
50
  private eventQueue;
51
+ private fixedupdateSub;
52
52
  private readonly collisionEvents;
53
53
  readonly beforeStep: Subject<number>;
54
54
  readonly afterStep: Subject<number>;
@@ -108,25 +108,23 @@ export declare class PhysicsSystem {
108
108
  removeSceneObject(object: Object3D): void;
109
109
  private activateActorEvents;
110
110
  private _onCollisionWithActorEvent;
111
- onBeginOverlapWithActorType<T extends BaseActor, A extends BaseActor>(self: T, actorType: Type<A>): Observable<A>;
112
- onEndOverlapWithActorType<T extends BaseActor, A extends BaseActor>(self: T, actorType: Type<A>): Observable<A>;
111
+ /**
112
+ * Get a subscription to contact started events where the value of the subscription
113
+ * is some unique number identifying the object in which the actor is in contact.
114
+ */
115
+ onBeginContact(self: BaseActor): Observable<number>;
116
+ /**
117
+ * Get a subscription to contact ended events where the value of the subscription
118
+ * is some unique number identifying the object in which the actor is in contact.
119
+ */
120
+ onEndContact(self: BaseActor): Observable<number>;
121
+ onHasContactChanged(self: BaseActor): Observable<boolean>;
122
+ onBeginOverlapWithActorType<T extends BaseActor, A extends BaseActor>(self: T, actorType: AbstractType<A>): Observable<A>;
123
+ onEndOverlapWithActorType<T extends BaseActor, A extends BaseActor>(self: T, actorType: AbstractType<A>): Observable<A>;
113
124
  onBeginOverlapWithActor<T extends BaseActor, A extends BaseActor>(self: T, actor: A): Observable<A>;
114
125
  onEndOverlapWithActor<T extends BaseActor, A extends BaseActor>(self: T, actor: A): Observable<A>;
115
126
  onCollisionWithActor<A extends BaseActor, S extends BaseActor>(self: S, actor: A): Observable<A>;
116
- onCollisionWithActorType<A extends BaseActor, S extends BaseActor>(self: S, actorType: Type<A>): Observable<A>;
117
- /**
118
- * Whenever there is collision with anything in the world which is not a trigger volume?
119
- * I suppose I can filter out trigger bodies.
120
- * Only return collision contact information
121
- *
122
- * It should be possible to pass in a collision filter (mask) to be able to narrow down the search.
123
- * Collision groups should be defined in code as integers. I suppose I can also have predefined collision groups that are available both in the editor and here.
124
- *
125
- * You might want more information about the object you are colliding with.
126
- * If it is a static object, I could provide the raw threejs mesh object.
127
- * I could also provide scene object information.
128
- */
129
- onCollision<S extends BaseActor>(self: S): Observable<CollisionContact>;
127
+ onCollisionWithActorType<A extends BaseActor, S extends BaseActor>(self: S, actorType: AbstractType<A>): Observable<A>;
130
128
  updateActorTransform(actor: BaseActor): void;
131
129
  private setupWorld;
132
130
  getActorContacts(actor: BaseActor, direction: Vector3): {
@@ -1,4 +1,4 @@
1
- import{__awaiter as e,__decorate as t,__metadata as i}from"tslib";import*as o from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{Quaternion as r,RaycastResult as n,Vec3 as l}from"cannon-es";import{filter as a,map as c,Observable as d,Subject as h,takeUntil as u}from"rxjs";import*as y from"three";import{ArrowHelper as p,BufferAttribute as g,BufferGeometry as m,Group as f,LineSegments as w,Matrix4 as v,MeshBasicMaterial as x,Object3D as B,Raycaster as b,Scene as A,Vector3 as C}from"three";import{Service as D}from"typedi";import{AssetMeshInstance as z}from"../../../scene/asset-resource-loader";import{BoxCollisionShape as T,CapsuleCollisionShape as M,ConeCollisionShape as R,ConvexPolyhedronCollisionShape as S,CylinderCollisionShape as E,PhysicalShapeMesh as W,PlaneCollisionShape as _,SphereCollisionShape as F,TrimeshCollisionShape as V}from"../../../";import{LandscapeGroup as P}from"../../../scene/landscape/landscape";import{ViewController as k}from"../render";import{World as I}from"../world";import*as L from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as O}from"../../../utils/three/traverse";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new C,this.hitNormal=new C}}new n,new l,new l;export var PhysicsBodyType;!function(e){e[e.dynamic=1]="dynamic",e[e.static=2]="static",e[e.kinematic=4]="kinematic",e[e.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));let j=class{set showDebug(e){this.shouldRenderDebug=e,this.debugMesh&&(this.debugMesh.visible=e)}get showDebug(){return this.shouldRenderDebug}constructor(e,t){this.viewController=e,this.gameWorld=t,this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.collisionEvents=new h,this.beforeStep=new h,this.afterStep=new h,this.shouldRenderDebug=!1,this._raycaster=new b,this._reusableResult=new RayTestResult,this._raytestDiff=new C,this._raytestDirection=new C,this.controlledActors=new Set,this.ready=this.setup()}createDebugMesh(){return new w(new m,new x({color:255}))}start(){return e(this,void 0,void 0,(function*(){return yield this.ready,this.handleTick(),this.ready}))}renderDebug(){null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.gameWorld.scene.add(this.debugMesh));const e=this.world.debugRender();this.debugMesh.geometry.setAttribute("position",new g(e.vertices,3))}setup(){return e(this,void 0,void 0,(function*(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=yield X(),this.eventQueue=new o.EventQueue(!0),this.setupWorld()}))}handleTick(){this.viewController.onUpdate().subscribe((e=>{this.beforeStep.next(e),this.updatePhysics(),this.afterStep.next(e),this.showDebug&&this.renderDebug(),this.world.bodies.forEach((e=>{var t,i,o;if(e.isFixed())return;const s=null!==(t=this.staticMeshes.get(e))&&void 0!==t?t:null===(i=this.bodyActors.get(e))||void 0===i?void 0:i.object;var r,n;null!=s&&(Y(s.position,e.translation()),(e.isDynamic()||e.isKinematic()&&!this.controlledActors.has(null===(o=this.bodyActors.get(e))||void 0===o?void 0:o.id))&&(r=s.quaternion,n=e.rotation(),r.x=n.x,r.y=n.y,r.z=n.z,r.w=n.w))}))}))}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(){this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents(((e,t,i)=>{this.collisionEvents.next({handle1:e,handle2:t,started:i}),this.collisionEvents.next({handle1:t,handle2:e,started:i})}))}rayTestFromCamera(e,t,i){this._raycaster.setFromCamera(K,this.viewController.getCamera());const o=this._raycaster.ray.origin,s=this._raycaster.ray.direction.multiplyScalar(e).add(o);return this.rayTest(o,s,t,i)}rayTest(e,t,i,s){var r,n;null==i&&(i=this._reusableResult);const l=this._raytestDiff,a=this._raytestDirection;if(l.subVectors(t,e),a.copy(l).normalize(),0===a.length())return console.warn("Ray test called with to and from being equal"),i;const c=new o.Ray(e,a),d=l.length(),h=this.world.castRayAndGetNormal(c,d,!1,void 0,void 0,void 0,null!=(null==s?void 0:s.excludeActor)?this.actorBodies.get(s.excludeActor.id):void 0);if(i.hasHit=null!=h,i.hasHit){const t=c.pointAt(h.toi);i._internal=h,Y(i.hitNormal,h.normal),Y(i.hitPoint,t),i.distance=$.subVectors(i.hitPoint,e).length();const o=this.world.bodies.getAll().find((e=>function(e,t){for(let i=0,o=e.numColliders();i<o;i++){const o=e.collider(i);if(t(o))return o}}(e,(e=>e===h.collider))));i.actor=null!=o?this.bodyActors.get(o):null}if(this.showDebug){const t=new p(a,e,d,null!==(r=null==s?void 0:s.debugColor)&&void 0!==r?r:255);this.gameWorld.scene.add(t),setTimeout((()=>this.gameWorld.scene.remove(t)),null!==(n=null==s?void 0:s.debugLifetime)&&void 0!==n?n:200)}return this._reusableResult}setGravity(e,t,i){this.world.gravity.x=e,this.world.gravity.y=t,this.world.gravity.z=i}getGravity(){return Q.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(e){this.addRecursively(e)}addRecursively(e){var t,i;if(this.removeSceneObject(e),!function(e){var t,i;if(null!=(null===(t=e.userData)||void 0===t?void 0:t.src)){return"actor"===(null===(i=e.userData)||void 0===i?void 0:i.src).type}return!1}(e))if(e instanceof W&&null!=e.collisionShape){const t=this.createStaticBody(e,[e.collisionShape]);this.staticMeshes.set(t,e),this.staticBodies.set(e,t)}else if(e instanceof z&&!1!==(null===(i=null===(t=e.userData)||void 0===t?void 0:t.src)||void 0===i?void 0:i.collisionDetection))if(e.children[0]&&e.children[0].instanceMatrix)this.createForInstancedMesh(e.children[0],e.collisionShapes);else{const t=this.createStaticBody(e,e.collisionShapes);this.staticMeshes.set(t,e),this.staticBodies.set(e,t)}else e instanceof P?this.addLandscapeGroup(e):(e instanceof f||e instanceof A)&&e.children.forEach((e=>this.addRecursively(e)))}createForInstancedMesh(e,t){const i=new v;for(let o=0;o<e.count;o++){const s=new B;s.matrix.identity(),i.fromArray(e.instanceMatrix.array,16*o),s.applyMatrix4(i);this.createStaticBody(s,t)}}getCharacterController(e=.01){var t;return null===(t=this.world)||void 0===t?void 0:t.createCharacterController(e)}getActorComputedMovement(e,t,i){const o=this.actorBodies.get(e.id);this.controlledActors.add(e.id);const r=o.collider(0);t.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,null,te);const n=t.computedMovement();return Y(ee,n),ee}setNextKinematicTranslation(e,t){const i=this.actorBodies.get(e.id),o=i.translation();o.x+=t.x,o.y+=t.y,o.z+=t.z,null==i||i.setNextKinematicTranslation(o)}setAngularVelocity(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.setAngvel(U,!0)}setLinearVelocity(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.setLinvel(U,!0)}getLinearVelocity(e,t=new C){const i=this.actorBodies.get(e.id).linvel();return t.x=i.x,t.y=i.y,t.z=i.z,t}getAngularVelocity(e,t=new C){const i=this.actorBodies.get(e.id).angvel();return t.x=i.x,t.y=i.y,t.z=i.z,t}setLinearDamping(e,t){const i=this.actorBodies.get(e.id);null==i||i.setLinearDamping(t)}setAngularDamping(e,t){const i=this.actorBodies.get(e.id);null==i||i.setAngularDamping(t)}createCharacterCollision(){return new o.CharacterCollision}addLandscapeGroup(e){const t=e.userData.src,i=t.landscape.heightMaps;for(const r of e.sections){this.staticBodies.has(r)&&this.world.removeRigidBody(this.staticBodies.get(r));const e=t.landscape.options.density+1,n=t.landscape.options.sectionSize,l=new Array(e);for(let t=0;t<e;t++)l[t]=new Array(e).fill(0);const a=i.find((e=>e.x===r.x&&e.y==r.y));if(null!=a)for(const t of a.points){if(null==l[t.i%e])continue;const i=e-1-Math.floor(t.i/e);i in l[t.i%e]?l[t.i%e][i]=t.y/n:console.warn("wrong index",{points:l,point:t,i:t.i%e,k:i,heightMap:a})}const c=t.landscape.options.density,d=l.flatMap((e=>e.reverse())),h=o.ColliderDesc.heightfield(c,c,new Float32Array(d),new o.Vector3(n,n,n));var s=r.getWorldPosition(new C);const u=this.world.createRigidBody(o.RigidBodyDesc.fixed()),y=new o.Vector3(0,0,0);J(y,s),u.setTranslation(y,!1),this.world.createCollider(h,u),this.staticBodies.set(r,u)}}addActor(e,t,i={}){var s,r;if(0==t.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(e);const n=e.object;let l;switch(null!==(s=i.type)&&void 0!==s?s:PhysicsBodyType.static){case PhysicsBodyType.dynamic:l=o.RigidBodyDesc.dynamic(),l.mass=null!==(r=i.mass)&&void 0!==r?r:1;break;case PhysicsBodyType.kinematic:l=o.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:l=o.RigidBodyDesc.kinematicVelocityBased();break;default:l=(i.isTrigger,o.RigidBodyDesc.kinematicVelocityBased())}const a=this.world.createRigidBody(l);a.enableCcd(1==i.continousCollisionDetection);for(const e of t)this.addShape(a,e,n);Z(a,(e=>{null!=i.isTrigger&&(e.setSensor(i.isTrigger),e.setActiveCollisionTypes(o.ActiveCollisionTypes.ALL)),null!=i.friction&&e.setFriction(i.friction),null!=i.restitution&&e.setDensity(i.restitution),null!=i.mass&&e.setMass(i.mass),null!=i.restitution&&e.setRestitution(i.restitution)})),G(a,n),this.actorBodies.set(e.id,a),this.bodyActors.set(a,e)}applyTorque(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.addTorque(U,!0)}applyTorqueImpulse(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.applyTorqueImpulse(U,!0)}resetForces(e){const t=this.actorBodies.get(e.id);null==t||t.resetForces(!1)}resetTorques(e){const t=this.actorBodies.get(e.id);null==t||t.resetTorques(!1)}applyForce(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.addForce(U,!0)}applyImpulse(e,t){const i=this.actorBodies.get(e.id);U.x=t.x,U.y=t.y,U.z=t.z,null==i||i.applyImpulse(U,!0)}applyLocalForce(e,t,i){const o=this.actorBodies.get(e.id);J(U,t),null==i?null==o||o.addForce(U,!0):(J(H,i),null==o||o.addForceAtPoint(U,H,!0))}applyLocalImpulse(e,t,i){const o=this.actorBodies.get(e.id);J(U,t),null==i?o.applyImpulse(U,!0):(J(H,i),o.applyImpulseAtPoint(U,H,!0))}removeActor(e){this.controlledActors.delete(e.id);const t=this.actorBodies.get(e.id);null!=t&&(this.bodyActors.delete(t),this.world.removeRigidBody(t)),this.actorBodies.delete(e.id)}removeSceneObject(e){let t=this.staticBodies.get(e);null!=t&&this.world.getRigidBody(t.handle)&&this.world.removeRigidBody(t)}activateActorEvents(e){const t=this.actorBodies.get(e.id);t&&Z(t,(e=>e.setActiveEvents(o.ActiveEvents.COLLISION_EVENTS)))}_onCollisionWithActorEvent(e,t,i){return this.activateActorEvents(e),this.collisionEvents.pipe(u(e.disposed),a((({started:e})=>e===i)),c((({handle1:e,handle2:t,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(e).parent()),a2:this.bodyActors.get(this.world.getCollider(t).parent()),started:i}))),a((({a1:i,a2:o})=>null!=i&&null!=o&&i.id===e.id&&t(i,o))),c((({a2:e})=>e)))}onBeginOverlapWithActorType(e,t){return this._onCollisionWithActorEvent(e,((e,i)=>i instanceof t),!0)}onEndOverlapWithActorType(e,t){return this._onCollisionWithActorEvent(e,((e,i)=>i instanceof t),!1)}onBeginOverlapWithActor(e,t){return this._onCollisionWithActorEvent(e,((e,i)=>t.id===i.id),!0)}onEndOverlapWithActor(e,t){return this._onCollisionWithActorEvent(e,((e,i)=>t.id===i.id),!1)}onCollisionWithActor(e,t){return this.onBeginOverlapWithActor(e,t)}onCollisionWithActorType(e,t){return this.onBeginOverlapWithActorType(e,t)}onCollision(e){return new d((t=>{if(null==this.actorBodies.get(e.id))throw new Error("Actor must be added to the physics system before setting up collision event handler");return()=>{}}))}updateActorTransform(e){const t=this.actorBodies.get(e.id);null!=t?G(t,e.object):console.warn("Actor has not been added to physics world",e)}setupWorld(){const e=new o.World({x:0,y:-9.81,z:0});this.world=e,e.maxVelocityIterations=4}getActorContacts(e,t){const i=this.actorBodies.get(e.id);if(i&&i.numColliders()>0){const s=i.collider(0);let r=s.shape,n=s.translation(),l=s.rotation(),a=t,c=.3;const d=this.world.castShape(n,l,a,r,c,!0,null,null,null,this.actorBodies.get(e.id),(e=>e.shape.type!=o.ShapeType.HeightField));if(null!=d){const e=new C,t=new C,i=new C;return Y(e,d.witness2),Y(t,d.witness1),Y(i,d.normal1),i.negate(),[{ri:e,rj:t,ni:i}]}return[]}return console.warn("Actor is not added to the physics system"),[]}stop(){this.world.free()}createStaticBody(e,t){const i=this.world.createRigidBody(o.RigidBodyDesc.kinematicPositionBased());for(const o of t)this.addShape(i,o,e);return G(i,e),i}addShape(e,t,i){const o=this.createShape(t,i.scale);o.friction=.1;const s=t.offset.clone().multiply(i.scale);var n,l;J(o.translation,s),n=o.rotation,l=(new r).setFromEuler(t.rotation.x,t.rotation.y,t.rotation.z),n.x=l.x,n.y=l.y,n.z=l.z,n.w=l.w;this.world.createCollider(o,e)}createShape(e,t){if(e instanceof T)return o.ColliderDesc.cuboid(e.dimensions.x*t.x/2,e.dimensions.y*t.y/2,e.dimensions.z*t.z/2);if(e instanceof M){return o.ColliderDesc.capsule(e.length/2*t.y,e.radius*Math.max(t.z,t.x))}if(e instanceof V){const t=null!=e.geometry.getIndex()?e.geometry:L.mergeVertices(e.geometry);return o.ColliderDesc.trimesh(new Float32Array(t.getAttribute("position").array),new Uint32Array(t.getIndex().array))}if(e instanceof S){let i;e.mesh instanceof y.Mesh?i=e.mesh.geometry:e.mesh instanceof y.BufferGeometry?i=e.mesh:console.log("Unknownd shape",{shapeInfo:e});const s=new Float32Array(i.getAttribute("position").array);if(e.mesh instanceof y.Mesh){const t=O(e.mesh);for(let e=0;e<s.length;e+=3)s[e]*=t.x,s[e+1]*=t.y,s[e+2]*=t.z}for(let e=0;e<s.length;e+=3)s[e]*=t.x,s[e+1]*=t.y,s[e+2]*=t.z;return o.ColliderDesc.convexHull(s)}return e instanceof F?o.ColliderDesc.ball(e.radius*Math.max(t.x,t.y,t.z)):e instanceof E?o.ColliderDesc.cylinder(e.height/2*t.y,e.radiusTop*Math.max(t.z,t.x)):e instanceof R?o.ColliderDesc.cone(e.height*t.y,e.radiusBottom/2*Math.max(t.z,t.x)):e instanceof _?o.ColliderDesc.cuboid(e.width/2*t.x,e.height/2*t.y,.01):(console.error("Unsupported shape",e),o.ColliderDesc.cuboid(1,1,1))}};j=t([D(),i("design:paramtypes",[k,I])],j);export{j as PhysicsSystem};const N=new C,q=new y.Quaternion;function G(e,t){const i=t.getWorldPosition(N),s=t.getWorldQuaternion(q);e.setTranslation(new o.Vector3(i.x,i.y,i.z),!1),e.setRotation(new o.Quaternion(s.x,s.y,s.z,s.w),!1)}const Q=new C,U=new o.Vector3(0,0,0),H=new o.Vector3(0,0,0),K=(new C,{x:0,y:0}),X=()=>e(void 0,void 0,void 0,(function*(){let e=yield import("@dimforge/rapier3d-compat");return yield e.init(),e}));function J(e,t){e.x=t.x,e.y=t.y,e.z=t.z}function Y(e,t){e.x=t.x,e.y=t.y,e.z=t.z}function Z(e,t){for(let i=0,o=e.numColliders();i<o;i++){t(e.collider(i))}}const $=new C,ee=new C,te=e=>!e.isSensor();
1
+ import{__awaiter as t,__decorate as e,__metadata as i}from"tslib";import*as s from"@dimforge/rapier3d-compat";import{QueryFilterFlags as o}from"@dimforge/rapier3d-compat";import{Quaternion as n,RaycastResult as r,Vec3 as a}from"cannon-es";import{BehaviorSubject as l,distinctUntilChanged as d,filter as c,map as h,Subject as u,takeUntil as y}from"rxjs";import*as p from"three";import{ArrowHelper as g,BufferAttribute as m,BufferGeometry as v,Group as f,LineSegments as w,Matrix4 as x,MeshBasicMaterial as b,Object3D as B,Raycaster as A,Scene as C,Vector3 as D}from"three";import{Service as z}from"typedi";import{AssetMeshInstance as T}from"../../../scene/asset-resource-loader";import{BoxCollisionShape as M,CapsuleCollisionShape as E,ConeCollisionShape as S,ConvexPolyhedronCollisionShape as R,CylinderCollisionShape as W,PhysicalShapeMesh as _,PlaneCollisionShape as V,SphereCollisionShape as F,TrimeshCollisionShape as P}from"../../../";import{LandscapeGroup as k}from"../../../scene/landscape/landscape";import{ViewController as I}from"../render";import{World as L}from"../world";import*as O from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as N}from"../../../utils/three/traverse";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new D,this.hitNormal=new D}}new r,new a,new a;export var PhysicsBodyType;!function(t){t[t.dynamic=1]="dynamic",t[t.static=2]="static",t[t.kinematic=4]="kinematic",t[t.kinematicVelocityBased=8]="kinematicVelocityBased"}(PhysicsBodyType||(PhysicsBodyType={}));let j=class{set showDebug(t){this.shouldRenderDebug=t,this.debugMesh&&(this.debugMesh.visible=t)}get showDebug(){return this.shouldRenderDebug}constructor(t,e){this.viewController=t,this.gameWorld=e,this.staticMeshes=new Map,this.staticBodies=new Map,this.actorBodies=new Map,this.bodyActors=new Map,this.collisionEvents=new u,this.beforeStep=new u,this.afterStep=new u,this.shouldRenderDebug=!1,this._raycaster=new A,this._reusableResult=new RayTestResult,this._raytestDiff=new D,this._raytestDirection=new D,this.controlledActors=new Set,this.ready=this.setup()}createDebugMesh(){return new w(new v,new b({color:255}))}start(){return t(this,void 0,void 0,(function*(){return yield this.ready,this.handleTick(),this.ready}))}renderDebug(){null==this.debugMesh&&(this.debugMesh=this.createDebugMesh(),this.debugMesh.visible=this.shouldRenderDebug,this.debugMesh.raycast=function(){},this.gameWorld.scene.add(this.debugMesh));const t=this.world.debugRender();this.debugMesh.geometry.setAttribute("position",new m(t.vertices,3))}setup(){return t(this,void 0,void 0,(function*(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=yield J(),this.eventQueue=new s.EventQueue(!0),this.setupWorld()}))}handleTick(){this.fixedupdateSub=this.viewController.onUpdate().subscribe((t=>{t=Math.min(.1,t),this.beforeStep.next(t),this.updatePhysics(t),this.afterStep.next(t),this.showDebug&&this.renderDebug(),this.world.bodies.forEach((t=>{var e,i,s;if(t.isFixed())return;const o=null!==(e=this.staticMeshes.get(t))&&void 0!==e?e:null===(i=this.bodyActors.get(t))||void 0===i?void 0:i.object;var n,r;null!=o&&(o.parent instanceof C&&(Z(o.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(null===(s=this.bodyActors.get(t))||void 0===s?void 0:s.id))&&(n=o.quaternion,r=t.rotation(),n.x=r.x,n.y=r.y,n.z=r.z,n.w=r.w)))}))}))}_updateWorld(){this.world.timestep=0,this.world.step()}updatePhysics(t){this.world.timestep=t,this.world.step(this.eventQueue),this.eventQueue.drainCollisionEvents(((t,e,i)=>{this.collisionEvents.next({handle1:t,handle2:e,started:i}),this.collisionEvents.next({handle1:e,handle2:t,started:i})}))}rayTestFromCamera(t,e,i){this._raycaster.setFromCamera(X,this.viewController.getCamera());const s=this._raycaster.ray.origin,o=this._raycaster.ray.direction.multiplyScalar(t).add(s);return this.rayTest(s,o,e,i)}rayTest(t,e,i,o){var n,r;null==i&&(i=this._reusableResult);const a=this._raytestDiff,l=this._raytestDirection;if(a.subVectors(e,t),l.copy(a).normalize(),0===l.length())return console.warn("Ray test called with to and from being equal"),i;const d=new s.Ray(t,l),c=a.length(),h=this.world.castRayAndGetNormal(d,c,!1,void 0,void 0,void 0,null!=(null==o?void 0:o.excludeActor)?this.actorBodies.get(o.excludeActor.id):void 0);if(i.hasHit=null!=h,i.hasHit){const e=d.pointAt(h.toi);i._internal=h,Z(i.hitNormal,h.normal),Z(i.hitPoint,e),i.distance=tt.subVectors(i.hitPoint,t).length();const s=this.world.bodies.getAll().find((t=>function(t,e){for(let i=0,s=t.numColliders();i<s;i++){const s=t.collider(i);if(e(s))return s}}(t,(t=>t===h.collider))));i.actor=null!=s?this.bodyActors.get(s):null}if(this.showDebug){const e=new g(l,t,c,null!==(n=null==o?void 0:o.debugColor)&&void 0!==n?n:255);this.gameWorld.scene.add(e),setTimeout((()=>this.gameWorld.scene.remove(e)),null!==(r=null==o?void 0:o.debugLifetime)&&void 0!==r?r:200)}return this._reusableResult}setGravity(t,e,i){this.world.gravity.x=t,this.world.gravity.y=e,this.world.gravity.z=i}getGravity(){return H.set(this.world.gravity.x,this.world.gravity.y,this.world.gravity.z)}addFromScene(t){this.addRecursively(t);for(const t of this.staticBodies.values())$(t,(t=>t.setActiveEvents(s.ActiveEvents.COLLISION_EVENTS)))}addRecursively(t){var e,i;if(this.removeSceneObject(t),!function(t){var e,i;if(null!=(null===(e=t.userData)||void 0===e?void 0:e.src)){return"actor"===(null===(i=t.userData)||void 0===i?void 0:i.src).type}return!1}(t))if(t instanceof _&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape]);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof T&&!1!==(null===(i=null===(e=t.userData)||void 0===e?void 0:e.src)||void 0===i?void 0:i.collisionDetection))if(t.children[0]&&t.children[0].instanceMatrix)this.createForInstancedMesh(t.children[0],t.collisionShapes);else{const e=this.createStaticBody(t,t.collisionShapes);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else t instanceof k?this.addLandscapeGroup(t):(t instanceof f||t instanceof C)&&t.children.forEach((t=>this.addRecursively(t)))}createForInstancedMesh(t,e){const i=new x;for(let s=0;s<t.count;s++){const o=new B;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*s),o.applyMatrix4(i);this.createStaticBody(o,e)}}getCharacterController(t=.01){var e;return null===(e=this.world)||void 0===e?void 0:e.createCharacterController(t)}getActorComputedMovement(t,e,i){const s=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const n=s.collider(0);e.computeColliderMovement(n,i,o.EXCLUDE_SENSORS,null,it);const r=e.computedMovement();return Z(et,r),et}setNextKinematicTranslation(t,e){const i=this.actorBodies.get(t.id),s=i.translation();s.x+=e.x,s.y+=e.y,s.z+=e.z,null==i||i.setNextKinematicTranslation(s)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.setAngvel(U,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.setLinvel(U,!0)}getLinearVelocity(t,e=new D){const i=this.actorBodies.get(t.id).linvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}getAngularVelocity(t,e=new D){const i=this.actorBodies.get(t.id).angvel();return e.x=i.x,e.y=i.y,e.z=i.z,e}setLinearDamping(t,e){const i=this.actorBodies.get(t.id);null==i||i.setLinearDamping(e)}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);null==i||i.setAngularDamping(e)}createCharacterCollision(){return new s.CharacterCollision}addLandscapeGroup(t){const e=t.userData.src,i=e.landscape.heightMaps;for(const n of t.sections){this.staticBodies.has(n)&&this.world.removeRigidBody(this.staticBodies.get(n));const t=e.landscape.options.density+1,r=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const l=i.find((t=>t.x===n.x&&t.y==n.y));if(null!=l)for(const e of l.points){if(null==a[e.i%t])continue;const i=t-1-Math.floor(e.i/t);i in a[e.i%t]?a[e.i%t][i]=e.y/r:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:l})}const d=e.landscape.options.density,c=a.flatMap((t=>t.reverse())),h=s.ColliderDesc.heightfield(d,d,new Float32Array(c),new s.Vector3(r,r,r));var o=n.getWorldPosition(new D);const u=this.world.createRigidBody(s.RigidBodyDesc.fixed()),y=new s.Vector3(0,0,0);Y(y,o),u.setTranslation(y,!1),this.world.createCollider(h,u),this.staticBodies.set(n,u)}}addActor(t,e,i={}){var o,n;if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const r=t.object;let a;switch(null!==(o=i.type)&&void 0!==o?o:PhysicsBodyType.static){case PhysicsBodyType.dynamic:a=s.RigidBodyDesc.dynamic(),a.mass=null!==(n=i.mass)&&void 0!==n?n:1;break;case PhysicsBodyType.kinematic:a=s.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:a=s.RigidBodyDesc.kinematicVelocityBased();break;default:a=(i.isTrigger,s.RigidBodyDesc.kinematicVelocityBased())}const l=this.world.createRigidBody(a);l.enableCcd(1==i.continousCollisionDetection);for(const t of e)this.addShape(l,t,r);$(l,(t=>{null!=i.isTrigger&&(t.setSensor(i.isTrigger),t.setActiveCollisionTypes(s.ActiveCollisionTypes.ALL),t.setActiveEvents(s.ActiveEvents.COLLISION_EVENTS)),null!=i.friction&&t.setFriction(i.friction),null!=i.restitution&&t.setDensity(i.restitution),null!=i.mass&&t.setMass(i.mass),null!=i.restitution&&t.setRestitution(i.restitution)})),Q(l,r),this.actorBodies.set(t.id,l),this.bodyActors.set(l,t)}applyTorque(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.addTorque(U,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.applyTorqueImpulse(U,!0)}resetForces(t){const e=this.actorBodies.get(t.id);null==e||e.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);null==e||e.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.addForce(U,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);U.x=e.x,U.y=e.y,U.z=e.z,null==i||i.applyImpulse(U,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);Y(U,e),null==i?null==s||s.addForce(U,!0):(Y(K,i),null==s||s.addForceAtPoint(U,K,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);Y(U,e),null==i?s.applyImpulse(U,!0):(Y(K,i),s.applyImpulseAtPoint(U,K,!0))}removeActor(t){this.controlledActors.delete(t.id);const e=this.actorBodies.get(t.id);null!=e&&(this.bodyActors.delete(e),this.world.removeRigidBody(e)),this.actorBodies.delete(t.id)}removeSceneObject(t){let e=this.staticBodies.get(t);null!=e&&this.world.getRigidBody(e.handle)&&this.world.removeRigidBody(e)}activateActorEvents(t){this.actorBodies.get(t.id)}_onCollisionWithActorEvent(t,e,i){return this.activateActorEvents(t),this.collisionEvents.pipe(y(t.disposed),c((({started:t})=>t===i)),h((({handle1:t,handle2:e,started:i})=>({a1:this.bodyActors.get(this.world.getCollider(t).parent()),a2:this.bodyActors.get(this.world.getCollider(e).parent()),started:i}))),c((({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s))),h((({a2:t})=>t)))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(y(t.disposed),c((t=>t.started)),c((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),h((t=>t.handle2)))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(y(t.disposed),c((t=>!t.started)),c((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),h((t=>t.handle2)))}onHasContactChanged(t){const e=new Set,i=new l(!1);return this.onBeginContact(t).subscribe((t=>{e.add(t),i.next(e.size>0)})),this.onEndContact(t).subscribe((t=>{e.delete(t),i.next(e.size>0)})),i.pipe(d())}onBeginOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,((t,i)=>i instanceof e),!0)}onEndOverlapWithActorType(t,e){return this._onCollisionWithActorEvent(t,((t,i)=>i instanceof e),!1)}onBeginOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,((t,i)=>e.id===i.id),!0)}onEndOverlapWithActor(t,e){return this._onCollisionWithActorEvent(t,((t,i)=>e.id===i.id),!1)}onCollisionWithActor(t,e){return this.onBeginOverlapWithActor(t,e)}onCollisionWithActorType(t,e){return this.onBeginOverlapWithActorType(t,e)}updateActorTransform(t){const e=this.actorBodies.get(t.id);null!=e?Q(e,t.object):console.warn("Actor has not been added to physics world",t)}setupWorld(){const t=new s.World({x:0,y:-9.81,z:0});this.world=t,t.maxVelocityIterations=4}getActorContacts(t,e){const i=this.actorBodies.get(t.id);if(i&&i.numColliders()>0){const o=i.collider(0);let n=o.shape,r=o.translation(),a=o.rotation(),l=e,d=.3;const c=this.world.castShape(r,a,l,n,d,!0,null,null,null,this.actorBodies.get(t.id),(t=>t.shape.type!=s.ShapeType.HeightField));if(null!=c){const t=new D,e=new D,i=new D;return Z(t,c.witness2),Z(e,c.witness1),Z(i,c.normal1),i.negate(),[{ri:t,rj:e,ni:i}]}return[]}return console.warn("Actor is not added to the physics system"),[]}stop(){var t,e,i;null===(t=this.world)||void 0===t||t.bodies.forEach((t=>this.world.removeRigidBody(t))),null===(e=this.world)||void 0===e||e.free(),null===(i=this.fixedupdateSub)||void 0===i||i.unsubscribe()}createStaticBody(t,e){const i=this.world.createRigidBody(s.RigidBodyDesc.kinematicPositionBased());for(const s of e)this.addShape(i,s,t);return Q(i,t),i}addShape(t,e,i){const s=this.createShape(e,i.scale);s.friction=.1;const o=e.offset.clone().multiply(i.scale);var r,a;Y(s.translation,o),r=s.rotation,a=(new n).setFromEuler(e.rotation.x,e.rotation.y,e.rotation.z),r.x=a.x,r.y=a.y,r.z=a.z,r.w=a.w;this.world.createCollider(s,t)}createShape(t,e){if(t instanceof M)return s.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof E){return s.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof P){const e=null!=t.geometry.getIndex()?t.geometry:O.mergeVertices(t.geometry);return s.ColliderDesc.trimesh(new Float32Array(e.getAttribute("position").array),new Uint32Array(e.getIndex().array))}if(t instanceof R){let i;t.mesh instanceof p.Mesh?i=t.mesh.geometry:t.mesh instanceof p.BufferGeometry?i=t.mesh:console.log("Unknownd shape",{shapeInfo:t});const o=new Float32Array(i.getAttribute("position").array);if(t.mesh instanceof p.Mesh){const e=N(t.mesh);for(let t=0;t<o.length;t+=3)o[t]*=e.x,o[t+1]*=e.y,o[t+2]*=e.z}for(let t=0;t<o.length;t+=3)o[t]*=e.x,o[t+1]*=e.y,o[t+2]*=e.z;return s.ColliderDesc.convexHull(o)}return t instanceof F?s.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z)):t instanceof W?s.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof S?s.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof V?s.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.01):(console.error("Unsupported shape",t),s.ColliderDesc.cuboid(1,1,1))}};j=e([z(),i("design:paramtypes",[I,L])],j);export{j as PhysicsSystem};const q=new D,G=new p.Quaternion;function Q(t,e){const i=e.getWorldPosition(q),o=e.getWorldQuaternion(G);t.setTranslation(new s.Vector3(i.x,i.y,i.z),!1),t.setRotation(new s.Quaternion(o.x,o.y,o.z,o.w),!1)}const H=new D,U=new s.Vector3(0,0,0),K=new s.Vector3(0,0,0),X=(new D,{x:0,y:0}),J=()=>t(void 0,void 0,void 0,(function*(){let t=yield import("@dimforge/rapier3d-compat");return yield t.init(),t}));function Y(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function Z(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function $(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const tt=new D,et=new D,it=t=>!t.isSensor();
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -9,6 +9,10 @@ export declare class ViewController {
9
9
  private readonly lateTick;
10
10
  readonly audioListener: THREE.AudioListener;
11
11
  constructor(view: RenderingView);
12
+ set fpsCap(fps: number);
13
+ get fpsCap(): number;
14
+ set showStats(value: boolean);
15
+ get showStats(): boolean;
12
16
  onUpdate(actor?: any): Observable<number>;
13
17
  onLateUpdate(actor?: any): Observable<number>;
14
18
  setCamera(camera: Camera | CameraActor): void;
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Service as i}from"typedi";import{RenderingView as s}from"../../rendering";import{Subject as r,takeUntil as a}from"rxjs";import*as n from"three";import{CameraActor as o}from"../../gameplay/actors/builtin/camera-actor";let p=class{constructor(e){this.view=e,this.tick=new r,this.lateTick=new r,this.audioListener=new n.AudioListener,e.onLoop((e=>{this.tick.next(e),this.lateTick.next(e)})),e.camera.add(this.audioListener)}onUpdate(e){return null!=e&&this.tick.pipe(a(e.disposed)),this.tick}onLateUpdate(e){return null!=e&&this.lateTick.pipe(a(e.disposed)),this.lateTick}setCamera(e){const t=e instanceof o?e.camera.instance:e;this.view.setCamera(t),t.add(this.audioListener)}getCamera(){return this.view.camera}get htmlElement(){return this.view.container}pauseRendering(){this.view.paused=!0}unpauseRendering(){this.view.paused=!1}dispose(){this.view.stop()}};p=e([i(),t("design:paramtypes",[s])],p);export{p as ViewController};
1
+ import{__decorate as t,__metadata as e}from"tslib";import{Service as i}from"typedi";import{RenderingView as s}from"../../rendering";import{Subject as a,takeUntil as r}from"rxjs";import*as o from"three";import{CameraActor as n}from"../../gameplay/actors/builtin/camera-actor";let p=class{constructor(t){this.view=t,this.tick=new a,this.lateTick=new a,this.audioListener=new o.AudioListener,t.onLoop((t=>{this.tick.next(t),this.lateTick.next(t)})),t.camera.add(this.audioListener),window.hology_view=this}set fpsCap(t){this.view.fpsCap=t}get fpsCap(){return this.view.fpsCap}set showStats(t){this.view.showStats=t}get showStats(){return this.view.showStats}onUpdate(t){return null!=t&&this.tick.pipe(r(t.disposed)),this.tick}onLateUpdate(t){return null!=t&&this.lateTick.pipe(r(t.disposed)),this.lateTick}setCamera(t){const e=t instanceof n?t.camera.instance:t;this.view.setCamera(e),e.add(this.audioListener)}getCamera(){return this.view.camera}get htmlElement(){return this.view.container}pauseRendering(){this.view.paused=!0}unpauseRendering(){this.view.paused=!1}dispose(){this.view.stop()}};p=t([i(),e("design:paramtypes",[s])],p);export{p as ViewController};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -36,6 +36,10 @@ export declare class RenderingView {
36
36
  private onLoopCallbacks;
37
37
  onLoop(onFrame: (deltaTime: number) => any): void;
38
38
  removeOnLoop(onFrame: (deltaTime: number) => any): void;
39
+ private stats;
40
+ private _showStats;
41
+ set showStats(value: boolean);
42
+ get showStats(): boolean;
39
43
  loop(onFrame: (deltaTime: number) => any, showStats?: boolean): void;
40
44
  private insetHeight;
41
45
  private insetWidth;
package/dist/rendering.js CHANGED
@@ -1,4 +1,4 @@
1
- import*as e from"three";import{Mesh as t,Matrix4 as i,ShaderMaterial as r,PerspectiveCamera as s,ShaderChunk as n}from"three";import{EffectComposer as a}from"three-stdlib";import{RenderPass as o}from"three-stdlib";import{ShaderPass as h}from"three-stdlib";import{FXAAShader as d}from"three-stdlib";import{CSM as l}from"three-stdlib";import{CSMUtil as c}from"./csm";import{GammaCorrectionShader as m}from"three-stdlib";import{Reflector as p}from"three-stdlib";import{depthUniformName as u,resolutionUniformName as g,supportsDepthTextureExtension as v,nearUniformName as f,farUniformName as w}from"./shader-nodes/depth";import{elapsedTimeUniformName as x}from"./shader-nodes/time";import{OutlinePass as b}from"./utils/three/outline-pass";import C from"./utils/three/stats";import{lambertVertexShaderOverride as R}from"./rendering/shader-override";import{DepthPass as y}from"./utils/three/depth-pass";const P=new e.MeshDepthMaterial;P.depthPacking=e.RGBADepthPacking,P.blending=e.NoBlending;n.lights_pars_begin;n.lights_lambert_vertex=R;export class RenderingView{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof s&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(this.container.clientWidth,this.container.clientHeight),this.composer.setSize(this.container.clientWidth*this.resolutionScale,this.container.clientHeight*this.resolutionScale),this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight)}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=1,this.onResize=()=>{this.resizeRender(),this.paused||this.composer.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,window.renderer=this.renderer=new e.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new e.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.composer=new a(this.renderer);var r=t.clientWidth/t.clientHeight;const s=new e.PerspectiveCamera(45,r,.5,500);s.layers.enable(19),this.setCamera(s),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=e.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=e.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,c.renderingView=this,c.patchThreeAdd(),this.isDepthTextureExtensionSupported=v(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=RenderingView.createDepthRenderTarget(this.renderer,this.container);const n=new o(this.scene,this.camera);if(this.composer.addPass(n),this.outlinePass=new b(new e.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),!0===i.enableOutlines){this.outlinePass.edgeThickness=0,this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.composer.addPass(this.outlinePass);const e=new h(d);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e);var l=new h(m);l.clear=!1,this.composer.addPass(l)}}setCamera(t){this.camera=t,this.composer.passes.forEach((e=>{e instanceof o?e.camera=t:e instanceof b?e.renderCamera=t:e instanceof y&&(e.camera=t)})),null==this.csm?this.csm=new l({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new e.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof s&&(this.csm.maxFar=this.camera.far)),this.csm.updateFrustums()}setSelectedObjects(e){const t=new Map;for(const i of e)t.set(i.uuid,i);for(const i of e)i.traverse((e=>{e.uuid!==i.uuid&&t.has(e.uuid)&&t.delete(e.uuid)}));this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(t,i){var r=!!t.extensions.get("WEBGL_depth_texture");const s=new e.WebGLRenderTarget(i.clientWidth*t.getPixelRatio(),i.clientHeight*t.getPixelRatio());return s.texture.minFilter=e.NearestFilter,s.texture.magFilter=e.NearestFilter,s.texture.generateMipmaps=!1,s.stencilBuffer=!1,!0===r&&(s.depthTexture=new e.DepthTexture(128,128),s.depthTexture.type=e.UnsignedShortType,s.depthTexture.minFilter=e.NearestFilter,s.depthTexture.magFilter=e.NearestFilter),s}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.depthRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren()}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);this.onLoopCallbacks.splice(t,1)}loop(r,s=!1){var n=C();n.showPanel(0);performance.now();e.Ray.prototype.intersectTriangle;let a=0;const o=new i,h=new i,d=e=>{var i,s;const l=this.renderer.getContext();if(this.paused&&this.running&&l.drawingBufferHeight>1)return void setTimeout((()=>d(e)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,n.begin();let c=(e*=.001)-a;if(a=e,o.copy(this.camera.matrixWorld),c>1){let e=c;for(;e>.05;)r(T),e-=T;r(e)}else r(c);this.onLoopCallbacks.forEach((e=>e(c))),null===(i=this.camera)||void 0===i||i.updateMatrixWorld(),h.copy(this.camera.matrixWorld),h.equals(o)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const m=[],g=[];if(this.scene.traverse((i=>{var r,s,n,a,o,h;i instanceof t&&i.visible&&((null===(s=null===(r=i.material)||void 0===r?void 0:r.userData)||void 0===s?void 0:s.water)||(null===(n=i.material)||void 0===n?void 0:n.uniforms)&&null!=(null===(a=i.material)||void 0===a?void 0:a.uniforms[u]))?(i.visible=!1,m.push(i),this.initDepthUniform(i.material),i.renderOrder=100):i instanceof p&&(i.visible=!1,g.push(i)),i instanceof t&&(null===(o=i.material)||void 0===o?void 0:o.uniforms)&&null!=(null===(h=i.material)||void 0===h?void 0:h.uniforms[x])&&(i.material.uniforms[x].value=e)})),m.length>0){if(this.scene.overrideMaterial=P,this.renderer.setRenderTarget(this.depthRenderTarget),!this.paused&&null!=this.camera)try{this.renderer.clear(),this.renderer.render(this.scene,this.camera)}catch(e){console.warn(e)}this.renderer.setRenderTarget(null),this.scene.overrideMaterial=null}m.forEach((e=>e.visible=!0)),g.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.composer.render(c),this.renderOverlay())}catch(e){console.warn(e)}n.end(),null===(s=this.csm)||void 0===s||s.update(),this.running&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(d)}),1e3/this.fpsCap):requestAnimationFrame(d))};requestAnimationFrame(d)}renderOverlay(){const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.container.clientWidth/2,i=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let r=0;r<e.length;r++)this.renderer.clearDepth(),this.renderer.setViewport(t-i/2+this.insetWidth*r+this.insetMargin*r,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[r])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(){this.composer.render()}initDepthUniform(e){e instanceof r&&(e.uniforms[u].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[g]&&e.uniforms[g].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof s&&(e.uniforms[f].value=this.camera.near,e.uniforms[w].value=this.camera.far))}}export function setRenderingPaused(e){var t,i;null!=(null===(i=null===(t=window.editor)||void 0===t?void 0:t.viewer)||void 0===i?void 0:i.renderingView)&&(window.editor.viewer.renderingView.paused=e)}const T=.05;
1
+ import*as e from"three";import{Mesh as t,Matrix4 as i,ShaderMaterial as s,PerspectiveCamera as r,ShaderChunk as n}from"three";import{EffectComposer as a}from"three-stdlib";import{RenderPass as h}from"three-stdlib";import{ShaderPass as o}from"three-stdlib";import{FXAAShader as d}from"three-stdlib";import{CSM as l}from"three-stdlib";import{CSMUtil as c}from"./csm";import{GammaCorrectionShader as m}from"three-stdlib";import{Reflector as p}from"three-stdlib";import{depthUniformName as u,resolutionUniformName as g,supportsDepthTextureExtension as v,nearUniformName as f,farUniformName as w}from"./shader-nodes/depth";import{elapsedTimeUniformName as x}from"./shader-nodes/time";import{OutlinePass as C}from"./utils/three/outline-pass";import b from"./utils/three/stats";import{lambertVertexShaderOverride as R}from"./rendering/shader-override";import{DepthPass as y}from"./utils/three/depth-pass";const P=new e.MeshDepthMaterial;P.depthPacking=e.RGBADepthPacking,P.blending=e.NoBlending;n.lights_pars_begin;n.lights_lambert_vertex=R;export class RenderingView{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof r&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(this.container.clientWidth,this.container.clientHeight),this.composer.setSize(this.container.clientWidth*this.resolutionScale,this.container.clientHeight*this.resolutionScale),this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight)}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=1,this.onResize=()=>{this.resizeRender(),this.paused||this.composer.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=b(),this._showStats=!1,this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,window.renderer=this.renderer=new e.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new e.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.composer=new a(this.renderer);var s=t.clientWidth/t.clientHeight;const r=new e.PerspectiveCamera(45,s,.5,500);r.layers.enable(19),this.setCamera(r),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=e.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=e.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,c.renderingView=this,c.patchThreeAdd(),this.isDepthTextureExtensionSupported=v(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=RenderingView.createDepthRenderTarget(this.renderer,this.container);const n=new h(this.scene,this.camera);if(this.composer.addPass(n),this.outlinePass=new C(new e.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),!0===i.enableOutlines){this.outlinePass.edgeThickness=0,this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.composer.addPass(this.outlinePass);const e=new o(d);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e);var l=new o(m);l.clear=!1,this.composer.addPass(l)}}setCamera(t){this.camera=t,this.composer.passes.forEach((e=>{e instanceof h?e.camera=t:e instanceof C?e.renderCamera=t:e instanceof y&&(e.camera=t)})),null==this.csm?this.csm=new l({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new e.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof r&&(this.csm.maxFar=this.camera.far)),this.csm.updateFrustums()}setSelectedObjects(e){const t=new Map;for(const i of e)t.set(i.uuid,i);for(const i of e)i.traverse((e=>{e.uuid!==i.uuid&&t.has(e.uuid)&&t.delete(e.uuid)}));this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(t,i){var s=!!t.extensions.get("WEBGL_depth_texture");const r=new e.WebGLRenderTarget(i.clientWidth*t.getPixelRatio(),i.clientHeight*t.getPixelRatio());return r.texture.minFilter=e.NearestFilter,r.texture.magFilter=e.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===s&&(r.depthTexture=new e.DepthTexture(128,128),r.depthTexture.type=e.UnsignedShortType,r.depthTexture.minFilter=e.NearestFilter,r.depthTexture.magFilter=e.NearestFilter),r}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.depthRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren()}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);this.onLoopCallbacks.splice(t,1)}set showStats(e){this._showStats=e,this._showStats&&!this.container.contains(this.stats.dom)?this.container.appendChild(this.stats.dom):!this._showStats&&this.container.contains(this.stats.dom)&&this.container.removeChild(this.stats.dom)}get showStats(){return this._showStats}loop(s,r=!1){const n=this.stats;n.showPanel(0),this.showStats=r;performance.now();e.Ray.prototype.intersectTriangle;let a=0;const h=new i,o=new i,d=e=>{var i,r;const l=this.renderer.getContext();if(this.paused&&this.running&&l.drawingBufferHeight>1)return void setTimeout((()=>d(e)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,n.begin();let c=(e*=.001)-a;if(a=e,h.copy(this.camera.matrixWorld),c>1){let e=c;for(;e>.05;)s(S),e-=S;s(e)}else s(c);this.onLoopCallbacks.forEach((e=>e(c))),null===(i=this.camera)||void 0===i||i.updateMatrixWorld(),o.copy(this.camera.matrixWorld),o.equals(h)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const m=[],g=[];if(this.scene.traverse((i=>{var s,r,n,a,h,o;i instanceof t&&i.visible&&((null===(r=null===(s=i.material)||void 0===s?void 0:s.userData)||void 0===r?void 0:r.water)||(null===(n=i.material)||void 0===n?void 0:n.uniforms)&&null!=(null===(a=i.material)||void 0===a?void 0:a.uniforms[u]))?(i.visible=!1,m.push(i),this.initDepthUniform(i.material),i.renderOrder=100):i instanceof p&&(i.visible=!1,g.push(i)),i instanceof t&&(null===(h=i.material)||void 0===h?void 0:h.uniforms)&&null!=(null===(o=i.material)||void 0===o?void 0:o.uniforms[x])&&(i.material.uniforms[x].value=e)})),m.length>0){if(this.scene.overrideMaterial=P,this.renderer.setRenderTarget(this.depthRenderTarget),!this.paused&&null!=this.camera)try{this.renderer.clear(),this.renderer.render(this.scene,this.camera)}catch(e){console.warn(e)}this.renderer.setRenderTarget(null),this.scene.overrideMaterial=null}m.forEach((e=>e.visible=!0)),g.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.composer.render(c),this.renderOverlay())}catch(e){console.warn(e)}n.end(),null===(r=this.csm)||void 0===r||r.update(),this.running&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(d)}),1e3/this.fpsCap):requestAnimationFrame(d))};requestAnimationFrame(d)}renderOverlay(){const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.container.clientWidth/2,i=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let s=0;s<e.length;s++)this.renderer.clearDepth(),this.renderer.setViewport(t-i/2+this.insetWidth*s+this.insetMargin*s,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[s])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(){this.composer.render()}initDepthUniform(e){e instanceof s&&(e.uniforms[u].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[g]&&e.uniforms[g].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof r&&(e.uniforms[f].value=this.camera.near,e.uniforms[w].value=this.camera.far))}}export function setRenderingPaused(e){var t,i;null!=(null===(i=null===(t=window.editor)||void 0===t?void 0:t.viewer)||void 0===i?void 0:i.renderingView)&&(window.editor.viewer.renderingView.paused=e)}const S=.05;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import { Group, Texture } from 'three';
1
+ import { Object3D, Texture } from 'three';
2
2
  import { Asset } from './model';
3
3
  import { CollisionShape } from './collision/collision-shape';
4
4
  export declare class AssetResourceLoader {
@@ -8,8 +8,10 @@ export declare class AssetResourceLoader {
8
8
  private loadingManager;
9
9
  private glbLoader;
10
10
  private fbxLoader;
11
+ private objLoader;
11
12
  private textureLoader;
12
13
  private audioLoader;
14
+ protected onError(error: unknown): void;
13
15
  private makeReady;
14
16
  private ready;
15
17
  constructor();
@@ -26,7 +28,7 @@ export declare class AssetResourceLoader {
26
28
  export interface LoadedMesh {
27
29
  scene: AssetMeshInstance;
28
30
  }
29
- export declare class AssetMeshInstance extends Group {
31
+ export declare class AssetMeshInstance extends Object3D {
30
32
  collisionShapes?: CollisionShape[];
31
33
  }
32
34
  export declare function getElectronArg(name: string): string;
@@ -1,4 +1,4 @@
1
- import{__awaiter as e}from"tslib";import{AudioLoader as t,Group as i,LoadingManager as s,TextureLoader as o}from"three";import{GLTFLoader as r}from"three-stdlib";import{FBXLoader as n}from"three-stdlib";import{cloneMesh as a}from"../utils/mesh";import{pathJoin as h}from"../utils/files";import{Subject as l,firstValueFrom as d}from"rxjs";import{importCollisionShapes as c}from"./collision/collision-shape-import";const u=["glb","fbx"];export class AssetResourceLoader{constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new r(this.loadingManager),this.fbxLoader=new n(this.loadingManager),this.textureLoader=new o(this.loadingManager),this.audioLoader=new t(this.loadingManager),this.makeReady=new l,this.ready=d(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=h(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return h(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}getTexture(t){return e(this,void 0,void 0,(function*(){return null==t?null:(yield this.ready,this.cache.has(t.id)||(yield this.textureLoader.loadAsync(this.getUri(t.fileKey)).then((e=>(e.flipY=!1,this.textureCache.set(t.id,e),e)))),this.textureCache.get(t.id))}))}getMesh(t){var s;return e(this,void 0,void 0,(function*(){if(yield this.ready,!u.includes(null===(s=t.fileFormat)||void 0===s?void 0:s.toLowerCase()))return console.error("Unsupported mesh file format "+t.fileFormat,t),{scene:new i};this.cache.has(t.fileKey)||(yield this.loadMesh(t));const{scene:e}=this.cache.get(t.fileKey),o=this.computeCollisionShapes(t,e),r=(new AssetMeshInstance).copy(a(e));return r.collisionShapes=o,{scene:r}}))}getAudio(t){return e(this,void 0,void 0,(function*(){return yield this.ready,this.audioLoader.loadAsync(this.getUri(t.fileKey))}))}computeCollisionShapes(e,t){return this.collisionShapeCache.get(e.id)||this.collisionShapeCache.set(e.id,c(t)),this.collisionShapeCache.get(e.id)}loadMesh(t){return e(this,void 0,void 0,(function*(){return yield this.ready,yield this.loadByAsset(t).then((e=>(e.scene.animations=[],this.cache.set(t.fileKey,e),e)))}))}loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e})))}}}export class AssetMeshInstance extends i{}export function getElectronArg(e){var t;const i=`--${e}=`,s=null===(t=window.process)||void 0===t?void 0:t.argv.find((e=>e.startsWith(i)));return null==s?void 0:s.substring(i.length)}
1
+ import{__awaiter as e}from"tslib";import{AudioLoader as t,Group as i,LoadingManager as s,Mesh as r,Object3D as o,TextureLoader as n}from"three";import{GLTFLoader as a,MTLLoader as l,OBJLoader as h}from"three-stdlib";import{FBXLoader as c}from"three-stdlib";import{cloneMesh as d}from"../utils/mesh";import{pathJoin as u}from"../utils/files";import{Subject as f,firstValueFrom as p}from"rxjs";import{importCollisionShapes as m}from"./collision/collision-shape-import";import*as g from"three";import{iterateMaterials as y}from"../utils/materials";const v=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new a(this.loadingManager),this.fbxLoader=new c(this.loadingManager),this.objLoader=new h(this.loadingManager),this.textureLoader=new n(this.loadingManager),this.audioLoader=new t(this.loadingManager),this.makeReady=new f,this.ready=p(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=u(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return u(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}getTexture(t){return e(this,void 0,void 0,(function*(){return null==t?null:(yield this.ready,this.cache.has(t.id)||(yield this.textureLoader.loadAsync(this.getUri(t.fileKey)).then((e=>{var i,s;return e.wrapS=g.RepeatWrapping,e.wrapT=g.RepeatWrapping,e.flipY=null===(s=null===(i=t.texture)||void 0===i?void 0:i.flipY)||void 0===s||s,this.textureCache.set(t.id,e),e}))),this.textureCache.get(t.id))}))}getMesh(t){var s;return e(this,void 0,void 0,(function*(){if(yield this.ready,!v.includes(null===(s=t.fileFormat)||void 0===s?void 0:s.toLowerCase()))return console.error("Unsupported mesh file format "+t.fileFormat,t),{scene:new i};if(!this.cache.has(t.fileKey))try{this.cache.set(t.fileKey,yield this.loadMesh(t))}catch(e){return this.onError(e),{scene:new i}}const e=d(this.cache.get(t.fileKey).scene);e.traverse((e=>{e instanceof r&&e.material instanceof Array&&(e.material=e.material.slice())}));const o=this.computeCollisionShapes(t,e),n=(new AssetMeshInstance).copy(e);return n.collisionShapes=o,{scene:n}}))}getAudio(t){return e(this,void 0,void 0,(function*(){return yield this.ready,this.audioLoader.loadAsync(this.getUri(t.fileKey))}))}computeCollisionShapes(e,t){return this.collisionShapeCache.get(e.id)||this.collisionShapeCache.set(e.id,m(t)),this.collisionShapeCache.get(e.id)}loadMesh(t){return e(this,void 0,void 0,(function*(){return yield this.ready,yield this.loadByAsset(t).then((e=>(e.scene.animations=[],e.scene=function(e,t){let i=!1;if(t.traverseVisible((e=>{L.test(e.name)&&(i=!0)})),!i)return t;const s=new g.LOD,r=[t];for(;r.length>0;){const e=r.shift(),t=e.name.match(e.name);if(null!=t){const i=parseInt(t[1]);0===i?s.addLevel(e,0):console.warn(`Skipping LOD level ${i} for now as LOD is not fully supported`)}else r.push(...e.children)}return s}(0,e.scene),e)))}))}loadByAsset(t){return e(this,void 0,void 0,(function*(){const e=this.getUri(t.fileKey);switch(t.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(e).then((e=>({scene:e.scene})));case"fbx":return this.fbxLoader.loadAsync(e).then((e=>({scene:e})));case"obj":if(null!=t.materialLib){const e=new l;e.materialOptions={normalizeRGB:!1};const i=yield e.loadAsync(this.getUri(t.materialLib));this.objLoader.setMaterials(i)}return this.objLoader.loadAsync(e).then((e=>(w(e),e))).then((e=>({scene:e})))}}))}}function w(e){var t;if(e instanceof r)for(const t of y(e.material))t instanceof g.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0,t.color.convertSRGBToLinear());null===(t=e.children)||void 0===t||t.forEach(w)}export class AssetMeshInstance extends o{}export function getElectronArg(e){var t;const i=`--${e}=`,s=null===(t=window.process)||void 0===t?void 0:t.argv.find((e=>e.startsWith(i)));return null==s?void 0:s.substring(i.length)}const L=/_LOD(\d+)$/;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{__awaiter as e}from"tslib";import{materialFromAsset as t}from"../../scene/materializer";import{Mesh as s,PlaneGeometry as o,Vector3 as n,InstancedMesh as i,Matrix4 as a,MeshLambertMaterial as r,Color as c,Vector2 as l,Triangle as h,Box3 as u,MathUtils as d,MeshStandardMaterial as f,ShaderMaterial as m,DoubleSide as p,PerspectiveCamera as w}from"three";import{indexBy as y}from"../../utils/collections";import{smoothNormalsCrossMeshes as v}from"./utils";import*as M from"three";import{defaultLandscapeMaterial as g,LandscapeMesh as x}from"./landscape";import{meanVectors3withWeight as S,clamp as b}from"../../utils/math";import{whenIdle as A}from"../../utils/async";import{Subject as P,debounceTime as z}from"rxjs";new n,new n;const L=new n,B=new n,G=new n;export class LandscapeManager{constructor(e,t,s,o,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=o,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new P,this.defaultLandscapeMaterial=g.clone(),this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new a,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.color=g.color,this.refreshRequests.pipe(z(500)).subscribe((e=>this.refreshScatter(e.origin,e.force,e.predicate)))}updateShaders(e){this.shaders=e}loadGrass(){return e(this,void 0,void 0,(function*(){const e=yield this.assetService.getAsset("6ij937n72g");yield this.assetManagerService.getMesh(e);this.grassGeometry=new o(2,2,3,3);const t=this.grassGeometry.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0,this.grassMaterial=new f({color:3765785})}))}refreshGeometry(){const e=this.source.landscape.options,t=(new n,new n);this.view.camera.getWorldPosition(t);const s=[];G.fromArray(this.source.position);const o=this.view.camera instanceof w?Math.min(this.view.camera.far,1e3):1e3,i=1.1*o,a=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(L.x=r+n*e.sectionSize,!(Math.abs(t.x-L.x)>i))for(let c=0;c<e.sections.y;c++){L.z=a+c*e.sectionSize,B.copy(G).add(L);const l=B.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=o){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,a,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>i&&this.landscape.remove(u)}v(s)}applyHeightMap(e,t,s,o=1){var n,i,a,r;const c=Math.pow(s+1,2),l=e.getAttribute("position"),h=y(null!==(n=t.points)&&void 0!==n?n:[],(e=>e.i));if(1===o)for(const e of t.points)l.setY(e.i,e.y);else for(let e=0;e<l.count;e++){const t=$(e,l.count,c);let s=0;s=t%1==0?null!==(a=null===(i=h.get(t))||void 0===i?void 0:i.y)&&void 0!==a?a:0:Math.floor(null===(r=h.get(t))||void 0===r?void 0:r.y),l.setY(e,s)}l.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){var e,t;const s=new Set;for(const[o,n]of null!==(t=null===(e=this.source.grass)||void 0===e?void 0:e.layers.entries())&&void 0!==t?t:[])for(const[e,t]of n.meshes.entries()){const t=`${o}-${e}`;s.add(t)}for(const e of this.scatterMeshes.keys())if(!s.has(e)){this.scatterMeshes.get(e).forEach((e=>{var t;null===(t=e.parent)||void 0===t||t.remove(e),e.dispose()})),this.scatterMeshes.delete(e)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}refreshScatter(a,l=!1,u=(()=>!0)){var f,w,v,g;return e(this,void 0,void 0,(function*(){l&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[x,P]of null!==(w=null===(f=this.source.grass)||void 0===f?void 0:f.layers.entries())&&void 0!==w?w:[])for(const[f,w]of P.meshes.entries()){const P=`${x}-${f}`;this.scatterMeshes.has(P)||this.scatterMeshes.set(P,new Map);const z=this.scatterMeshes.get(P),L=yield this.assetService.getAsset(w.assetId),B=yield this.assetManagerService.getMesh(L),G=[];if(B.scene.traverse((e=>{e instanceof s&&G.push(e)})),1!==G.length){console.log(B),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(G[0]instanceof s)){console.warn("Only meshes can be used for dynamic grass. Found:",B.scene);continue}const $=G[0];let _=$.geometry;this.scatterGeometryCache.has($.geometry.uuid)?_=this.scatterGeometryCache.get($.geometry.uuid):(_=$.geometry.clone(),!0===w.normalsUp&&E(_),this.scatterGeometryCache.set($.geometry.uuid,_),null==_.userData.updatedMatrix&&(B.scene.updateMatrixWorld(),_.applyMatrix4($.matrixWorld),_.userData.updatedMatrix=!0));const U=_.getIndex().count/3;if(U>400){console.warn(`The triangle count of ${L.name} is too big ${U}. Keep it below 400`);continue}const D=null!=L.materialAssignments&&L.materialAssignments.length>0?L.materialAssignments[0].materialId:null,I=null!=D&&"null"!==D?yield t(yield this.assetService.getAsset(D),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let O=null!=I?I:$.material;O instanceof m&&(O.side=p);const Y=d.degToRad(null!==(v=w.maxSlope)&&void 0!==v?v:90),X=Math.cos(Y),F=this.landscape.sections,N=F.filter(k(a,w.viewDistance)).filter((e=>!z.has(e.uuid)||l)).filter((e=>u(e)));F.filter(C(a,2*w.viewDistance)).forEach((e=>{var t;const s=z.get(e.uuid);null===(t=null==s?void 0:s.parent)||void 0===t||t.remove(s),z.delete(e.uuid)}));performance.now();const Z=this.source.landscape.options,K=Z.sectionSize,V=null!==(g=w.density)&&void 0!==g?g:1,J=null!=V?V:1,Q=Z.density,ee=K/Q,te=J,se=ee/Math.sqrt(te),oe=Math.pow(Q,2),ne=se/ee,ie=Math.floor(oe*te),ae=[0,0,0];for(const t of N)yield A((()=>e(this,void 0,void 0,(function*(){var e,s,a,u,d,f,m;t.updateWorldMatrix(!0,!1);const p=this._matrix,v=new n,g=t.geometry.getAttribute("position"),A=t.geometry.getAttribute("normal"),P=(null!==(e=this.source.vertexMaterials)&&void 0!==e?e:[]).filter((e=>e.m===t.name)),L=y(P,(e=>e.i));let B=z.get(t.uuid);if(null==B||B.count==ie&&!l||(null===(s=B.parent)||void 0===s||s.remove(B),z.delete(t.uuid),B=null),null==B){const e=new o(.15,.75).getAttribute("normal");for(let t=0;t<e.count;t++);new r({color:new c(3765785),side:M.DoubleSide});B=new i(_,O,ie),B.raycast=()=>{},B.receiveShadow=!0}const G=new h(new n,new n,new n);let[$,C,k,U]=[new n,new n,new n,new n],[D,I,Y]=[[],[],[]],[E,F,N]=[new n,new n,new n,new n];const Z=new n,K=new n,V=new n,J=new n,ee=new h(new n,new n,new n),re=new h(new n,new n,new n),ce=new h(new n,new n,new n),le=new h(new n,new n,new n);let he=0;e:for(let e=0;e<oe;e++){const s=Math.floor(e/Q);$.fromBufferAttribute(g,e+s),J.copy($).applyMatrix4(t.matrixWorld),ee.a.copy($),ee.b.fromBufferAttribute(g,e+1+s),ee.c.fromBufferAttribute(g,e+Q+1+s),re.a.copy(ee.b),re.b.copy(ee.c),re.c.fromBufferAttribute(g,e+Q+2+s),ce.a.fromBufferAttribute(A,e+s),ce.b.fromBufferAttribute(A,e+1+s),ce.c.fromBufferAttribute(A,e+Q+1+s),le.a.copy(ce.b),le.b.copy(ce.c),le.c.fromBufferAttribute(A,e+Q+2+s);const o=[];o[0]=null===(a=L.get(e+s))||void 0===a?void 0:a.w,o[1]=null===(u=L.get(e+1+s))||void 0===u?void 0:u.w,o[2]=null===(d=L.get(e+Q+1+s))||void 0===d?void 0:d.w,o[3]=null===(f=L.get(e+Q+2+s))||void 0===f?void 0:f.w;let n=0;for(let e=0;e<1;e+=ne)for(let s=0;s<1;s+=ne){if(he>ie)break e;if(n++,n>te)continue e;1-e>s?(C=ee.a,k=ee.b,U=ee.c,E=ce.a,F=ce.b,N=ce.c,D=o[0],I=o[1],Y=o[2]):(C=re.a,k=re.b,U=re.c,E=le.a,F=le.b,N=le.c,D=o[1],I=o[2],Y=o[3]),G.a.copy(C),G.b.copy(k),G.c.copy(U),q(G),Z.set($.x,0,$.z);const i=1.5;Z.x+=(2*Math.random()-1)*i*se,Z.z+=(2*Math.random()-1)*i*se,G.getBarycoord(Z,v).toArray(ae);if(R([D,I,Y],ae,.2)!==x-1)continue;const a=[C,k,U];S(a,ae,K),S([E,F,N],ae,V);const r=a.map((e=>e.y)),c=Math.max(...r),l=Math.min(...r);if(K.y=b(K.y,l,c),null!=w.maxSlope&&w.maxSlope<90&&V.y<X)continue;const h=K.applyMatrix4(t.matrixWorld);h.y+=T(w.offsetMin,w.offsetMax);const u=T(w.scaleMin,w.scaleMax);p.makeScale(1,1,1),p.setPosition(h),p.scale(W(u)),w.alignToNormal&&H(p,h,B.matrixWorld,V),!1!==w.randomRotation&&j(p),B.setMatrixAt(he,p),he++}}B.instanceMatrix.count=he,p.makeScale(0,0,0);for(let e=he;e<ie;e++)B.setMatrixAt(e,p);B.instanceMatrix.needsUpdate=!0,z.has(t.uuid)||null===(m=this.landscape)||void 0===m||m.attach(B),z.set(t.uuid,B)}))));performance.now()}}))}stop(){this.view.removeOnLoop(this.onLoopHandler)}update(){this.view.camera&&(this.view.camera.getWorldPosition(this._cameraPosition),this._cameraPosition.distanceTo(this._lastUpdatePosition)>10&&(this._lastUpdatePosition.copy(this._cameraPosition),this.refreshGeometry(),this.refreshScatter(this._cameraPosition)))}clear(){this.scatterMeshes.forEach((e=>e.forEach((e=>{var t;return null===(t=e.parent)||void 0===t?void 0:t.remove(e)}))))}createLandscapeMesh(e,t,s,n,i,a){const r=new o(t.sectionSize,t.sectionSize,t.density,t.density);r.rotateX(Math.PI/-2);const c=this.defaultLandscapeMaterial,l=new x(r,c);l.position.x=s+i*t.sectionSize,l.position.z=n+a*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:i,y:a},l.x=i,l.y=a,l.name=`${i},${a}`;const h=e.landscape.heightMaps.find((e=>e.x===i&&e.y===a));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function $(e,t,s){const o=Math.sqrt(t),n=Math.floor(e/o)/(o-1),i=e%o/(o-1),a=Math.sqrt(s);return(s-1)*n-(a-1)*n+(a-1)*i}new Map,new l(0,0),new l(1,0),new l(0,1),new l(1,0),new l(0,1),new l(1,1),new n;const _=new u;function C(e,t){return function(s){return _.setFromObject(s).distanceToPoint(e)>t}}function k(e,t){return function(s){return _.setFromObject(s).distanceToPoint(e)<t}}function q(e){e.a.y=0,e.b.y=0,e.c.y=0}function R(e,t,s=.5){let o=-1,n=0;for(let i=0;i<e.length;i++)if(null!=e[i])for(let a=0;a<e[i].length;a++){const r=e[i][a]*t[i];r>s&&r>n&&(n=r,o=a)}return o}function T(e,t){let s=t-e,o=Math.random();return o*=s,o+=e,o}const U=new n;function W(e){return U.set(e,e,e)}new n;const D=new n,I=new n(0,1,0),O=(new a).makeRotationX(Math.PI/-2);function H(e,t,s,o){e.lookAt(D,o,I).multiply(O)}const Y=new a;function j(e){e.multiply(Y.makeRotationY(Math.random()*Math.PI/2))}function E(e){const t=e.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0}
1
+ import{__awaiter as e}from"tslib";import{materialFromAsset as t}from"../../scene/materializer";import{Mesh as s,PlaneGeometry as o,Vector3 as n,InstancedMesh as i,Matrix4 as a,MeshLambertMaterial as r,Color as c,Vector2 as l,Triangle as h,Box3 as u,MathUtils as d,MeshStandardMaterial as f,ShaderMaterial as m,DoubleSide as p,PerspectiveCamera as w}from"three";import{indexBy as y}from"../../utils/collections";import{smoothNormalsCrossMeshes as v}from"./utils";import*as M from"three";import{defaultLandscapeMaterial as g,LandscapeMesh as x}from"./landscape";import{meanVectors3withWeight as b,clamp as S}from"../../utils/math";import{whenIdle as A}from"../../utils/async";import{Subject as z,debounceTime as P}from"rxjs";new n,new n;const L=new n,B=new n,G=new n;export class LandscapeManager{constructor(e,t,s,o,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=o,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new z,this.defaultLandscapeMaterial=g.clone(),this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new a,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.color=g.color,this.refreshRequests.pipe(P(500)).subscribe((e=>this.refreshScatter(e.origin,e.force,e.predicate)))}updateShaders(e){this.shaders=e}loadGrass(){return e(this,void 0,void 0,(function*(){const e=yield this.assetService.getAsset("6ij937n72g");yield this.assetManagerService.getMesh(e);this.grassGeometry=new o(2,2,3,3);const t=this.grassGeometry.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0,this.grassMaterial=new f({color:3765785})}))}refreshGeometry(){const e=this.source.landscape.options,t=(new n,new n);this.view.camera.getWorldPosition(t);const s=[];G.fromArray(this.source.position);const o=this.view.camera instanceof w?Math.min(this.view.camera.far,1e3):1e3,i=1.1*o,a=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(L.x=r+n*e.sectionSize,!(Math.abs(t.x-L.x)>i))for(let c=0;c<e.sections.y;c++){L.z=a+c*e.sectionSize,B.copy(G).add(L);const l=B.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=o){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,a,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>i&&this.landscape.remove(u)}v(s)}applyHeightMap(e,t,s,o=1){var n,i,a,r;const c=Math.pow(s+1,2),l=e.getAttribute("position"),h=y(null!==(n=t.points)&&void 0!==n?n:[],(e=>e.i));if(1===o)for(const e of t.points)l.setY(e.i,e.y);else for(let e=0;e<l.count;e++){const t=$(e,l.count,c);let s=0;s=t%1==0?null!==(a=null===(i=h.get(t))||void 0===i?void 0:i.y)&&void 0!==a?a:0:Math.floor(null===(r=h.get(t))||void 0===r?void 0:r.y),l.setY(e,s)}l.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){var e,t;const s=new Set;for(const[o,n]of null!==(t=null===(e=this.source.grass)||void 0===e?void 0:e.layers.entries())&&void 0!==t?t:[])for(const[e,t]of n.meshes.entries()){const t=`${o}-${e}`;s.add(t)}for(const e of this.scatterMeshes.keys())if(!s.has(e)){this.scatterMeshes.get(e).forEach((e=>{var t;null===(t=e.parent)||void 0===t||t.remove(e),e.dispose()})),this.scatterMeshes.delete(e)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}refreshScatter(a,l=!1,u=(()=>!0)){var f,w,v,g;return e(this,void 0,void 0,(function*(){l&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[x,z]of null!==(w=null===(f=this.source.grass)||void 0===f?void 0:f.layers.entries())&&void 0!==w?w:[])for(const[f,w]of z.meshes.entries()){const z=`${x}-${f}`;this.scatterMeshes.has(z)||this.scatterMeshes.set(z,new Map);const P=this.scatterMeshes.get(z),L=yield this.assetService.getAsset(w.assetId),B=yield this.assetManagerService.getMesh(L),G=[];if(B.scene.traverse((e=>{e instanceof s&&G.push(e)})),1!==G.length){console.log(B),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(G[0]instanceof s)){console.warn("Only meshes can be used for dynamic grass. Found:",B.scene);continue}const $=G[0];let _=$.geometry;this.scatterGeometryCache.has($.geometry.uuid)?_=this.scatterGeometryCache.get($.geometry.uuid):(_=$.geometry.clone(),!0===w.normalsUp&&E(_),this.scatterGeometryCache.set($.geometry.uuid,_),null==_.userData.updatedMatrix&&(B.scene.updateMatrixWorld(),_.applyMatrix4($.matrixWorld),_.userData.updatedMatrix=!0));const U=_.getIndex().count/3;if(U>400){console.warn(`The triangle count of ${L.name} is too big ${U}. Keep it below 400`);continue}const D=null!=L.materialAssignments&&L.materialAssignments.length>0?L.materialAssignments[0].materialId:null,I=null!=D&&"null"!==D?yield t(yield this.assetService.getAsset(D),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let O=null!=I?I:$.material;O instanceof m&&(O.side=p);const Y=d.degToRad(null!==(v=w.maxSlope)&&void 0!==v?v:90),X=Math.cos(Y),F=this.landscape.sections,N=F.filter(k(a,w.viewDistance)).filter((e=>!P.has(e.uuid)||l)).filter((e=>u(e)));F.filter(C(a,2*w.viewDistance)).forEach((e=>{var t;const s=P.get(e.uuid);null===(t=null==s?void 0:s.parent)||void 0===t||t.remove(s),P.delete(e.uuid)}));performance.now();const Z=this.source.landscape.options,K=Z.sectionSize,V=null!==(g=w.density)&&void 0!==g?g:1,J=null!=V?V:1,Q=Z.density,ee=K/Q,te=J,se=ee/Math.sqrt(te),oe=Math.pow(Q,2),ne=se/ee,ie=Math.floor(oe*te),ae=[0,0,0];for(const t of N)yield A((()=>e(this,void 0,void 0,(function*(){var e,s,a,u,d,f,m;t.updateWorldMatrix(!0,!1);const p=this._matrix,v=new n,g=t.geometry.getAttribute("position"),A=t.geometry.getAttribute("normal"),z=(null!==(e=this.source.vertexMaterials)&&void 0!==e?e:[]).filter((e=>e.m===t.name)),L=y(z,(e=>e.i));let B=P.get(t.uuid);if(null==B||B.count==ie&&!l||(null===(s=B.parent)||void 0===s||s.remove(B),P.delete(t.uuid),B=null),null==B){const e=new o(.15,.75).getAttribute("normal");for(let t=0;t<e.count;t++);new r({color:new c(3765785),side:M.DoubleSide});B=new i(_,O,ie),B.raycast=()=>{},B.receiveShadow=!0}const G=new h(new n,new n,new n);let[$,C,k,U]=[new n,new n,new n,new n],[D,I,Y]=[[],[],[]],[E,F,N]=[new n,new n,new n,new n];const Z=new n,K=new n,V=new n,J=new n,ee=new h(new n,new n,new n),se=new h(new n,new n,new n),re=new h(new n,new n,new n),ce=new h(new n,new n,new n);let le=0;e:for(let e=0;e<oe;e++){const s=Math.floor(e/Q);$.fromBufferAttribute(g,e+s),J.copy($).applyMatrix4(t.matrixWorld),ee.a.copy($),ee.b.fromBufferAttribute(g,e+1+s),ee.c.fromBufferAttribute(g,e+Q+1+s),se.a.copy(ee.b),se.b.copy(ee.c),se.c.fromBufferAttribute(g,e+Q+2+s),re.a.fromBufferAttribute(A,e+s),re.b.fromBufferAttribute(A,e+1+s),re.c.fromBufferAttribute(A,e+Q+1+s),ce.a.copy(re.b),ce.b.copy(re.c),ce.c.fromBufferAttribute(A,e+Q+2+s);const o=[];o[0]=null===(a=L.get(e+s))||void 0===a?void 0:a.w,o[1]=null===(u=L.get(e+1+s))||void 0===u?void 0:u.w,o[2]=null===(d=L.get(e+Q+1+s))||void 0===d?void 0:d.w,o[3]=null===(f=L.get(e+Q+2+s))||void 0===f?void 0:f.w;let n=0;for(let e=0;e<=1+ne;e+=ne)for(let s=0;s<=1+ne;s+=ne){if(le>ie)break e;if(n++,n>te)continue e;1-e>s?(C=ee.a,k=ee.b,U=ee.c,E=re.a,F=re.b,N=re.c,D=o[0],I=o[1],Y=o[2]):(C=se.a,k=se.b,U=se.c,E=ce.a,F=ce.b,N=ce.c,D=o[1],I=o[2],Y=o[3]),G.a.copy(C),G.b.copy(k),G.c.copy(U),q(G),Z.set($.x,0,$.z),Z.x=T(G.a.x,G.b.x),Z.z=T(G.a.z,G.c.z),G.getBarycoord(Z,v).toArray(ae);if(R([D,I,Y],ae,.2)!==x-1)continue;const i=[C,k,U];b(i,ae,K),b([E,F,N],ae,V);const a=i.map((e=>e.y)),r=Math.max(...a),c=Math.min(...a);if(K.y=S(K.y,c,r),null!=w.maxSlope&&w.maxSlope<90&&V.y<X)continue;const l=K.applyMatrix4(t.matrixWorld);l.y+=T(w.offsetMin,w.offsetMax);const h=T(w.scaleMin,w.scaleMax);p.makeScale(1,1,1),p.setPosition(l),p.scale(W(h)),w.alignToNormal&&H(p,l,B.matrixWorld,V),!1!==w.randomRotation&&j(p),B.setMatrixAt(le,p),le++}}B.instanceMatrix.count=le,p.makeScale(0,0,0);for(let e=le;e<ie;e++)B.setMatrixAt(e,p);B.instanceMatrix.needsUpdate=!0,P.has(t.uuid)||null===(m=this.landscape)||void 0===m||m.attach(B),P.set(t.uuid,B)}))));performance.now()}}))}stop(){this.view.removeOnLoop(this.onLoopHandler)}update(){this.view.camera&&(this.view.camera.getWorldPosition(this._cameraPosition),this._cameraPosition.distanceTo(this._lastUpdatePosition)>10&&(this._lastUpdatePosition.copy(this._cameraPosition),this.refreshGeometry(),this.refreshScatter(this._cameraPosition)))}clear(){this.scatterMeshes.forEach((e=>e.forEach((e=>{var t;return null===(t=e.parent)||void 0===t?void 0:t.remove(e)}))))}createLandscapeMesh(e,t,s,n,i,a){const r=new o(t.sectionSize,t.sectionSize,t.density,t.density);r.rotateX(Math.PI/-2);const c=this.defaultLandscapeMaterial,l=new x(r,c);l.position.x=s+i*t.sectionSize,l.position.z=n+a*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:i,y:a},l.x=i,l.y=a,l.name=`${i},${a}`;const h=e.landscape.heightMaps.find((e=>e.x===i&&e.y===a));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function $(e,t,s){const o=Math.sqrt(t),n=Math.floor(e/o)/(o-1),i=e%o/(o-1),a=Math.sqrt(s);return(s-1)*n-(a-1)*n+(a-1)*i}new Map,new l(0,0),new l(1,0),new l(0,1),new l(1,0),new l(0,1),new l(1,1),new n;const _=new u;function C(e,t){return function(s){return _.setFromObject(s).distanceToPoint(e)>t}}function k(e,t){return function(s){return _.setFromObject(s).distanceToPoint(e)<t}}function q(e){e.a.y=0,e.b.y=0,e.c.y=0}function R(e,t,s=.5){let o=-1,n=0;for(let i=0;i<e.length;i++)if(null!=e[i])for(let a=0;a<e[i].length;a++){const r=e[i][a]*t[i];r>s&&r>n&&(n=r,o=a)}return o}function T(e,t){let s=t-e,o=Math.random();return o*=s,o+=e,o}const U=new n;function W(e){return U.set(e,e,e)}new n;const D=new n,I=new n(0,1,0),O=(new a).makeRotationX(Math.PI/-2);function H(e,t,s,o){e.lookAt(D,o,I).multiply(O)}const Y=new a;function j(e){e.multiply(Y.makeRotationY(Math.random()*Math.PI/2))}function E(e){const t=e.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,5 @@
1
1
  import { Subject } from "rxjs";
2
+ import * as THREE from "three";
2
3
  import { Euler, Material, Object3D, Scene, Vector3 } from "three";
3
4
  import { GameComponent } from "../game-component/game-component";
4
5
  import { RenderingView } from "../rendering";
@@ -207,7 +208,7 @@ export declare class SceneMaterializer {
207
208
  updateActors(actors: ActorImpl[]): void;
208
209
  updateShaders(shaders: ShaderImpl[]): void;
209
210
  private update;
210
- private materializeAndInitActor;
211
+ materializeAndInitActor(source: SceneObject, parent?: THREE.Object3D<THREE.Event>): Promise<THREE.Object3D<THREE.Event>>;
211
212
  private findParent;
212
213
  private fixFogColor;
213
214
  private findMeshWithGeometry;