@hology/core 0.0.41 → 0.0.43

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/dist/effects/vfx/vfx-defs.d.ts +2 -2
  2. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +2 -0
  3. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  4. package/dist/gameplay/actors/builtin/index.d.ts +2 -0
  5. package/dist/gameplay/actors/builtin/index.js +1 -1
  6. package/dist/gameplay/actors/builtin/navmesh-actor.d.ts +18 -0
  7. package/dist/gameplay/actors/builtin/navmesh-actor.js +5 -0
  8. package/dist/gameplay/ai/build-tile.d.ts +50 -0
  9. package/dist/gameplay/ai/build-tile.js +5 -0
  10. package/dist/gameplay/ai/dynamic-tiled-navmesh.d.ts +31 -0
  11. package/dist/gameplay/ai/dynamic-tiled-navmesh.js +5 -0
  12. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.d.ts +1 -0
  13. package/dist/gameplay/ai/dynamic-tiled-navmesh.worker.js +5 -0
  14. package/dist/gameplay/ai/index.d.ts +1 -0
  15. package/dist/gameplay/ai/index.js +5 -0
  16. package/dist/gameplay/ai/navigation.d.ts +19 -0
  17. package/dist/gameplay/ai/navigation.js +5 -0
  18. package/dist/gameplay/index.d.ts +1 -0
  19. package/dist/gameplay/index.js +1 -1
  20. package/dist/gameplay/services/physics/physics-system.d.ts +1 -0
  21. package/dist/gameplay/services/physics/physics-system.js +1 -1
  22. package/dist/rendering.d.ts +1 -0
  23. package/dist/rendering.js +1 -1
  24. package/dist/scene/asset-resource-loader.d.ts +2 -0
  25. package/dist/scene/bootstrap.js +1 -1
  26. package/dist/scene/collision/collision-shape.d.ts +4 -6
  27. package/dist/scene/collision/collision-shape.js +1 -1
  28. package/dist/scene/landscape/landscape-manager.js +1 -1
  29. package/dist/scene/materializer.d.ts +32 -8
  30. package/dist/scene/materializer.js +1 -1
  31. package/dist/scene/model.d.ts +7 -1
  32. package/dist/scene/objects/shapes.d.ts +1 -1
  33. package/dist/scene/runtime-backend-service.d.ts +2 -1
  34. package/dist/scene/runtime-backend-service.js +1 -1
  35. package/dist/scene/scene-data-service.d.ts +1 -1
  36. package/dist/scene/scene-data-service.js +1 -1
  37. package/dist/utils/three/traverse.d.ts +1 -1
  38. package/package.json +2 -1
  39. package/tsconfig.tsbuildinfo +1 -1
@@ -203,8 +203,8 @@ declare const vfxBehaviours: {
203
203
  };
204
204
  export type LibraryVfxInitalizerType = keyof typeof vfxInitializsers;
205
205
  export declare const VfxInitializserLibrary: Record<LibraryVfxInitalizerType, InitializerDefinition>;
206
- export declare const VfxInitializserLibraryKeys: ("rotation" | "scale" | "mass" | "velocity" | "lifetime" | "positionPoint" | "positionBox" | "positionSphere" | "positionLine" | "randomDirection")[];
206
+ export declare const VfxInitializserLibraryKeys: ("rotation" | "mass" | "scale" | "velocity" | "lifetime" | "positionPoint" | "positionBox" | "positionSphere" | "positionLine" | "randomDirection")[];
207
207
  export type LibraryVfxBehaviourType = keyof typeof vfxBehaviours;
208
208
  export declare const VfxBehaviourLibrary: Record<LibraryVfxBehaviourType, BehaviourDefinition>;
209
- export declare const VfxBehaviourLibraryKeys: ("scale" | "rotate" | "force" | "gravity" | "randomDrift" | "changeColor" | "changeOpacity" | "vortex" | "moveTo" | "linearDamping")[];
209
+ export declare const VfxBehaviourLibraryKeys: ("scale" | "force" | "gravity" | "randomDrift" | "rotate" | "changeColor" | "changeOpacity" | "vortex" | "moveTo" | "linearDamping")[];
210
210
  export {};
@@ -33,6 +33,8 @@ export declare class CharacterMovementComponent extends ActorComponent {
33
33
  set autoStepMaxHeight(maxHeight: number);
34
34
  get snapToGround(): number;
35
35
  set snapToGround(distance: number);
36
+ set offset(distance: number);
37
+ get offset(): number;
36
38
  readonly velocity: Vector3;
37
39
  mode: CharacterMovementMode;
38
40
  isSprinting: boolean;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as i}from"tslib";import{ActionInput as e,AxisInput as o,RotationInput as s}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as n,RayTestResult as r}from"../../../../../gameplay/services/physics/physics-system.js";import{MathUtils as a,Vector3 as c}from"three";import{ActorComponent as l,Component as h}from"../../../component.js";import{CharacterMovementMode as p}from"./modes.js";import{CapsuleCollisionShape as m}from"../../../../../scene/collision/collision-shape.js";import{takeUntil as d}from"rxjs";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{RootMotionClip as u}from"../../../../../gameplay/animation/root-motion.js";const g=new c,S=new c,f=1/30;let v=class extends l{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}constructor(t){super(),this.physicsSystem=t,this.directionInput=new o,this.jumpInput=new e,this.sprintInput=new e,this.rotationInput=new s,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=a.degToRad(70),this.maxSlopeClimbAngle=a.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.velocity=new c,this.mode=p.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new r,this.resetRootMotion=!1;const i=this.cc=this.physicsSystem.getCharacterController(.1);i.enableSnapToGround(.1),i.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!0,friction:1}),this.rotationInput.rotation.copy(this.actor.rotation);let i=this.rotationInput.rotation.y;const e=new c,o=new c,s=new c,n=new c,r=new c,l=new c;let h=0,m=null;const v=new c,M=new c,x=new c,I=new c;this.physicsSystem.beforeStep.pipe(d(this.disposed)).subscribe((d=>{if(this.checkGrounded(d),null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof u){const t=this.rootMotionInterpolant;this.resetRootMotion&&(v.fromArray(t.evaluate(0)),this.resetRootMotion=!1),I.fromArray(t.evaluate(this.rootMotionAction.time)),M.subVectors(I,v),v.copy(I),this.rootMotionAction.getRoot().getWorldScale(x),M.multiply(x)}}d>f&&(d=f);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled&&0!=M.length();this.pressedJump=this.jumpInput.activated,this.isSprinting=this.sprintInput.activated&&this.directionInput.vertical>=0;let T=i-this.rotationInput.rotation.y;i=this.rotationInput.rotation.y,s.copy(this.actor.position),n.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const b=n.z<0?this.maxSpeedBackwards:this.isSprinting?this.maxSpeedSprint:this.maxSpeed;l.copy(n).applyAxisAngle(w,this.rotationInput.rotation.y),this.mode===p.walking?(0!==l.length()?(h=Math.min(b,h),h=a.lerp(h,b,4*d)):h=0,r.copy(l).multiplyScalar(h),this.pressedJump&&(this.mode=p.falling,this.velocity.copy(r),this.velocity.y=this.jumpVelocity),r.y=d*this.getEffectiveGravity()):this.mode===p.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=p.falling,this.velocity.copy(r),this.velocity.y=this.jumpVelocity),this.velocity.y+=d*this.getEffectiveGravity(),r.copy(this.velocity),r.add(l.clone().multiplyScalar(b*this.fallingMovementControl*d)),this.fallingReorientation&&r.applyAxisAngle(new c(0,1,0),-T)),o.copy(r).normalize(),e.copy(r),this.actor.rotation.y-=T,r.length(),y?(M.applyAxisAngle(w,this.actor.rotation.y),M.y+=d*this.getEffectiveGravity(),g.copy(M)):g.copy(r).multiplyScalar(d),this.isGrounded&&this.mode===p.walking&&(g.y=0),S.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,g)),this.physicsSystem.setNextKinematicTranslation(this.actor,S);let j=function(t){if(t.numComputedCollisions()>0){const i=t.computedCollision(0);A.x=i.normal2.x,A.y=i.normal2.y,A.z=i.normal2.z;const e=A.angleTo(w);A.x=i.normal1.x,A.y=i.normal1.y,A.z=i.normal1.z;const o=A.angleTo(w);return!(e<100)&&o>t.minSlopeSlideAngle()}return!1}(t);y||this.isGrounded&&!j||this.mode!==p.falling&&(null==m?m=performance.now():performance.now()-m>100&&(this.mode=p.falling,this.velocity.copy(e))),this.isGrounded&&this.velocity.y<=0&&(this.mode,p.falling,this.mode=p.walking,this.velocity.y=0,m=null),this.mode,p.walking,this.horizontalSpeed=h}))}setRootMotionAction(t){const i=t?.getClip();if(i instanceof u){this.rootMotionAction=t,this.resetRootMotion=!0;const e=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(e)}}getWallDirection(t,i){const e=t.clone().negate().cross(w);return e.dot(i)<0?e.negate():e}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){const i=this.colliderHeight+2*this.colliderRadius;this.physicsSystem.rayTest(M.addVectors(this.actor.position,I.set(0,i/4,0)),x.addVectors(this.actor.position,T),this.rayTestResult,{excludeActor:this.actor})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new m(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2,t}step(t){}performMovement(t){}};v=t([h({inEditor:!1}),i("design:paramtypes",[n])],v);export{v as CharacterMovementComponent};const w=new c(0,1,0),A=new c;const M=new c,x=new c,I=new c(0,1,0),T=new c(0,-.1,0);
1
+ import{__decorate as t,__metadata as i}from"tslib";import{ActionInput as e,AxisInput as o,RotationInput as s}from"../../../../../gameplay/input/index.js";import{PhysicsSystem as n,RayTestResult as r}from"../../../../../gameplay/services/physics/physics-system.js";import{MathUtils as c,Vector3 as a}from"three";import{ActorComponent as l,Component as h}from"../../../component.js";import{CharacterMovementMode as p}from"./modes.js";import{CapsuleCollisionShape as m}from"../../../../../scene/collision/collision-shape.js";import{takeUntil as d}from"rxjs";import{PhysicsBodyType as y}from"../../../../services/physics/physics-system.js";import{RootMotionClip as u}from"../../../../../gameplay/animation/root-motion.js";const g=new a,f=new a,S=1/30;let v=class extends l{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}constructor(t){super(),this.physicsSystem=t,this.directionInput=new o,this.jumpInput=new e,this.sprintInput=new e,this.rotationInput=new s,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=c.degToRad(70),this.maxSlopeClimbAngle=c.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.velocity=new a,this.mode=p.walking,this.isSprinting=!1,this.pressedJump=!1,this.rayTestResult=new r,this.resetRootMotion=!1;const i=this.cc=this.physicsSystem.getCharacterController(.1);i.enableSnapToGround(.1),i.enableAutostep(0,.1,!1)}onInit(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:y.kinematic,continousCollisionDetection:!0,friction:1,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation);let i=this.rotationInput.rotation.y;const e=new a,o=new a,s=new a,n=new a,r=new a,l=new a;let h=0,m=null;const v=new a,M=new a,x=new a,I=new a;this.physicsSystem.beforeStep.pipe(d(this.disposed)).subscribe((d=>{if(this.checkGrounded(d),null!=this.rootMotionAction){if(this.rootMotionAction.getClip()instanceof u){const t=this.rootMotionInterpolant;this.resetRootMotion&&(v.fromArray(t.evaluate(0)),this.resetRootMotion=!1),I.fromArray(t.evaluate(this.rootMotionAction.time)),M.subVectors(I,v),v.copy(I),this.rootMotionAction.getRoot().getWorldScale(x),M.multiply(x)}}d>S&&(d=S);const y=null!=this.rootMotionAction&&this.rootMotionAction.enabled&&0!=M.length();this.pressedJump=this.jumpInput.activated,this.isSprinting=this.sprintInput.activated&&this.directionInput.vertical>=0;let T=i-this.rotationInput.rotation.y;i=this.rotationInput.rotation.y,s.copy(this.actor.position),n.set(-this.directionInput.vector.x,0,this.directionInput.vector.y).normalize();const b=n.z<0?this.maxSpeedBackwards:this.isSprinting?this.maxSpeedSprint:this.maxSpeed;l.copy(n).applyAxisAngle(w,this.rotationInput.rotation.y),this.mode===p.walking?(0!==l.length()?(h=Math.min(b,h),h=c.lerp(h,b,4*d)):h=0,r.copy(l).multiplyScalar(h),this.pressedJump&&(this.mode=p.falling,this.velocity.copy(r),this.velocity.y=this.jumpVelocity),r.y=d*this.getEffectiveGravity()):this.mode===p.falling&&(this.pressedJump&&this.jumpInAir&&(this.mode=p.falling,this.velocity.copy(r),this.velocity.y=this.jumpVelocity),this.velocity.y+=d*this.getEffectiveGravity(),r.copy(this.velocity),r.add(l.clone().multiplyScalar(b*this.fallingMovementControl*d)),this.fallingReorientation&&r.applyAxisAngle(new a(0,1,0),-T)),o.copy(r).normalize(),e.copy(r),this.actor.rotation.y-=T,r.length(),y?(M.applyAxisAngle(w,this.actor.rotation.y),M.y+=d*this.getEffectiveGravity(),g.copy(M)):g.copy(r).multiplyScalar(d),this.isGrounded&&this.mode===p.walking&&(g.y=0),f.copy(this.physicsSystem.getActorComputedMovement(this.actor,t,g)),this.physicsSystem.setNextKinematicTranslation(this.actor,f);let j=function(t){if(t.numComputedCollisions()>0){const i=t.computedCollision(0);A.x=i.normal2.x,A.y=i.normal2.y,A.z=i.normal2.z;const e=A.angleTo(w);A.x=i.normal1.x,A.y=i.normal1.y,A.z=i.normal1.z;const o=A.angleTo(w);return!(e<100)&&o>t.minSlopeSlideAngle()}return!1}(t);y||this.isGrounded&&!j||this.mode!==p.falling&&(null==m?m=performance.now():performance.now()-m>100&&(this.mode=p.falling,this.velocity.copy(e))),this.isGrounded&&this.velocity.y<=0&&(this.mode,p.falling,this.mode=p.walking,this.velocity.y=0,m=null),this.mode,p.walking,this.horizontalSpeed=h}))}setRootMotionAction(t){const i=t?.getClip();if(i instanceof u){this.rootMotionAction=t,this.resetRootMotion=!0;const e=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(e)}}getWallDirection(t,i){const e=t.clone().negate().cross(w);return e.dot(i)<0?e.negate():e}moveTo(t){this.actor.position.copy(t),this.physicsSystem.updateActorTransform(this.actor)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}checkGrounded(t){const i=this.colliderHeight+2*this.colliderRadius;this.physicsSystem.rayTest(M.addVectors(this.actor.position,I.set(0,i/4,0)),x.addVectors(this.actor.position,T),this.rayTestResult,{excludeActor:this.actor})}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}createCollisionShape(){const t=new m(this.colliderHeight,this.colliderRadius);return t.offset.y=this.colliderRadius+this.colliderHeight/2,t}step(t){}performMovement(t){}};v=t([h({inEditor:!1}),i("design:paramtypes",[n])],v);export{v as CharacterMovementComponent};const w=new a(0,1,0),A=new a;const M=new a,x=new a,I=new a(0,1,0),T=new a(0,-.1,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 { CameraActor } from './camera-actor.js';
2
+ import NavMeshActor from './navmesh-actor.js';
2
3
  import { PositionalAudioActor } from './positional-audio-actor.js';
3
4
  import { SpawnPoint } from './spawn-point.js';
4
5
  import { TriggerVolume } from './trigger-volume.js';
@@ -7,5 +8,6 @@ declare const _default: {
7
8
  SpawnPoint: typeof SpawnPoint;
8
9
  TriggerVolume: typeof TriggerVolume;
9
10
  PositionalAudio: typeof PositionalAudioActor;
11
+ NavMesh: typeof NavMeshActor;
10
12
  };
11
13
  export default _default;
@@ -1,4 +1,4 @@
1
- import{CameraActor as o}from"./camera-actor.js";import{PositionalAudioActor as r}from"./positional-audio-actor.js";import{SpawnPoint as i}from"./spawn-point.js";import{TriggerVolume as t}from"./trigger-volume.js";export default{Camera:o,SpawnPoint:i,TriggerVolume:t,PositionalAudio:r};
1
+ import{CameraActor as o}from"./camera-actor.js";import r from"./navmesh-actor.js";import{PositionalAudioActor as a}from"./positional-audio-actor.js";import{SpawnPoint as i}from"./spawn-point.js";import{TriggerVolume as m}from"./trigger-volume.js";export default{Camera:o,SpawnPoint:i,TriggerVolume:m,PositionalAudio:a,NavMesh:r};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -0,0 +1,18 @@
1
+ import { BaseActor } from "../../";
2
+ import { NavMesh } from 'recast-navigation';
3
+ declare class NavMeshActor extends BaseActor {
4
+ private physics;
5
+ private view;
6
+ debug: boolean;
7
+ refreshMs: number;
8
+ tileSize: number;
9
+ cellSize: number;
10
+ walkableClimb: number;
11
+ walkableSlopeAngle: number;
12
+ walkableRadius: number;
13
+ walkableHeight: number;
14
+ navMesh: NavMesh;
15
+ onInit(): Promise<void>;
16
+ private init;
17
+ }
18
+ export default NavMeshActor;
@@ -0,0 +1,5 @@
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Ball as o,Capsule as i,Cone as n,ConvexPolyhedron as s,Cuboid as r,Cylinder as a,Heightfield as l,ShapeType as h,TriMesh as c}from"@dimforge/rapier3d-compat";import{Actor as p,BaseActor as d,Parameter as u,PhysicsSystem as w,ViewController as f,inject as m}from"../../";import{init as g}from"@recast-navigation/core";import{DebugDrawer as b,getPositionsAndIndices as y}from"recast-navigation/three";import*as v from"three";import{DynamicTiledNavMesh as x}from"../../ai/dynamic-tiled-navmesh";const M=new v.Box3(new v.Vector3(-5e3,-1e3,-5e4),new v.Vector3(7e4,3e4,4e4)),S=navigator.hardwareConcurrency??3;let B=class extends d{constructor(){super(...arguments),this.physics=m(w),this.view=m(f),this.debug=!0,this.refreshMs=1e3,this.tileSize=100,this.cellSize=.2,this.walkableClimb=1,this.walkableSlopeAngle=45,this.walkableRadius=.5,this.walkableHeight=1}async onInit(){await g(),this.init()}init(){const e={tileSize:this.tileSize,walkableClimb:this.walkableClimb,walkableSlopeAngle:this.walkableSlopeAngle,walkableRadius:this.walkableRadius,walkableHeight:this.walkableHeight,detailSampleDist:6,minRegionArea:8,mergeRegionArea:100,cs:this.cellSize,ch:this.cellSize},t=new x({navMeshBounds:M,recastConfig:e,maxTiles:1024,workers:S});this.navMesh=t.navMesh,this.object.position.set(0,0,0);const o=this.tileSize+10,i=performance.now(),n=new Map,s=new b,r=()=>{const e=this.view.getCamera().getWorldPosition(new v.Vector3),t=new v.Box3((new v.Vector3).copy(e).subScalar(o),(new v.Vector3).copy(e).addScalar(o)),i=[],s=this.physics.world.bodies,r=new v.Box3;for(const e of s.getAll())for(let o=0,s=e.numColliders();o<s;o++){const s=e.collider(o);if(s.isSensor()||null!=s.parent().userData&&!0===s.parent().userData.ignoreForNavMesh)continue;const a=n.get(s)?.mesh,l=a??z(s);if(C(s,l),null!=l){r.copy(l.geometry.boundingBox),r.min.add(l.position),r.max.add(l.position);const e=r.intersectsBox(t);n.set(s,{pos:s.translation(),mesh:l}),e&&i.push(l)}}return i},a=new v.Box3,l=new Map,h=new Map,c=setInterval((()=>{const e=new v.Box3,o=r();for(const t of o){const o=l.get(t);!0!==o?.equals(t.position)&&(null!=o&&e.expandByPoint(o),e.expandByObject(t),l.set(t,t.position.clone()))}const i=t.getTilesForBounds(e);if(0!=i.length){const n=[];for(const t of o)a.setFromObject(t),a.intersect(e)&&n.push(t);const[r,l]=y(n);Promise.all(i.map((e=>t.buildTile(r,l,e).then((()=>{const t=e[0]+","+e[1];h.set(t,(h.get(t)??0)+1)}))))).then((()=>{this.debug&&(s.clear(),s.drawNavMesh(t.navMesh))}))}}),this.refreshMs??1e4);this.disposed.subscribe((()=>clearInterval(c)));const p=t.navMesh;console.log("create with debug",this.debug),this.debug&&(s.clear(),s.drawNavMesh(p));const d=()=>{s.resize(window.innerWidth,window.innerHeight)};d(),window.addEventListener("resize",d),this.debug&&this.object.parent.add(s),this.disposed.subscribe((()=>{p?.destroy(),s.removeFromParent(),s.dispose(),window.removeEventListener("resize",d)}));const u=performance.now()-i;u>1e3&&console.warn(`NavMesh update took ${u} ms. Consider changing tileSize or other parameter that may affect performance`)}};e([u(),t("design:type",Boolean)],B.prototype,"debug",void 0),e([u(),t("design:type",Number)],B.prototype,"refreshMs",void 0),e([u(),t("design:type",Number)],B.prototype,"tileSize",void 0),e([u(),t("design:type",Number)],B.prototype,"cellSize",void 0),e([u(),t("design:type",Number)],B.prototype,"walkableClimb",void 0),e([u({range:[0,89]}),t("design:type",Number)],B.prototype,"walkableSlopeAngle",void 0),e([u(),t("design:type",Number)],B.prototype,"walkableRadius",void 0),e([u(),t("design:type",Number)],B.prototype,"walkableHeight",void 0),B=e([p()],B);export default B;function k(e){if(e.shape instanceof l)return function(e){const t=e.shape;if(t.type!==h.HeightField)throw new Error("The provided collider is not a height field.");let o=!1;const i=t,n=i.heights,s=i.nrows,r=i.ncols,a=i.scale.x,l=i.scale.z,c=i.scale.y,p=s+1,d=new v.PlaneGeometry(l,a,r,s);d.rotateX(-Math.PI/2);const u=d.attributes.position.array;let w=0;for(let e=0;e<p;e++)for(let t=0;t<p;t++)u[w+1]=n[t*p+e]*c,w+=3,0!=u[w+1]&&(o=!0);if(!o){const e=new v.PlaneGeometry(a,l,2,2);return e.rotateX(-Math.PI/2),e}return d}(e);if(e.shape instanceof o)return new v.SphereGeometry(e.shape.radius);if(e.shape instanceof r){const t=e.shape.halfExtents;return new v.BoxGeometry(2*t.x,2*t.y,2*t.z)}if(e.shape instanceof s||e.shape instanceof c){const t=e.shape.vertices,o=e.shape.indices,i=new v.BufferGeometry;return i.setAttribute("position",new v.Float32BufferAttribute(t,3)),null!=o&&i.setIndex(new v.Uint16BufferAttribute(o,1)),i}if(e.shape instanceof a){const t=e.shape.halfHeight,o=e.shape.radius;return new v.CylinderGeometry(o,o,2*t)}if(e.shape instanceof n){const t=e.shape.halfHeight,o=e.shape.radius;return new v.ConeGeometry(o,2*t)}if(e.shape instanceof i){const t=e.shape.halfHeight,o=e.shape.radius;return new v.CapsuleGeometry(o,2*t)}return console.warn("Unsupported shape",e.shape.type,e),null}function z(e){const t=k(e);if(null==t)return null;const o=new v.MeshBasicMaterial({wireframe:!1,color:16711680,side:v.DoubleSide}),i=new v.Mesh(t,o);return i.geometry.computeBoundingBox(),i}function C(e,t){const o=e.translation(),i=e.rotation();t.position.set(o.x,o.y,o.z),t.quaternion.set(i.x,i.y,i.z,i.w)}
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -0,0 +1,50 @@
1
+ import { RecastBuildContext, RecastCompactHeightfield, RecastConfig, RecastContourSet, RecastHeightfield, UnsignedCharArray, Vector3Tuple } from '@recast-navigation/core';
2
+ type BuildConfigProps = {
3
+ recastConfig: RecastConfig;
4
+ navMeshBounds: [min: Vector3Tuple, max: Vector3Tuple];
5
+ };
6
+ export declare const buildConfig: ({ recastConfig, navMeshBounds: [navMeshBoundsMin, navMeshBoundsMax] }: BuildConfigProps) => {
7
+ config: import("@recast-navigation/wasm").default.rcConfig;
8
+ orig: {
9
+ x: number;
10
+ y: number;
11
+ z: number;
12
+ };
13
+ tileBits: number;
14
+ polyBits: number;
15
+ maxTiles: number;
16
+ maxPolysPerTile: number;
17
+ tcs: number;
18
+ tileWidth: number;
19
+ tileHeight: number;
20
+ };
21
+ export type TileIntermediates = {
22
+ tileX: number;
23
+ tileY: number;
24
+ heightfield?: RecastHeightfield;
25
+ compactHeightfield?: RecastCompactHeightfield;
26
+ contourSet?: RecastContourSet;
27
+ };
28
+ export type BuildTileMeshProps = {
29
+ positions: Float32Array;
30
+ indices: Uint32Array;
31
+ recastConfig: RecastConfig;
32
+ tileX: number;
33
+ tileY: number;
34
+ tileBoundsMin: Vector3Tuple;
35
+ tileBoundsMax: Vector3Tuple;
36
+ navMeshBounds: [Vector3Tuple, Vector3Tuple];
37
+ keepIntermediates: boolean;
38
+ };
39
+ export type BuildTileMeshResult = ({
40
+ success: true;
41
+ data?: UnsignedCharArray;
42
+ } | {
43
+ success: false;
44
+ error: string;
45
+ }) & {
46
+ tileIntermediates?: TileIntermediates;
47
+ buildContext: RecastBuildContext;
48
+ };
49
+ export declare const buildTile: ({ positions, indices, navMeshBounds, recastConfig, tileX, tileY, tileBoundsMin, tileBoundsMax, keepIntermediates, }: BuildTileMeshProps) => BuildTileMeshResult;
50
+ export {};
@@ -0,0 +1,5 @@
1
+ import{NavMeshCreateParams as e,Raw as t,RecastBuildContext as i,TriangleAreasArray as l,TrianglesArray as o,VerticesArray as r,allocCompactHeightfield as a,allocContourSet as s,allocHeightfield as n,allocPolyMesh as d,allocPolyMeshDetail as c,buildCompactHeightfield as h,buildContours as g,buildDistanceField as m,buildPolyMesh as u,buildPolyMeshDetail as b,buildRegions as f,calcGridSize as S,cloneRcConfig as R,createHeightfield as w,createNavMeshData as p,createRcConfig as C,erodeWalkableArea as M,filterLedgeSpans as _,filterLowHangingWalkableObstacles as x,filterWalkableLowHeightSpans as A,freeCompactHeightfield as k,freeContourSet as y,freeHeightfield as z,markWalkableTriangles as E,rasterizeTriangles as v,vec3 as T}from"@recast-navigation/core";import{dtIlog2 as B,dtNextPow2 as O}from"@recast-navigation/generators";import*as P from"three";export const buildConfig=({recastConfig:e,navMeshBounds:[t,i]})=>{const l=C(e),o=S(t,i,l.cs);l.width=o.width,l.height=o.height,l.minRegionArea=l.minRegionArea*l.minRegionArea,l.mergeRegionArea=l.mergeRegionArea*l.mergeRegionArea,l.tileSize=Math.floor(l.tileSize),l.borderSize=l.walkableRadius+3,l.width=l.tileSize+2*l.borderSize,l.height=l.tileSize+2*l.borderSize,l.detailSampleDist=l.detailSampleDist<.9?0:l.cs*l.detailSampleDist,l.detailSampleMaxError=l.ch*l.detailSampleMaxError;const r=Math.floor(l.tileSize),a=Math.floor((o.width+r-1)/r),s=Math.floor((o.height+r-1)/r),n=l.tileSize*l.cs,d=T.fromArray(t);let c=Math.min(Math.floor(B(O(a*s))),14);c>14&&(c=14);const h=22-c;return{config:l,orig:d,tileBits:c,polyBits:h,maxTiles:1<<c,maxPolysPerTile:1<<h,tcs:n,tileWidth:a,tileHeight:s}};export const buildTile=({positions:S,indices:C,navMeshBounds:T,recastConfig:B,tileX:O,tileY:H,tileBoundsMin:L,tileBoundsMax:G,keepIntermediates:D})=>{const $=new i,F=S,V=C.length,W=new r;W.copy(F);const I=C,K=C.length/3;(new o).copy(I);const X={tileX:O,tileY:H},Y=()=>{D||(X.compactHeightfield&&k(X.compactHeightfield),X.heightfield&&z(X.heightfield),X.contourSet&&y(X.contourSet))},N=e=>($.log(t.Module.RC_LOG_ERROR,e),Y(),{success:!1,error:e,tileIntermediates:X,buildContext:$}),{config:U}=buildConfig({recastConfig:B,navMeshBounds:T}),j=R(U),q=[...L],J=[...G];q[0]-=j.borderSize*j.cs,q[2]-=j.borderSize*j.cs,J[0]+=j.borderSize*j.cs,J[2]+=j.borderSize*j.cs,j.set_bmin(0,q[0]),j.set_bmin(1,q[1]),j.set_bmin(2,q[2]),j.set_bmax(0,J[0]),j.set_bmax(1,J[1]),j.set_bmax(2,J[2]),$.resetTimers(),$.startTimer(t.Module.RC_TIMER_TOTAL),$.log(t.Module.RC_LOG_PROGRESS,`Building tile at x: ${O}, y: ${H}`),$.log(t.Module.RC_LOG_PROGRESS,` - ${U.width} x ${U.height} cells`),$.log(t.Module.RC_LOG_PROGRESS,` - ${V/1e3}fK verts, ${K/1e3}K tris`);const Q=n();if(X.heightfield=Q,!w($,Q,j.width,j.height,q,J,j.cs,j.ch))return N("Could not create heightfield");const Z=((e,t,i)=>{const l=[],o=new P.Vector3,r=new P.Vector3,a=new P.Vector3,s=new P.Triangle;for(let n=0;n<t.length;n+=3){const d=t[n],c=t[n+1],h=t[n+2];o.fromArray(e,3*d),r.fromArray(e,3*c),a.fromArray(e,3*h),s.set(o,r,a),s.intersectsBox(i)&&l.push(d,c,h)}return l})(S,C,new P.Box3(new P.Vector3(q[0],q[1],q[2]),new P.Vector3(J[0],J[1],J[2]))),ee=Z.length/3,te=new o;te.copy(Z);const ie=new l;ie.resize(ee),E($,j.walkableSlopeAngle,W,V,te,ee,ie);const le=v($,W,V,te,ie,ee,Q,j.walkableClimb);if(ie.destroy(),!le)return N("Could not rasterize triangles");x($,j.walkableClimb,Q),_($,j.walkableHeight,j.walkableClimb,Q),A($,j.walkableHeight,Q);const oe=a();if(X.compactHeightfield=oe,!h($,j.walkableHeight,j.walkableClimb,Q,oe))return N("Could not build compact heightfield");if(D||(z(X.heightfield),X.heightfield=void 0),!M($,j.walkableRadius,oe))return N("Could not erode walkable area");if(!m($,oe))return N("Failed to build distance field");if(!f($,oe,j.borderSize,j.minRegionArea,j.mergeRegionArea))return N("Failed to build regions");const re=s();if(X.contourSet=re,!g($,oe,j.maxSimplificationError,j.maxEdgeLen,re,t.Module.RC_CONTOUR_TESS_WALL_EDGES))return N("Failed to create contours");const ae=d();if(!u($,re,j.maxVertsPerPoly,ae))return N("Failed to triangulate contours");const se=c();if(!b($,ae,oe,j.detailSampleDist,j.detailSampleMaxError,se))return N("Failed to build detail mesh");D||(k(oe),X.compactHeightfield=void 0,y(re),X.contourSet=void 0);for(let e=0;e<ae.npolys();e++)ae.areas(e)==t.Recast.WALKABLE_AREA&&ae.setAreas(e,0),0==ae.areas(e)&&ae.setFlags(e,1);const ne=new e;ne.setPolyMeshCreateParams(ae),ne.setPolyMeshDetailCreateParams(se),ne.setWalkableHeight(j.walkableHeight),ne.setWalkableRadius(j.walkableRadius),ne.setWalkableClimb(j.walkableClimb),ne.setCellSize(j.cs),ne.setCellHeight(j.ch),ne.setBuildBvTree(!0),ne.setTileX(O),ne.setTileY(H);const de=p(ne);return de.success?($.log(t.Module.RC_LOG_PROGRESS,`>> Polymesh: ${ae.nverts()} vertices ${ae.npolys()} polygons`),Y(),{success:!0,data:de.navMeshData,tileIntermediates:X,buildContext:$}):N("Failed to create Detour navmesh data")};
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -0,0 +1,31 @@
1
+ import { NavMesh, RecastConfig, Vector3Tuple } from 'recast-navigation';
2
+ import * as THREE from 'three';
3
+ import { Subject } from 'rxjs';
4
+ export type DynamicTiledNavMeshProps = {
5
+ navMeshBounds: THREE.Box3;
6
+ recastConfig: Partial<RecastConfig>;
7
+ maxTiles: number;
8
+ workers: number;
9
+ };
10
+ export declare class DynamicTiledNavMesh {
11
+ navMesh: NavMesh;
12
+ navMeshVersion: number;
13
+ onNavMeshUpdate: Subject<[version: number, tile: [x: number, y: number]]>;
14
+ navMeshBounds: [min: Vector3Tuple, max: Vector3Tuple];
15
+ navMeshBoundsMin: THREE.Vector3;
16
+ navMeshBoundsMax: THREE.Vector3;
17
+ navMeshOrigin: THREE.Vector3;
18
+ tileWidth: number;
19
+ tileHeight: number;
20
+ tcs: number;
21
+ recastConfig: RecastConfig;
22
+ workers: InstanceType<any>[];
23
+ workerRoundRobin: number;
24
+ constructor(props: DynamicTiledNavMeshProps);
25
+ private onResult;
26
+ buildTile(positions: Float32Array, indices: Uint32Array, [tileX, tileY]: [x: number, y: number]): Promise<unknown>;
27
+ buildAllTiles(positions: Float32Array, indices: Uint32Array): void;
28
+ getTileForWorldPosition(worldPosition: THREE.Vector3): [x: number, y: number];
29
+ getTilesForBounds(bounds: THREE.Box3): [x: number, y: number][];
30
+ destroy(): void;
31
+ }
@@ -0,0 +1,5 @@
1
+ import{NavMesh as s,NavMeshParams as t,Raw as e,UnsignedCharArray as i,recastConfigDefaults as n,statusToReadableString as o}from"recast-navigation";import{buildConfig as a,buildTile as h}from"./build-tile.js";import{Subject as r}from"rxjs";export class DynamicTiledNavMesh{constructor(e){this.navMeshVersion=0,this.onNavMeshUpdate=new r,this.workerRoundRobin=0;const i=e.navMeshBounds.min,o=e.navMeshBounds.max,h=[i.toArray(),o.toArray()],l=e.navMeshBounds.min;this.navMeshBoundsMin=i,this.navMeshBoundsMax=o,this.navMeshBounds=h,this.navMeshOrigin=l;const d={...n,...e.recastConfig};this.recastConfig=d;const M=new s,{tileWidth:u,tileHeight:c,tcs:v,maxPolysPerTile:m}=a({recastConfig:d,navMeshBounds:h});this.tileWidth=u,this.tileHeight=c,this.tcs=v;const B=t.create({orig:l,tileWidth:d.tileSize*d.cs,tileHeight:d.tileSize*d.cs,maxTiles:e.maxTiles,maxPolys:m});M.initTiled(B),this.navMesh=M,this.workers=[]}onResult(s){const{tileX:t,tileY:n,navMeshData:a}=s.data,h=new i;h.copy(a),this.navMesh.removeTile(this.navMesh.getTileRefAt(t,n,0));const r=this.navMesh.addTile(h,e.Module.DT_TILE_FREE_DATA,0);e.Detour.statusFailed(r.status)&&(console.error(e.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${t}, ty: ${n},status: ${o(r.status)} (${r.status})`),h.destroy()),this.navMeshVersion++,this.onNavMeshUpdate.next([this.navMeshVersion,[t,n]])}buildTile(s,t,[e,i]){const n=new Float32Array(s),o=new Uint32Array(t),a={tileX:e,tileY:i,tileBoundsMin:[this.navMeshBoundsMin.x+e*this.tcs,this.navMeshBoundsMin.y,this.navMeshBoundsMin.z+i*this.tcs],tileBoundsMax:[this.navMeshBoundsMax.x+(e+1)*this.tcs,this.navMeshBoundsMax.y,this.navMeshBoundsMax.z+(i+1)*this.tcs],recastConfig:this.recastConfig,navMeshBounds:this.navMeshBounds,keepIntermediates:!1,positions:n,indices:o};return this.workerRoundRobin=(this.workerRoundRobin+1)%this.workers.length,new Promise((s=>{requestIdleCallback((()=>{const t=h(a);if(!t.success||!t.data)return;const e=t.data.toTypedArray();this.onResult({data:{tileX:a.tileX,tileY:a.tileY,navMeshData:e}}),s(t)}))}))}buildAllTiles(s,t){const{tileWidth:e,tileHeight:i}=this;for(let n=0;n<i;n++)for(let i=0;i<e;i++)this.buildTile(s,t,[i,n])}getTileForWorldPosition(s){return[Math.floor((s.x-this.navMeshBoundsMin.x)/this.tcs),Math.floor((s.z-this.navMeshBoundsMin.z)/this.tcs)]}getTilesForBounds(s){const t=this.getTileForWorldPosition(s.min),e=this.getTileForWorldPosition(s.max),i=[];for(let s=t[1];s<=e[1];s++)for(let n=t[0];n<=e[0];n++)i.push([n,s]);return i}destroy(){this.navMesh.destroy();for(const s of this.workers)s.terminate()}}
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import{init as t}from"recast-navigation";import{buildTile as e}from"./build-tile.js";let s=!1;const a=[];self.onmessage=t=>{s?o(t.data):a.push(t.data)};const o=t=>{const s=e(t);if(!s.success||!s.data)return;const a=s.data.toTypedArray();s.data.destroy(),self.postMessage({tileX:t.tileX,tileY:t.tileY,navMeshData:a},[a.buffer])};t().then((()=>{s=!0;for(const t of a)o(t)}));
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -0,0 +1 @@
1
+ export * from './navigation.js';
@@ -0,0 +1,5 @@
1
+ export*from"./navigation.js";
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -0,0 +1,19 @@
1
+ import { Vector3 } from "three";
2
+ export declare class Navigation {
3
+ private navMeshActor;
4
+ private query?;
5
+ private world;
6
+ constructor();
7
+ /**
8
+ * Finds a path from a start point to an end point.
9
+ */
10
+ findPath(start: Vector3, end: Vector3): {
11
+ success: boolean;
12
+ path: Vector3[];
13
+ };
14
+ /**
15
+ * Finds the closest point on the navmesh to a given position.
16
+ * Returns null if it can't be found or if nav mesh has not been generated
17
+ */
18
+ findClosestPoint(position: Vector3): Vector3 | null;
19
+ }
@@ -0,0 +1,5 @@
1
+ import{__decorate as t,__metadata as e}from"tslib";import{Service as s,World as n,inject as r}from"../";import o from"../actors/builtin/navmesh-actor";import{NavMeshQuery as i}from"recast-navigation";import{Vector3 as a}from"three";let c=class{constructor(){this.world=r(n);const t=this.world.actors.find((t=>t instanceof o));null!=t&&(this.navMeshActor=t,this.query=new i(t.navMesh)),this.world.actorAdded.subscribe((t=>{t instanceof o&&(this.navMeshActor=t,this.query=new i(t.navMesh))})),this.world.actorRemoved.subscribe((t=>{t instanceof o&&t.id===this.navMeshActor?.id&&(this.navMeshActor=null,this.query=null)}))}findPath(t,e){if(null==this.query)return console.warn("NavMesh has not been generated yet"),h;const{success:s,error:n,path:r}=this.query.computePath(t,e);return s?{success:!0,path:r.map((t=>new a(t.x,t.y,t.z)))}:(console.warn("Failed to generate path",n),h)}findClosestPoint(t){if(null==this.query)return console.warn("NavMesh has not been generated yet"),null;const{success:e,point:s}=this.query.findClosestPoint(t);return e?new a(s.x,s.y,s.z):null}};c=t([s(),e("design:paramtypes",[])],c);export{c as Navigation};const h={success:!1,path:[]};
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
@@ -15,3 +15,4 @@ export * from './services/asset-loader.js';
15
15
  export * from './services/pointer-events.js';
16
16
  export { VisualEffect } from '../effects/vfx/vfx-param.js';
17
17
  export * from '../shader/parameter.js';
18
+ export * from './ai/index.js';
@@ -1,4 +1,4 @@
1
- import"reflect-metadata";export{Container as DIContainer}from"typedi";export*from"./initiate.js";export*from"./inject.js";export{Service,Inject}from"typedi";export{ActorFactory}from"./actors/factory.js";export{Actor,BaseActor}from"./actors/actor.js";export{Component,ActorComponent,attach,Attach}from"./actors/component.js";export*from"./services/world.js";export*from"./services/render.js";export*from"./services/physics/physics-system.js";export*from"./animation/anim-sm.js";export*from"./animation/root-motion.js";export*from"./services/asset-loader.js";export*from"./services/pointer-events.js";export{VisualEffect}from"../effects/vfx/vfx-param.js";export*from"../shader/parameter.js";
1
+ import"reflect-metadata";export{Container as DIContainer}from"typedi";export*from"./initiate.js";export*from"./inject.js";export{Service,Inject}from"typedi";export{ActorFactory}from"./actors/factory.js";export{Actor,BaseActor}from"./actors/actor.js";export{Component,ActorComponent,attach,Attach}from"./actors/component.js";export*from"./services/world.js";export*from"./services/render.js";export*from"./services/physics/physics-system.js";export*from"./animation/anim-sm.js";export*from"./animation/root-motion.js";export*from"./services/asset-loader.js";export*from"./services/pointer-events.js";export{VisualEffect}from"../effects/vfx/vfx-param.js";export*from"../shader/parameter.js";export*from"./ai/index.js";
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -34,6 +34,7 @@ export type ActorPhysicsOptions = {
34
34
  density: number;
35
35
  restitution: number;
36
36
  type: PhysicsBodyType;
37
+ ignoreForNavMesh: boolean;
37
38
  };
38
39
  export declare class PhysicsSystem {
39
40
  viewController: ViewController;
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as r,filter as n,map as a,Subject as c,takeUntil as l}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,MeshBasicMaterial as f,Object3D as w,Quaternion as v,Raycaster as x,Scene as b,Vector3 as B}from"three";import{Service as A}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as D,CapsuleCollisionShape as z,ConeCollisionShape as T,ConvexPolyhedronCollisionShape as M,CylinderCollisionShape as E,PhysicalShapeMesh as S,PlaneCollisionShape as R,SphereCollisionShape as W,TrimeshCollisionShape as _}from"../../../index.js";import{LandscapeGroup as V}from"../../../scene/landscape/landscape.js";import{ViewController as F}from"../render.js";import{World as P}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as I}from"../../../utils/three/traverse.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new B,this.hitNormal=new B}}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 L=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 c,this.beforeStep=new c,this.afterStep=new c,this.shouldRenderDebug=!1,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new B,this._raytestDirection=new B,this.controlledActors=new Set,this.ready=this.setup()}createDebugMesh(){return new g(new y,new f({color:255}))}async start(){return await 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 u(t.vertices,3))}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await U(),this.eventQueue=new i.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=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;var i,s;null!=e&&(e.parent instanceof b&&(X(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&(i=e.quaternion,s=t.rotation(),i.x=s.x,i.y=s.y,i.z=s.z,i.w=s.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(H,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,s,o){null==s&&(s=this._reusableResult);const r=this._raytestDiff,n=this._raytestDirection;if(r.subVectors(e,t),n.copy(r).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),s;const a=new i.Ray(t,n),c=r.length(),l=this.world.castRayAndGetNormal(a,c,!1,void 0,void 0,void 0,null!=o?.excludeActor?this.actorBodies.get(o.excludeActor.id):void 0);if(s.hasHit=null!=l,s.hasHit){const e=a.pointAt(l.toi);s._internal=l,X(s.hitNormal,l.normal),X(s.hitPoint,e),s.distance=Y.subVectors(s.hitPoint,t).length();const i=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===l.collider))));s.actor=null!=i?this.bodyActors.get(i):null}if(this.showDebug){const e=new h(n,t,c,o?.debugColor??255);this.gameWorld.scene.add(e),setTimeout((()=>this.gameWorld.scene.remove(e)),o?.debugLifetime??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 q.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())J(t,(t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof S&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape]);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C&&!1!==t.userData?.src?.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 V?this.addLandscapeGroup(t):(t instanceof p||t instanceof b)&&t.children.forEach((t=>this.addRecursively(t)))}createForInstancedMesh(t,e){const i=new m;for(let s=0;s<t.count;s++){const o=new w;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*s),o.applyMatrix4(i);this.createStaticBody(o,e)}}getCharacterController(t=.01){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i){const o=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=o.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,null,$);const n=e.computedMovement();return X(Z,n),Z}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,i?.setNextKinematicTranslation(s)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.setAngvel(G,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.setLinvel(G,!0)}getLinearVelocity(t,e=new B){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 B){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);i?.setLinearDamping(e)}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}createCharacterCollision(){return new i.CharacterCollision}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const r of t.sections){this.staticBodies.has(r)&&this.world.removeRigidBody(this.staticBodies.get(r));const t=e.landscape.options.density+1,n=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const c=s.find((t=>t.x===r.x&&t.y==r.y));if(null!=c)for(const e of c.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/n:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:c})}const l=e.landscape.options.density,d=a.flatMap((t=>t.reverse())),h=i.ColliderDesc.heightfield(l,l,new Float32Array(d),new i.Vector3(n,n,n));var o=r.getWorldPosition(new B);const u=this.world.createRigidBody(i.RigidBodyDesc.fixed()),y=new i.Vector3(0,0,0);K(y,o),u.setTranslation(y,!1),this.world.createCollider(h,u),this.staticBodies.set(r,u)}}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let r;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:r=i.RigidBodyDesc.dynamic(),r.mass=s.mass??1;break;case PhysicsBodyType.kinematic:r=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:r=i.RigidBodyDesc.kinematicVelocityBased();break;default:r=(s.isTrigger,i.RigidBodyDesc.kinematicVelocityBased())}const n=this.world.createRigidBody(r);n.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(n,t,o);J(n,(t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.restitution&&t.setDensity(s.restitution),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)})),N(n,o),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t)}applyTorque(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.addTorque(G,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.applyTorqueImpulse(G,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.addForce(G,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.applyImpulse(G,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);K(G,e),null==i?s?.addForce(G,!0):(K(Q,i),s?.addForceAtPoint(G,Q,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);K(G,e),null==i?s.applyImpulse(G,!0):(K(Q,i),s.applyImpulseAtPoint(G,Q,!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(l(t.disposed),n((({started:t})=>t===i)),a((({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}))),n((({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s))),a((({a2:t})=>t)))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(l(t.disposed),n((t=>t.started)),n((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),a((t=>t.handle2)))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(l(t.disposed),n((t=>!t.started)),n((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),a((t=>t.handle2)))}onHasContactChanged(t){const e=new Set,i=new o(!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(r())}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?N(e,t.object):console.warn("Actor has not been added to physics world",t)}setupWorld(){const t=new i.World({x:0,y:-9.81,z:0});this.world=t,t.maxVelocityIterations=4}getActorContacts(t,e){const s=this.actorBodies.get(t.id);if(s&&s.numColliders()>0){const o=s.collider(0);let r=o.shape,n=o.translation(),a=o.rotation(),c=e,l=.3;const d=this.world.castShape(n,a,c,r,l,!0,null,null,null,this.actorBodies.get(t.id),(t=>t.shape.type!=i.ShapeType.HeightField));if(null!=d){const t=new B,e=new B,i=new B;return X(t,d.witness2),X(e,d.witness1),X(i,d.normal1),i.negate(),[{ri:t,rj:e,ni:i}]}return[]}return console.warn("Actor is not added to the physics system"),[]}stop(){this.world?.bodies.forEach((t=>this.world.removeRigidBody(t))),this.world?.free(),this.fixedupdateSub?.unsubscribe()}createStaticBody(t,e){const s=this.world.createRigidBody(i.RigidBodyDesc.kinematicPositionBased());for(const i of e)this.addShape(s,i,t);return N(s,t),s}addShape(t,e,i){const s=this.createShape(e,i.scale);s.friction=.1;const o=e.offset.clone().multiply(i.scale);var r,n;K(s.translation,o),r=s.rotation,n=(new v).setFromEuler(e.rotation),r.x=n.x,r.y=n.y,r.z=n.z,r.w=n.w;this.world.createCollider(s,t)}createShape(t,e){if(t instanceof D)return i.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof z){return i.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof _){const e=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry);return i.ColliderDesc.trimesh(new Float32Array(e.getAttribute("position").array),new Uint32Array(e.getIndex().array))}if(t instanceof M){let s;t.mesh instanceof d.Mesh?s=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?s=t.mesh:console.log("Unknownd shape",{shapeInfo:t});const o=new Float32Array(s.getAttribute("position").array);if(t.mesh instanceof d.Mesh){const e=I(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 i.ColliderDesc.convexHull(o)}return t instanceof W?i.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z)):t instanceof E?i.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof T?i.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof R?i.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.01):(console.error("Unsupported shape",t),i.ColliderDesc.cuboid(1,1,1))}};L=t([A(),e("design:paramtypes",[F,P])],L);export{L as PhysicsSystem};const j=new B,O=new d.Quaternion;function N(t,e){const s=e.getWorldPosition(j),o=e.getWorldQuaternion(O);t.setTranslation(new i.Vector3(s.x,s.y,s.z),!1),t.setRotation(new i.Quaternion(o.x,o.y,o.z,o.w),!1)}const q=new B,G=new i.Vector3(0,0,0),Q=new i.Vector3(0,0,0),H=(new B,{x:0,y:0}),U=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function K(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function X(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function J(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const Y=new B,Z=new B,$=t=>!t.isSensor();
1
+ import{__decorate as t,__metadata as e}from"tslib";import*as i from"@dimforge/rapier3d-compat";import{QueryFilterFlags as s}from"@dimforge/rapier3d-compat";import{BehaviorSubject as o,distinctUntilChanged as r,filter as n,map as a,Subject as c,takeUntil as l}from"rxjs";import*as d from"three";import{ArrowHelper as h,BufferAttribute as u,BufferGeometry as y,Group as p,LineSegments as g,Matrix4 as m,MeshBasicMaterial as f,Object3D as w,Quaternion as v,Raycaster as x,Scene as B,Vector3 as b}from"three";import{Service as A}from"typedi";import{AssetMeshInstance as C}from"../../../scene/asset-resource-loader.js";import{BoxCollisionShape as D,CapsuleCollisionShape as z,ConeCollisionShape as M,ConvexPolyhedronCollisionShape as T,CylinderCollisionShape as R,PhysicalShapeMesh as S,PlaneCollisionShape as E,SphereCollisionShape as W,TrimeshCollisionShape as F}from"../../../index.js";import{LandscapeGroup as _}from"../../../scene/landscape/landscape.js";import{ViewController as V}from"../render.js";import{World as P}from"../world.js";import*as k from"three/examples/jsm/utils/BufferGeometryUtils.js";import{calculateEffectiveScale as I}from"../../../utils/three/traverse.js";export class RayTestResult{constructor(){this.hasHit=!1,this.hitPoint=new b,this.hitNormal=new b}}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 L=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 c,this.beforeStep=new c,this.afterStep=new c,this.shouldRenderDebug=!1,this._raycaster=new x,this._reusableResult=new RayTestResult,this._raytestDiff=new b,this._raytestDirection=new b,this.controlledActors=new Set,this.ready=this.setup()}createDebugMesh(){return new g(new y,new f({color:255}))}async start(){return await 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 u(t.vertices,3))}async setup(){if(null!=this.rapier)throw new Error("Rapier is already estup");this.rapier=await U(),this.eventQueue=new i.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=>{if(t.isFixed())return;const e=this.staticMeshes.get(t)??this.bodyActors.get(t)?.object;var i,s;null!=e&&(e.parent instanceof B&&(X(e.position,t.translation()),(t.isDynamic()||t.isKinematic()&&!this.controlledActors.has(this.bodyActors.get(t)?.id))&&(i=e.quaternion,s=t.rotation(),i.x=s.x,i.y=s.y,i.z=s.z,i.w=s.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(H,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,s,o){null==s&&(s=this._reusableResult);const r=this._raytestDiff,n=this._raytestDirection;if(r.subVectors(e,t),n.copy(r).normalize(),0===n.length())return console.warn("Ray test called with to and from being equal"),s;const a=new i.Ray(t,n),c=r.length(),l=this.world.castRayAndGetNormal(a,c,!1,void 0,void 0,void 0,null!=o?.excludeActor?this.actorBodies.get(o.excludeActor.id):void 0);if(s.hasHit=null!=l,s.hasHit){const e=a.pointAt(l.toi);s._internal=l,X(s.hitNormal,l.normal),X(s.hitPoint,e),s.distance=Y.subVectors(s.hitPoint,t).length();const i=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===l.collider))));s.actor=null!=i?this.bodyActors.get(i):null}if(this.showDebug){const e=new h(n,t,c,o?.debugColor??255);this.gameWorld.scene.add(e),setTimeout((()=>this.gameWorld.scene.remove(e)),o?.debugLifetime??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 q.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())J(t,(t=>t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)))}addRecursively(t){if(this.removeSceneObject(t),!function(t){if(null!=t.userData?.src){const e=t.userData?.src;return"actor"===e.type}return!1}(t))if(t instanceof S&&null!=t.collisionShape){const e=this.createStaticBody(t,[t.collisionShape],t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else if(t instanceof C&&!1!==t.userData?.src?.collisionDetection)if(t.children[0]&&t.children[0].instanceMatrix)this.createForInstancedMesh(t.children[0],t.collisionShapes);else{const e=this.createStaticBody(t,t.collisionShapes,t.physics);this.staticMeshes.set(e,t),this.staticBodies.set(t,e)}else t instanceof _?this.addLandscapeGroup(t):(t instanceof p||t instanceof B)&&t.children.forEach((t=>this.addRecursively(t)))}createForInstancedMesh(t,e){const i=new m;for(let s=0;s<t.count;s++){const o=new w;o.matrix.identity(),i.fromArray(t.instanceMatrix.array,16*s),o.applyMatrix4(i);this.createStaticBody(o,e)}}getCharacterController(t=.01){return this.world?.createCharacterController(t)}getActorComputedMovement(t,e,i){const o=this.actorBodies.get(t.id);this.controlledActors.add(t.id);const r=o.collider(0);e.computeColliderMovement(r,i,s.EXCLUDE_SENSORS,null,$);const n=e.computedMovement();return X(Z,n),Z}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,i?.setNextKinematicTranslation(s)}setAngularVelocity(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.setAngvel(G,!0)}setLinearVelocity(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.setLinvel(G,!0)}getLinearVelocity(t,e=new b){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 b){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);i?.setLinearDamping(e)}setAngularDamping(t,e){const i=this.actorBodies.get(t.id);i?.setAngularDamping(e)}createCharacterCollision(){return new i.CharacterCollision}addLandscapeGroup(t){const e=t.userData.src,s=e.landscape.heightMaps;for(const r of t.sections){this.staticBodies.has(r)&&this.world.removeRigidBody(this.staticBodies.get(r));const t=e.landscape.options.density+1,n=e.landscape.options.sectionSize,a=new Array(t);for(let e=0;e<t;e++)a[e]=new Array(t).fill(0);const c=s.find((t=>t.x===r.x&&t.y==r.y));if(null!=c)for(const e of c.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/n:console.warn("wrong index",{points:a,point:e,i:e.i%t,k:i,heightMap:c})}const l=e.landscape.options.density,d=a.flatMap((t=>t.reverse())),h=i.ColliderDesc.heightfield(l,l,new Float32Array(d),new i.Vector3(n,n,n));var o=r.getWorldPosition(new b);const u=this.world.createRigidBody(i.RigidBodyDesc.fixed()),y=new i.Vector3(0,0,0);K(y,o),u.setTranslation(y,!1),this.world.createCollider(h,u),this.staticBodies.set(r,u)}}addActor(t,e,s={}){if(0==e.length)return void console.error("No collision shapes were defined when adding actor to the physics system.");this.removeActor(t);const o=t.object;let r;switch(s.type??PhysicsBodyType.static){case PhysicsBodyType.dynamic:r=i.RigidBodyDesc.dynamic(),r.mass=s.mass??1;break;case PhysicsBodyType.kinematic:r=i.RigidBodyDesc.kinematicPositionBased();break;case PhysicsBodyType.kinematicVelocityBased:r=i.RigidBodyDesc.kinematicVelocityBased();break;default:r=(s.isTrigger,i.RigidBodyDesc.kinematicVelocityBased())}const n=this.world.createRigidBody(r);n.enableCcd(1==s.continousCollisionDetection);for(const t of e)this.addShape(n,t,o);J(n,(t=>{null!=s.isTrigger&&(t.setSensor(s.isTrigger),t.setActiveCollisionTypes(i.ActiveCollisionTypes.ALL),t.setActiveEvents(i.ActiveEvents.COLLISION_EVENTS)),null!=s.friction&&t.setFriction(s.friction),null!=s.density&&t.setDensity(s.density),null!=s.mass&&t.setMass(s.mass),null!=s.restitution&&t.setRestitution(s.restitution)})),O(n,o),!0===s.ignoreForNavMesh&&(n.userData={ignoreForNavMesh:!0}),this.actorBodies.set(t.id,n),this.bodyActors.set(n,t)}applyTorque(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.addTorque(G,!0)}applyTorqueImpulse(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.applyTorqueImpulse(G,!0)}resetForces(t){const e=this.actorBodies.get(t.id);e?.resetForces(!1)}resetTorques(t){const e=this.actorBodies.get(t.id);e?.resetTorques(!1)}applyForce(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.addForce(G,!0)}applyImpulse(t,e){const i=this.actorBodies.get(t.id);G.x=e.x,G.y=e.y,G.z=e.z,i?.applyImpulse(G,!0)}applyLocalForce(t,e,i){const s=this.actorBodies.get(t.id);K(G,e),null==i?s?.addForce(G,!0):(K(Q,i),s?.addForceAtPoint(G,Q,!0))}applyLocalImpulse(t,e,i){const s=this.actorBodies.get(t.id);K(G,e),null==i?s.applyImpulse(G,!0):(K(Q,i),s.applyImpulseAtPoint(G,Q,!0))}removeActor(t){if(null==t)return;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(l(t.disposed),n((({started:t})=>t===i)),a((({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}))),n((({a1:i,a2:s})=>null!=i&&null!=s&&i.id===t.id&&e(i,s))),a((({a2:t})=>t)))}onBeginContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(l(t.disposed),n((t=>t.started)),n((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),a((t=>t.handle2)))}onEndContact(t){return this.activateActorEvents(t),this.collisionEvents.pipe(l(t.disposed),n((t=>!t.started)),n((({handle1:e})=>{const i=this.bodyActors.get(this.world.getCollider(e).parent());return null!=i&&i.id===t.id})),a((t=>t.handle2)))}onHasContactChanged(t){const e=new Set,i=new o(!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(r())}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?O(e,t.object):console.warn("Actor has not been added to physics world",t)}setupWorld(){const t=new i.World({x:0,y:-9.81,z:0});this.world=t,t.maxVelocityIterations=4}getActorContacts(t,e){const s=this.actorBodies.get(t.id);if(s&&s.numColliders()>0){const o=s.collider(0);let r=o.shape,n=o.translation(),a=o.rotation(),c=e,l=.3;const d=this.world.castShape(n,a,c,r,l,!0,null,null,null,this.actorBodies.get(t.id),(t=>t.shape.type!=i.ShapeType.HeightField));if(null!=d){const t=new b,e=new b,i=new b;return X(t,d.witness2),X(e,d.witness1),X(i,d.normal1),i.negate(),[{ri:t,rj:e,ni:i}]}return[]}return console.warn("Actor is not added to the physics system"),[]}stop(){this.world?.bodies.forEach((t=>this.world.removeRigidBody(t))),this.world?.free(),this.fixedupdateSub?.unsubscribe()}createStaticBody(t,e,s){const o=s?.type===PhysicsBodyType.dynamic?i.RigidBodyDesc.dynamic():i.RigidBodyDesc.kinematicPositionBased(),r=this.world.createRigidBody(o);for(const i of e){const o=this.addShape(r,i,t);null!=s?.friction&&o.setFriction(s.friction),null!=s?.density&&o.setDensity(s.density),null!=s?.mass&&o.setMass(s.mass/e.length),null!=s?.restitution&&o.setRestitution(s.restitution)}return O(r,t),r}addShape(t,e,i){const s=i.getWorldScale(tt),o=this.createShape(e,s);o.friction=.1;const r=e.offset.clone().multiply(s);var n,a;return K(o.translation,r),n=o.rotation,a=(new v).setFromEuler(e.rotation),n.x=a.x,n.y=a.y,n.z=a.z,n.w=a.w,this.world.createCollider(o,t)}createShape(t,e){if(t instanceof D)return i.ColliderDesc.cuboid(t.dimensions.x*e.x/2,t.dimensions.y*e.y/2,t.dimensions.z*e.z/2);if(t instanceof z){return i.ColliderDesc.capsule(t.length/2*e.y,t.radius*Math.max(e.z,e.x))}if(t instanceof F){const e=null!=t.geometry.getIndex()?t.geometry:k.mergeVertices(t.geometry);return i.ColliderDesc.trimesh(new Float32Array(e.getAttribute("position").array),new Uint32Array(e.getIndex().array))}if(t instanceof T){let s;t.mesh instanceof d.Mesh?s=t.mesh.geometry:t.mesh instanceof d.BufferGeometry?s=t.mesh:console.log("Unknownd shape",{shapeInfo:t});const o=new Float32Array(s.getAttribute("position").array);if(t.mesh instanceof d.Mesh){const e=I(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 i.ColliderDesc.convexHull(o)}return t instanceof W?i.ColliderDesc.ball(t.radius*Math.max(e.x,e.y,e.z)):t instanceof R?i.ColliderDesc.cylinder(t.height/2*e.y,t.radiusTop*Math.max(e.z,e.x)):t instanceof M?i.ColliderDesc.cone(t.height*e.y,t.radiusBottom/2*Math.max(e.z,e.x)):t instanceof E?i.ColliderDesc.cuboid(t.width/2*e.x,t.height/2*e.y,.01):(console.error("Unsupported shape",t),i.ColliderDesc.cuboid(1,1,1))}};L=t([A(),e("design:paramtypes",[V,P])],L);export{L as PhysicsSystem};const j=new b,N=new d.Quaternion;function O(t,e){const s=e.getWorldPosition(j),o=e.getWorldQuaternion(N);t.setTranslation(new i.Vector3(s.x,s.y,s.z),!1),t.setRotation(new i.Quaternion(o.x,o.y,o.z,o.w),!1)}const q=new b,G=new i.Vector3(0,0,0),Q=new i.Vector3(0,0,0),H=(new b,{x:0,y:0}),U=async()=>{let t=await import("@dimforge/rapier3d-compat");return await t.init(),t};function K(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function X(t,e){t.x=e.x,t.y=e.y,t.z=e.z}function J(t,e){for(let i=0,s=t.numColliders();i<s;i++){e(t.collider(i))}}const Y=new b,Z=new b,$=t=>!t.isSensor(),tt=new b;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -54,6 +54,7 @@ export declare class RenderingView {
54
54
  clearOverlayCameras(): void;
55
55
  removeOverlayCamera(camera: Camera): void;
56
56
  private prevClearColor;
57
+ private hadBloom;
57
58
  render(deltaTime?: number): void;
58
59
  private bloomStoredMaterials;
59
60
  private hasBloom;
package/dist/rendering.js CHANGED
@@ -1,4 +1,4 @@
1
- var e;import{__decorate as t,__metadata as i}from"tslib";import*as s from"three";import{Mesh as r,Matrix4 as n,ShaderMaterial as a,Color as o,PerspectiveCamera as h,ShaderChunk as l}from"three";import{EffectComposer as d,UnrealBloomPass as c,VRButton as m}from"three-stdlib";import{RenderPass as p}from"three-stdlib";import{ShaderPass as u}from"three-stdlib";import{FXAAShader as g}from"three-stdlib";import{CSM as v}from"three-stdlib";import{CSMUtil as f}from"./csm.js";import{GammaCorrectionShader as w}from"three-stdlib";import{Reflector as b}from"three-stdlib";import{depthUniformName as x,resolutionUniformName as C,supportsDepthTextureExtension as S,nearUniformName as y,farUniformName as P}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as T}from"./shader-nodes/time.js";import{OutlinePass as R}from"./utils/three/outline-pass.js";import M from"./utils/three/stats.js";import{findFirstVisibleObject as W}from"./utils/three/traverse.js";import{lambertVertexShaderOverride as L}from"./rendering/shader-override.js";import{DepthPass as E}from"./utils/three/depth-pass.js";import{Service as H}from"typedi";(new s.Layers).set(9);const D=new s.MeshBasicMaterial({color:"black"}),F=new s.MeshDepthMaterial;F.depthPacking=s.RGBADepthPacking,F.blending=s.NoBlending;l.lights_pars_begin;l.lights_lambert_vertex=L;const B=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let z=e=class{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof h&&(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=B?.5:1,this.onResize=()=>{this.resizeRender(),this.paused||this.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=M(),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,this.prevClearColor=new o,this.bloomStoredMaterials={},window.renderer=this.renderer=new s.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new s.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(m.createButton(this.renderer)),this.composer=new d(this.renderer);var r=t.clientWidth/t.clientHeight;const n=new s.PerspectiveCamera(45,r,.5,800);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=s.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=s.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,f.renderingView=this,f.patchThreeAdd(),this.isDepthTextureExtensionSupported=S(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=e.createDepthRenderTarget(this.renderer,this.container);const a=new p(this.scene,this.camera);this.composer.addPass(a);const h=new c(new s.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);h.threshold=0,h.strength=.9,h.radius=1;const l=new d(this.renderer);l.renderToScreen=!1,l.addPass(a),l.addPass(h),this.bloomComposer=l;const v=new u(new s.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:l.renderTarget2.texture}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D baseTexture;\n uniform sampler2D bloomTexture;\n varying vec2 vUv;\n void main() {\n gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n }",defines:{}}),"baseTexture");if(v.needsSwap=!0,this.composer.addPass(v),this.outlinePass=new R(new s.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 u(g);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var b=new u(w);b.clear=!1,this.composer.addPass(b)}setCamera(e){this.camera=e,this.composer.passes.forEach((t=>{t instanceof p?t.camera=e:t instanceof R?t.renderCamera=e:t instanceof E&&(t.camera=e)})),null==this.csm?this.csm=new v({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new s.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof h&&(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(e,t){var i=!!e.extensions.get("WEBGL_depth_texture");const r=new s.WebGLRenderTarget(t.clientWidth*e.getPixelRatio(),t.clientHeight*e.getPixelRatio());return r.texture.minFilter=s.NearestFilter,r.texture.magFilter=s.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===i&&(r.depthTexture=new s.DepthTexture(128,128),r.depthTexture.type=s.UnsignedShortType,r.depthTexture.minFilter=s.NearestFilter,r.depthTexture.magFilter=s.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(e,t=!1){const i=this.stats;i.showPanel(0),this.showStats=t;performance.now();s.Ray.prototype.intersectTriangle;let a=0;const o=new n,h=new n,l=t=>{const s=this.renderer.getContext();if(this.paused&&this.running&&s.drawingBufferHeight>1)return void setTimeout((()=>l(t)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,i.begin();let n=(t*=.001)-a;if(a=t,o.copy(this.camera.matrixWorld),n>1){let t=n;for(;t>.05;)e(O),t-=O;e(t)}else e(n);this.onLoopCallbacks.forEach((e=>e(n))),this.camera?.updateMatrixWorld(),h.copy(this.camera.matrixWorld),h.equals(o)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const d=[],c=[];if(this.scene.traverse((e=>{e instanceof r&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[x])?(e.visible=!1,d.push(e),this.initDepthUniform(e.material),e.renderOrder=100):e instanceof b&&(e.visible=!1,c.push(e)),e instanceof r&&e.material?.uniforms&&null!=e.material?.uniforms[T]&&(e.material.uniforms[T].value=t)})),d.length>0){if(this.scene.overrideMaterial=F,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}d.forEach((e=>e.visible=!0)),c.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.render(n),this.renderOverlay())}catch(e){console.warn(e)}i.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(l)}),1e3/this.fpsCap):requestAnimationFrame(l))};!0===this.options.enableXR?this.renderer.setAnimationLoop(l):requestAnimationFrame(l)}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(e){if(this.hasBloom()){const e=this.scene.fog;this.scene.fog=null;const t=this.renderer.getClearColor(this.prevClearColor);this.renderer.setClearColor(0),this.scene.traverseVisible((e=>this.darkenNonBloomed(e))),this.bloomComposer.render(),this.scene.traverse((e=>this.restoreMaterial(e))),this.renderer.setClearColor(t),this.scene.fog=e}this.composer.render(e)}hasBloom(){return null!=W(this.scene,(e=>e instanceof r&&!0===e.material?.userData?.hasBloom))}darkenNonBloomed(e){e.isMesh&&e.visible&&!0!==e.material.userData.hasBloom&&(this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=D:e.visible=!1)}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof a&&(e.uniforms[x].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[C]&&e.uniforms[C].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof h&&(e.uniforms[y].value=this.camera.near,e.uniforms[P].value=this.camera.far))}};z=e=t([H(),i("design:paramtypes",[HTMLElement,Object])],z);export{z as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const O=.05;
1
+ var e;import{__decorate as t,__metadata as i}from"tslib";import*as s from"three";import{Mesh as r,Matrix4 as n,ShaderMaterial as a,Color as o,PerspectiveCamera as h,ShaderChunk as l}from"three";import{EffectComposer as d,UnrealBloomPass as c,VRButton as m}from"three-stdlib";import{RenderPass as p}from"three-stdlib";import{ShaderPass as u}from"three-stdlib";import{FXAAShader as g}from"three-stdlib";import{CSM as v}from"three-stdlib";import{CSMUtil as f}from"./csm.js";import{GammaCorrectionShader as w}from"three-stdlib";import{Reflector as b}from"three-stdlib";import{depthUniformName as x,resolutionUniformName as C,supportsDepthTextureExtension as S,nearUniformName as y,farUniformName as P}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as T}from"./shader-nodes/time.js";import{OutlinePass as R}from"./utils/three/outline-pass.js";import M from"./utils/three/stats.js";import{findFirstVisibleObject as W}from"./utils/three/traverse.js";import{lambertVertexShaderOverride as L}from"./rendering/shader-override.js";import{DepthPass as E}from"./utils/three/depth-pass.js";import{Service as H}from"typedi";(new s.Layers).set(9);const B=new s.MeshBasicMaterial({color:"black"}),D=new s.MeshDepthMaterial;D.depthPacking=s.RGBADepthPacking,D.blending=s.NoBlending;l.lights_pars_begin;l.lights_lambert_vertex=L;const F=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let z=e=class{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof h&&(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=F?.5:1,this.onResize=()=>{this.resizeRender(),this.paused||this.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=M(),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,this.prevClearColor=new o,this.hadBloom=!1,this.bloomStoredMaterials={},window.renderer=this.renderer=new s.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new s.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(m.createButton(this.renderer)),this.composer=new d(this.renderer);var r=t.clientWidth/t.clientHeight;const n=new s.PerspectiveCamera(45,r,.5,800);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=s.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=s.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,f.renderingView=this,f.patchThreeAdd(),this.isDepthTextureExtensionSupported=S(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=e.createDepthRenderTarget(this.renderer,this.container);const a=new p(this.scene,this.camera);this.composer.addPass(a);const h=new c(new s.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);h.threshold=0,h.strength=.9,h.radius=1;const l=new d(this.renderer);l.renderToScreen=!1,l.addPass(a),l.addPass(h),this.bloomComposer=l;const v=new u(new s.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:l.renderTarget2.texture}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D baseTexture;\n uniform sampler2D bloomTexture;\n varying vec2 vUv;\n void main() {\n gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n }",defines:{}}),"baseTexture");if(v.needsSwap=!0,this.composer.addPass(v),this.outlinePass=new R(new s.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 u(g);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var b=new u(w);b.clear=!1,this.composer.addPass(b)}setCamera(e){this.camera=e,this.composer.passes.forEach((t=>{t instanceof p?t.camera=e:t instanceof R?t.renderCamera=e:t instanceof E&&(t.camera=e)})),null==this.csm?this.csm=new v({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new s.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof h&&(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(e,t){var i=!!e.extensions.get("WEBGL_depth_texture");const r=new s.WebGLRenderTarget(t.clientWidth*e.getPixelRatio(),t.clientHeight*e.getPixelRatio());return r.texture.minFilter=s.NearestFilter,r.texture.magFilter=s.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===i&&(r.depthTexture=new s.DepthTexture(128,128),r.depthTexture.type=s.UnsignedShortType,r.depthTexture.minFilter=s.NearestFilter,r.depthTexture.magFilter=s.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(e,t=!1){const i=this.stats;i.showPanel(0),this.showStats=t;performance.now();s.Ray.prototype.intersectTriangle;let a=0;const o=new n,h=new n,l=t=>{const s=this.renderer.getContext();if(this.paused&&this.running&&s.drawingBufferHeight>1)return void setTimeout((()=>l(t)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,i.begin();let n=(t*=.001)-a;if(a=t,o.copy(this.camera.matrixWorld),n>1){let t=n;for(;t>.05;)e(O),t-=O;e(t)}else e(n);this.onLoopCallbacks.forEach((e=>e(n))),this.camera?.updateMatrixWorld(),h.copy(this.camera.matrixWorld),h.equals(o)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const d=[],c=[];if(this.scene.traverse((e=>{e instanceof r&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[x])?(e.visible=!1,d.push(e),this.initDepthUniform(e.material),e.renderOrder=100):e instanceof b&&(e.visible=!1,c.push(e)),e instanceof r&&e.material?.uniforms&&null!=e.material?.uniforms[T]&&(e.material.uniforms[T].value=t)})),d.length>0){if(this.scene.overrideMaterial=D,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}d.forEach((e=>e.visible=!0)),c.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.render(n),this.renderOverlay())}catch(e){console.warn(e)}i.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(l)}),1e3/this.fpsCap):requestAnimationFrame(l))};!0===this.options.enableXR?this.renderer.setAnimationLoop(l):requestAnimationFrame(l)}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(e){const t=this.hasBloom();if(t||this.hadBloom){const e=this.scene.fog;this.scene.fog=null;const t=this.renderer.getClearColor(this.prevClearColor);this.renderer.setClearColor(0),this.scene.traverseVisible((e=>this.darkenNonBloomed(e))),this.bloomComposer.render(),this.scene.traverse((e=>this.restoreMaterial(e))),this.renderer.setClearColor(t),this.scene.fog=e}this.hadBloom=t,this.composer.render(e)}hasBloom(){return null!=W(this.scene,(e=>e instanceof r&&!0===e.material?.userData?.hasBloom))}darkenNonBloomed(e){e.isMesh&&e.visible&&!0!==e.material.userData.hasBloom&&(this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=B:e.visible=!1)}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof a&&(e.uniforms[x].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[C]&&e.uniforms[C].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof h&&(e.uniforms[y].value=this.camera.near,e.uniforms[P].value=this.camera.far))}};z=e=t([H(),i("design:paramtypes",[HTMLElement,Object])],z);export{z as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const O=.05;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -2,6 +2,7 @@ import { Object3D, Texture } from 'three';
2
2
  import { Asset } from './model.js';
3
3
  import { CollisionShape } from './collision/collision-shape.js';
4
4
  import * as THREE from 'three';
5
+ import { SceneObjectPhysicsSettings } from './materializer.js';
5
6
  export declare class AssetResourceLoader {
6
7
  private basePath;
7
8
  private cache;
@@ -32,5 +33,6 @@ export interface LoadedMesh {
32
33
  }
33
34
  export declare class AssetMeshInstance extends Object3D {
34
35
  collisionShapes?: CollisionShape[];
36
+ physics?: SceneObjectPhysicsSettings;
35
37
  }
36
38
  export declare function getElectronArg(name: string): string;
@@ -1,4 +1,4 @@
1
- import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as a}from"./sky.js";export async function loadScene(r,i,s,o,c,m,l,p,f){e();const{scene:w,renderer:d,camera:j}=r;a(w);const u=await l.getScene(i);if(null==u)throw Error(`Could not find scene with name ${i}`);const y=await l.getSceneData(u.id),S=new t;S.initiate(y);const g=Object.entries(o).map((([e,t])=>({name:e,type:t}))),h=Object.entries(c).map((([e,t])=>({name:e,type:t}))),v=new n(w,S,p,f,r,g,h,m);return await v.initWithInstancing(),{scene:w,view:r,materializer:v,assetResourceLoader:f,assetsService:p,actors:v.actorInstances}}
1
+ import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as i}from"./sky.js";export async function loadScene(r,a,s,o,c,m,l,p,d){e();const{scene:f,renderer:w,camera:j}=r;i(f);const u=await l.getScene(a);if(null==u)throw Error(`Could not find scene with name ${a}`);const y=await l.getSceneData(u.id),S=new t;S.initiate(y);const g=Object.entries(o).map((([e,t])=>({name:e,type:t}))),h=Object.entries(c).map((([e,t])=>({name:e,type:t}))),v=new n(f,S,p,d,r,g,h,m);return v.inEditor=!1,await v.initWithInstancing(),{scene:f,view:r,materializer:v,assetResourceLoader:d,assetsService:p,actors:v.actorInstances}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,5 @@
1
- import { BoxGeometry, BufferGeometry, Euler, Material, Mesh, Vector3 } from "three";
1
+ import { SceneObjectPhysicsSettings } from "../../scene/materializer.js";
2
+ import { BufferGeometry, Euler, Material, Mesh, Vector3 } from "three";
2
3
  export declare class CollisionShape {
3
4
  offset: Vector3;
4
5
  rotation: Euler;
@@ -50,10 +51,7 @@ export declare class CapsuleCollisionShape extends CollisionShape {
50
51
  }
51
52
  export declare class PhysicalShapeMesh extends Mesh {
52
53
  collisionShape: CollisionShape;
54
+ physics?: SceneObjectPhysicsSettings;
53
55
  isPhysicalShapeMesh: boolean;
54
- constructor(geometry: BufferGeometry, material: Material, collisionShape: CollisionShape);
55
- }
56
- export declare class PhysicalBoxMesh extends PhysicalShapeMesh {
57
- isPhysicalBoxMesh: boolean;
58
- constructor(geometry: BoxGeometry, material: Material);
56
+ constructor(geometry: BufferGeometry, material: Material, collisionShape: CollisionShape, physics?: SceneObjectPhysicsSettings);
59
57
  }
@@ -1,4 +1,4 @@
1
- import{Euler as s,Mesh as e,Vector3 as o}from"three";export class CollisionShape{constructor(){this.offset=new o,this.rotation=new s}withOffset(s){return this.offset.copy(s),this}withRotation(s){return this.rotation.copy(s),this}}export class BoxCollisionShape extends CollisionShape{constructor(s){super(),this.dimensions=s}}export class PlaneCollisionShape extends CollisionShape{constructor(s,e){super(),this.width=s,this.height=e}}export class SphereCollisionShape extends CollisionShape{constructor(s){super(),this.radius=s}}export class CylinderCollisionShape extends CollisionShape{constructor(s,e,o,t,i){super(),this.radiusTop=s,this.radiusBottom=e,this.height=o,this.segments=t,this.orentation=i}}export class ConeCollisionShape extends CollisionShape{constructor(s,e){super(),this.radiusBottom=s,this.height=e}}export class ConvexPolyhedronCollisionShape extends CollisionShape{constructor(s){super(),this.mesh=s}}export class TrimeshCollisionShape extends CollisionShape{constructor(s){super(),this.geometry=s}}export class MeshCollisionShape extends CollisionShape{constructor(s){super(),this.geometry=s}}export class CapsuleCollisionShape extends CollisionShape{constructor(s,e){super(),this.length=s,this.radius=e}}export class PhysicalShapeMesh extends e{constructor(s,e,o){super(s,e),this.collisionShape=o,this.isPhysicalShapeMesh=!0}}export class PhysicalBoxMesh extends PhysicalShapeMesh{constructor(s,e){super(s,e,new BoxCollisionShape(new o(s.parameters.width,s.parameters.height,s.parameters.depth))),this.isPhysicalBoxMesh=!0}}
1
+ import{Euler as s,Mesh as o,Vector3 as e}from"three";export class CollisionShape{constructor(){this.offset=new e,this.rotation=new s}withOffset(s){return this.offset.copy(s),this}withRotation(s){return this.rotation.copy(s),this}}export class BoxCollisionShape extends CollisionShape{constructor(s){super(),this.dimensions=s}}export class PlaneCollisionShape extends CollisionShape{constructor(s,o){super(),this.width=s,this.height=o}}export class SphereCollisionShape extends CollisionShape{constructor(s){super(),this.radius=s}}export class CylinderCollisionShape extends CollisionShape{constructor(s,o,e,t,i){super(),this.radiusTop=s,this.radiusBottom=o,this.height=e,this.segments=t,this.orentation=i}}export class ConeCollisionShape extends CollisionShape{constructor(s,o){super(),this.radiusBottom=s,this.height=o}}export class ConvexPolyhedronCollisionShape extends CollisionShape{constructor(s){super(),this.mesh=s}}export class TrimeshCollisionShape extends CollisionShape{constructor(s){super(),this.geometry=s}}export class MeshCollisionShape extends CollisionShape{constructor(s){super(),this.geometry=s}}export class CapsuleCollisionShape extends CollisionShape{constructor(s,o){super(),this.length=s,this.radius=o}}export class PhysicalShapeMesh extends o{constructor(s,o,e,t){super(s,o),this.collisionShape=e,this.physics=t,this.isPhysicalShapeMesh=!0}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{materialFromAsset as e}from"../../scene/materializer.js";import{Mesh as t,PlaneGeometry as s,Vector3 as n,InstancedMesh as a,Matrix4 as o,MeshLambertMaterial as i,Color as r,Vector2 as c,Triangle as l,Box3 as h,MathUtils as u,MeshStandardMaterial as f,ShaderMaterial as m,DoubleSide as d,PerspectiveCamera as p}from"three";import{indexBy as w}from"../../utils/collections.js";import{smoothNormalsCrossMeshes as y}from"./utils.js";import*as M from"three";import{defaultLandscapeMaterial as g,LandscapeMesh as x}from"./landscape.js";import{meanVectors3withWeight as S,clamp as b}from"../../utils/math.js";import{whenIdle as v}from"../../utils/async.js";import{Subject as A,debounceTime as z}from"rxjs";new n,new n;const P=new n,L=new n,j=new n;export class LandscapeManager{constructor(e,t,s,a,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=a,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new A,this.defaultLandscapeMaterial=g.clone(),this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new o,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.name=g.name,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}async loadGrass(){const e=await this.assetService.getAsset("6ij937n72g");await this.assetManagerService.getMesh(e);this.grassGeometry=new s(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=[];j.fromArray(this.source.position);const a=this.view.camera instanceof p?Math.min(this.view.camera.far,1e3):1e3,o=1.1*a,i=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(P.x=r+n*e.sectionSize,!(Math.abs(t.x-P.x)>o))for(let c=0;c<e.sections.y;c++){P.z=i+c*e.sectionSize,L.copy(j).add(P);const l=L.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=a){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,i,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>o&&this.landscape.remove(u)}y(s)}applyHeightMap(e,t,s,n=1){const a=Math.pow(s+1,2),o=e.getAttribute("position"),i=w(t.points??[],(e=>e.i));if(1===n)for(const e of t.points)o.setY(e.i,e.y);else for(let e=0;e<o.count;e++){const t=B(e,o.count,a);let s=0;s=t%1==0?i.get(t)?.y??0:Math.floor(i.get(t)?.y),o.setY(e,s)}o.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){const e=new Set;for(const[t,s]of this.source.grass?.layers.entries()??[])for(const[n,a]of s.meshes.entries()){const s=`${t}-${n}`;e.add(s)}for(const t of this.scatterMeshes.keys())if(!e.has(t)){this.scatterMeshes.get(t).forEach((e=>{e.parent?.remove(e),e.dispose()})),this.scatterMeshes.delete(t)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}async refreshScatter(o,c=!1,h=(()=>!0)){c&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[f,p]of this.source.grass?.layers.entries()??[])for(const[y,g]of p.meshes.entries()){const p=`${f}-${y}`;this.scatterMeshes.has(p)||this.scatterMeshes.set(p,new Map);const x=this.scatterMeshes.get(p),A=await this.assetService.getAsset(g.assetId),z=await this.assetManagerService.getMesh(A),P=[];if(z.scene.traverse((e=>{e instanceof t&&P.push(e)})),1!==P.length){console.log(z),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(P[0]instanceof t)){console.warn("Only meshes can be used for dynamic grass. Found:",z.scene);continue}const L=P[0];let j=L.geometry;this.scatterGeometryCache.has(L.geometry.uuid)?j=this.scatterGeometryCache.get(L.geometry.uuid):(j=L.geometry.clone(),!0===g.normalsUp&&Y(j),this.scatterGeometryCache.set(L.geometry.uuid,j),null==j.userData.updatedMatrix&&(z.scene.updateMatrixWorld(),j.applyMatrix4(L.matrixWorld),j.userData.updatedMatrix=!0));const B=j.getIndex().count/3;if(B>400){console.warn(`The triangle count of ${A.name} is too big ${B}. Keep it below 400`);continue}const G=null!=A.materialAssignments&&A.materialAssignments.length>0?A.materialAssignments[0].materialId:null,R=null!=G&&"null"!==G?await e(await this.assetService.getAsset(G),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let U=null!=R?R:L.material;U instanceof m&&(U.side=d);const W=u.degToRad(g.maxSlope??90),D=Math.cos(W),O=this.landscape.sections,E=O.filter(_(o,g.viewDistance)).filter((e=>!x.has(e.uuid)||c)).filter((e=>h(e)));O.filter($(o,2*g.viewDistance)).forEach((e=>{const t=x.get(e.uuid);t?.parent?.remove(t),x.delete(e.uuid)}));performance.now();const X=this.source.landscape.options,F=X.sectionSize,N=g.density??1??1,Z=X.density,K=F/Z,V=N,J=K/Math.sqrt(V),Q=Math.pow(Z,2),ee=J/K,te=Math.floor(Q*V),se=[0,0,0];for(const e of E)await v((async()=>{e.updateWorldMatrix(!0,!1);const t=this._matrix,o=new n,h=e.geometry.getAttribute("position"),u=e.geometry.getAttribute("normal"),m=(this.source.vertexMaterials??[]).filter((t=>t.m===e.name)),d=w(m,(e=>e.i));let p=x.get(e.uuid);if(null==p||p.count==te&&!c||(p.parent?.remove(p),x.delete(e.uuid),p=null),null==p){const e=new s(.15,.75).getAttribute("normal");for(let t=0;t<e.count;t++);new i({color:new r(3765785),side:M.DoubleSide});p=new a(j,U,te),p.raycast=()=>{},p.receiveShadow=!0}const y=new l(new n,new n,new n);let[v,A,z,P]=[new n,new n,new n,new n],[L,B,G]=[[],[],[]],[$,_,R]=[new n,new n,new n,new n];const W=new n,O=new n,Y=new n,E=new n,X=new l(new n,new n,new n),F=new l(new n,new n,new n),N=new l(new n,new n,new n),K=new l(new n,new n,new n);let J=0;e:for(let s=0;s<Q;s++){const n=Math.floor(s/Z);v.fromBufferAttribute(h,s+n),E.copy(v).applyMatrix4(e.matrixWorld),X.a.copy(v),X.b.fromBufferAttribute(h,s+1+n),X.c.fromBufferAttribute(h,s+Z+1+n),F.a.copy(X.b),F.b.copy(X.c),F.c.fromBufferAttribute(h,s+Z+2+n),N.a.fromBufferAttribute(u,s+n),N.b.fromBufferAttribute(u,s+1+n),N.c.fromBufferAttribute(u,s+Z+1+n),K.a.copy(N.b),K.b.copy(N.c),K.c.fromBufferAttribute(u,s+Z+2+n);const a=[];a[0]=d.get(s+n)?.w,a[1]=d.get(s+1+n)?.w,a[2]=d.get(s+Z+1+n)?.w,a[3]=d.get(s+Z+2+n)?.w;let i=0;for(let s=0;s<=1+ee;s+=ee)for(let n=0;n<=1+ee;n+=ee){if(J>te)break e;if(i++,i>V)continue e;1-s>n?(A=X.a,z=X.b,P=X.c,$=N.a,_=N.b,R=N.c,L=a[0],B=a[1],G=a[2]):(A=F.a,z=F.b,P=F.c,$=K.a,_=K.b,R=K.c,L=a[1],B=a[2],G=a[3]),y.a.copy(A),y.b.copy(z),y.c.copy(P),C(y),W.set(v.x,0,v.z),W.x=q(y.a.x,y.b.x),W.z=q(y.a.z,y.c.z),y.getBarycoord(W,o).toArray(se);if(k([L,B,G],se,.2)!==f-1)continue;const r=[A,z,P];S(r,se,O),S([$,_,R],se,Y);const c=r.map((e=>e.y)),l=Math.max(...c),h=Math.min(...c);if(O.y=b(O.y,h,l),null!=g.maxSlope&&g.maxSlope<90&&Y.y<D)continue;const u=O.applyMatrix4(e.matrixWorld);u.y+=q(g.offsetMin,g.offsetMax);const m=q(g.scaleMin,g.scaleMax);t.makeScale(1,1,1),t.setPosition(u),t.scale(T(m)),g.alignToNormal&&I(t,u,p.matrixWorld,Y),!1!==g.randomRotation&&H(t),p.setMatrixAt(J,t),J++}}p.instanceMatrix.count=J,t.makeScale(0,0,0);for(let e=J;e<te;e++)p.setMatrixAt(e,t);p.instanceMatrix.needsUpdate=!0,x.has(e.uuid)||this.landscape?.attach(p),x.set(e.uuid,p)}));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=>e.parent?.remove(e)))))}createLandscapeMesh(e,t,n,a,o,i){const r=new s(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=n+o*t.sectionSize,l.position.z=a+i*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:o,y:i},l.x=o,l.y=i,l.name=`${o},${i}`;const h=e.landscape.heightMaps.find((e=>e.x===o&&e.y===i));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function B(e,t,s){const n=Math.sqrt(t),a=Math.floor(e/n)/(n-1),o=e%n/(n-1),i=Math.sqrt(s);return(s-1)*a-(i-1)*a+(i-1)*o}new Map,new c(0,0),new c(1,0),new c(0,1),new c(1,0),new c(0,1),new c(1,1),new n;const G=new h;function $(e,t){return function(s){return G.setFromObject(s).distanceToPoint(e)>t}}function _(e,t){return function(s){return G.setFromObject(s).distanceToPoint(e)<t}}function C(e){e.a.y=0,e.b.y=0,e.c.y=0}function k(e,t,s=.5){let n=-1,a=0;for(let o=0;o<e.length;o++)if(null!=e[o])for(let i=0;i<e[o].length;i++){const r=e[o][i]*t[o];r>s&&r>a&&(a=r,n=i)}return n}function q(e,t){let s=t-e,n=Math.random();return n*=s,n+=e,n}const R=new n;function T(e){return R.set(e,e,e)}new n;const U=new n,W=new n(0,1,0),D=(new o).makeRotationX(Math.PI/-2);function I(e,t,s,n){e.lookAt(U,n,W).multiply(D)}const O=new o;function H(e){e.multiply(O.makeRotationY(Math.random()*Math.PI/2))}function Y(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{materialFromAsset as e}from"../../scene/materializer.js";import{Mesh as t,PlaneGeometry as s,Vector3 as n,InstancedMesh as a,Matrix4 as o,MeshLambertMaterial as i,Color as r,Vector2 as c,Triangle as l,Box3 as h,MathUtils as u,MeshStandardMaterial as f,ShaderMaterial as m,DoubleSide as d,PerspectiveCamera as p}from"three";import{indexBy as w}from"../../utils/collections.js";import{smoothNormalsCrossMeshes as y}from"./utils.js";import*as M from"three";import{defaultLandscapeMaterial as g,LandscapeMesh as x}from"./landscape.js";import{meanVectors3withWeight as S,clamp as b}from"../../utils/math.js";import{whenIdle as v}from"../../utils/async.js";import{Subject as A,debounceTime as z}from"rxjs";new n,new n;const P=new n,L=new n,j=new n;export class LandscapeManager{constructor(e,t,s,a,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=a,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new A,this.defaultLandscapeMaterial=g.clone(),this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new o,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.name=g.name,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}async loadGrass(){const e=await this.assetService.getAsset("6ij937n72g");await this.assetManagerService.getMesh(e);this.grassGeometry=new s(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=[];j.fromArray(this.source.position);const a=this.view.camera instanceof p?Math.min(this.view.camera.far,1e3):1e3,o=1.1*a,i=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(P.x=r+n*e.sectionSize,!(Math.abs(t.x-P.x)>o))for(let c=0;c<e.sections.y;c++){P.z=i+c*e.sectionSize,L.copy(j).add(P);const l=L.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=a){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,i,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>o&&this.landscape.remove(u)}y(s)}applyHeightMap(e,t,s,n=1){const a=Math.pow(s+1,2),o=e.getAttribute("position");if(1===n)for(const e of t.points)o.setY(e.i,e.y);else{const e=w(t.points??[],(e=>e.i));for(let t=0;t<o.count;t++){const s=B(t,o.count,a);let n=0;n=s%1==0?e.get(s)?.y??0:Math.floor(e.get(s)?.y),o.setY(t,n)}}o.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){const e=new Set;for(const[t,s]of this.source.grass?.layers.entries()??[])for(const[n,a]of s.meshes.entries()){const s=`${t}-${n}`;e.add(s)}for(const t of this.scatterMeshes.keys())if(!e.has(t)){this.scatterMeshes.get(t).forEach((e=>{e.parent?.remove(e),e.dispose()})),this.scatterMeshes.delete(t)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}async refreshScatter(o,c=!1,h=(()=>!0)){c&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[f,p]of this.source.grass?.layers.entries()??[])for(const[y,g]of p.meshes.entries()){const p=`${f}-${y}`;this.scatterMeshes.has(p)||this.scatterMeshes.set(p,new Map);const x=this.scatterMeshes.get(p),A=await this.assetService.getAsset(g.assetId),z=await this.assetManagerService.getMesh(A),P=[];if(z.scene.traverse((e=>{e instanceof t&&P.push(e)})),1!==P.length){console.log(z),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(P[0]instanceof t)){console.warn("Only meshes can be used for dynamic grass. Found:",z.scene);continue}const L=P[0];let j=L.geometry;this.scatterGeometryCache.has(L.geometry.uuid)?j=this.scatterGeometryCache.get(L.geometry.uuid):(j=L.geometry.clone(),!0===g.normalsUp&&Y(j),this.scatterGeometryCache.set(L.geometry.uuid,j),null==j.userData.updatedMatrix&&(z.scene.updateMatrixWorld(),j.applyMatrix4(L.matrixWorld),j.userData.updatedMatrix=!0));const B=j.getIndex().count/3;if(B>400){console.warn(`The triangle count of ${A.name} is too big ${B}. Keep it below 400`);continue}const G=null!=A.materialAssignments&&A.materialAssignments.length>0?A.materialAssignments[0].materialId:null,R=null!=G&&"null"!==G?await e(await this.assetService.getAsset(G),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let U=null!=R?R:L.material;U instanceof m&&(U.side=d);const W=u.degToRad(g.maxSlope??90),D=Math.cos(W),O=this.landscape.sections,E=O.filter(_(o,g.viewDistance)).filter((e=>!x.has(e.uuid)||c)).filter((e=>h(e)));O.filter($(o,2*g.viewDistance)).forEach((e=>{const t=x.get(e.uuid);t?.parent?.remove(t),x.delete(e.uuid)}));performance.now();const X=this.source.landscape.options,F=X.sectionSize,N=g.density??1??1,Z=X.density,K=F/Z,V=N,J=K/Math.sqrt(V),Q=Math.pow(Z,2),ee=J/K,te=Math.floor(Q*V),se=[0,0,0];for(const e of E)await v((async()=>{e.updateWorldMatrix(!0,!1);const t=this._matrix,o=new n,h=e.geometry.getAttribute("position"),u=e.geometry.getAttribute("normal"),m=(this.source.vertexMaterials??[]).filter((t=>t.m===e.name)),d=w(m,(e=>e.i));let p=x.get(e.uuid);if(null==p||p.count==te&&!c||(p.parent?.remove(p),x.delete(e.uuid),p=null),null==p){const e=new s(.15,.75).getAttribute("normal");for(let t=0;t<e.count;t++);new i({color:new r(3765785),side:M.DoubleSide});p=new a(j,U,te),p.raycast=()=>{},p.receiveShadow=!0}const y=new l(new n,new n,new n);let[v,A,z,P]=[new n,new n,new n,new n],[L,B,G]=[[],[],[]],[$,_,R]=[new n,new n,new n,new n];const W=new n,O=new n,Y=new n,E=new n,X=new l(new n,new n,new n),F=new l(new n,new n,new n),N=new l(new n,new n,new n),K=new l(new n,new n,new n);let J=0;e:for(let s=0;s<Q;s++){const n=Math.floor(s/Z);v.fromBufferAttribute(h,s+n),E.copy(v).applyMatrix4(e.matrixWorld),X.a.copy(v),X.b.fromBufferAttribute(h,s+1+n),X.c.fromBufferAttribute(h,s+Z+1+n),F.a.copy(X.b),F.b.copy(X.c),F.c.fromBufferAttribute(h,s+Z+2+n),N.a.fromBufferAttribute(u,s+n),N.b.fromBufferAttribute(u,s+1+n),N.c.fromBufferAttribute(u,s+Z+1+n),K.a.copy(N.b),K.b.copy(N.c),K.c.fromBufferAttribute(u,s+Z+2+n);const a=[];a[0]=d.get(s+n)?.w,a[1]=d.get(s+1+n)?.w,a[2]=d.get(s+Z+1+n)?.w,a[3]=d.get(s+Z+2+n)?.w;let i=0;for(let s=0;s<=1+ee;s+=ee)for(let n=0;n<=1+ee;n+=ee){if(J>te)break e;if(i++,i>V)continue e;1-s>n?(A=X.a,z=X.b,P=X.c,$=N.a,_=N.b,R=N.c,L=a[0],B=a[1],G=a[2]):(A=F.a,z=F.b,P=F.c,$=K.a,_=K.b,R=K.c,L=a[1],B=a[2],G=a[3]),y.a.copy(A),y.b.copy(z),y.c.copy(P),C(y),W.set(v.x,0,v.z),W.x=q(y.a.x,y.b.x),W.z=q(y.a.z,y.c.z),y.getBarycoord(W,o).toArray(se);if(k([L,B,G],se,.2)!==f-1)continue;const r=[A,z,P];S(r,se,O),S([$,_,R],se,Y);const c=r.map((e=>e.y)),l=Math.max(...c),h=Math.min(...c);if(O.y=b(O.y,h,l),null!=g.maxSlope&&g.maxSlope<90&&Y.y<D)continue;const u=O.applyMatrix4(e.matrixWorld);u.y+=q(g.offsetMin,g.offsetMax);const m=q(g.scaleMin,g.scaleMax);t.makeScale(1,1,1),t.setPosition(u),t.scale(T(m)),g.alignToNormal&&I(t,u,p.matrixWorld,Y),!1!==g.randomRotation&&H(t),p.setMatrixAt(J,t),J++}}p.instanceMatrix.count=J,t.makeScale(0,0,0);for(let e=J;e<te;e++)p.setMatrixAt(e,t);p.instanceMatrix.needsUpdate=!0,x.has(e.uuid)||this.landscape?.attach(p),x.set(e.uuid,p)}));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=>e.parent?.remove(e)))))}createLandscapeMesh(e,t,n,a,o,i){const r=new s(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=n+o*t.sectionSize,l.position.z=a+i*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:o,y:i},l.x=o,l.y=i,l.name=`${o},${i}`;const h=e.landscape.heightMaps.find((e=>e.x===o&&e.y===i));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function B(e,t,s){const n=Math.sqrt(t),a=Math.floor(e/n)/(n-1),o=e%n/(n-1),i=Math.sqrt(s);return(s-1)*a-(i-1)*a+(i-1)*o}new Map,new c(0,0),new c(1,0),new c(0,1),new c(1,0),new c(0,1),new c(1,1),new n;const G=new h;function $(e,t){return function(s){return G.setFromObject(s).distanceToPoint(e)>t}}function _(e,t){return function(s){return G.setFromObject(s).distanceToPoint(e)<t}}function C(e){e.a.y=0,e.b.y=0,e.c.y=0}function k(e,t,s=.5){let n=-1,a=0;for(let o=0;o<e.length;o++)if(null!=e[o])for(let i=0;i<e[o].length;i++){const r=e[o][i]*t[o];r>s&&r>a&&(a=r,n=i)}return n}function q(e,t){let s=t-e,n=Math.random();return n*=s,n+=e,n}const R=new n;function T(e){return R.set(e,e,e)}new n;const U=new n,W=new n(0,1,0),D=(new o).makeRotationX(Math.PI/-2);function I(e,t,s,n){e.lookAt(U,n,W).multiply(D)}const O=new o;function H(e){e.multiply(O.makeRotationY(Math.random()*Math.PI/2))}function Y(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.