@hology/core 0.0.206 → 0.0.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/sequence-data.d.ts +8 -3
- package/dist/effects/sequence/sequence-data.js +1 -1
- package/dist/effects/sequence/sequence-definitions.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +4 -0
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/sequence/sequence-value-lane.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/factory.d.ts +1 -0
- package/dist/gameplay/actors/factory.js +1 -1
- package/dist/gameplay/actors/internal/component-init.d.ts +1 -0
- package/dist/gameplay/actors/internal/component-init.js +1 -1
- package/dist/gameplay/animation/anim-sm.d.ts +2 -0
- package/dist/gameplay/animation/anim-sm.js +1 -1
- package/dist/gameplay/initiate.d.ts +3 -0
- package/dist/gameplay/initiate.js +1 -1
- package/dist/gameplay/services/world.js +1 -1
- package/dist/rendering/upscaling-pass.d.ts +95 -0
- package/dist/rendering/upscaling-pass.js +4 -0
- package/dist/rendering.d.ts +77 -1
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +2 -0
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/materializer.d.ts +2 -0
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/materials/water.js +1 -1
- package/dist/scene/runtime-asset-service.d.ts +2 -0
- package/dist/scene/runtime-asset-service.js +1 -1
- package/dist/scene/storage/storage.d.ts +3 -0
- package/dist/scene/storage/storage.js +1 -1
- package/dist/shader/builtin/landscape-composite-shader.d.ts +0 -1
- package/dist/shader/builtin/landscape-composite-shader.js +1 -1
- package/dist/shader/builtin/standard-shader.d.ts +13 -12
- package/dist/shader/builtin/standard-shader.js +1 -1
- package/dist/shader/builtin/toon-shader.d.ts +9 -7
- package/dist/shader/builtin/toon-shader.js +1 -1
- package/dist/shader/builtin/unlit-shader.d.ts +5 -4
- package/dist/shader/builtin/unlit-shader.js +1 -1
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/parameter.js +1 -1
- package/dist/shader-nodes/pom.js +1 -1
- package/dist/test/data-asset-definition.test.js +1 -1
- package/dist/test/parameter-definition.test.js +1 -1
- package/dist/test/runtime-asset-service.test.d.ts +2 -0
- package/dist/test/runtime-asset-service.test.js +4 -0
- package/dist/test/runtime-param-type-inference.test.js +1 -1
- package/dist/test/sequence-post-process.test.js +1 -1
- package/dist/test/sequence-property-parameters.test.js +1 -1
- package/dist/test/sequence-vfx.test.d.ts +2 -0
- package/dist/test/sequence-vfx.test.js +4 -0
- package/dist/test/shader-graph.test.js +1 -1
- package/dist/test/storage-case-collision.test.js +1 -1
- package/dist/test/world-lifecycle.test.d.ts +2 -0
- package/dist/test/world-lifecycle.test.js +4 -0
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as d,SkinnedMesh as p,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";import{ArrayMap as B}from"../../../../../utils/collections.js";const I=new d(0,-1,0),P=new d(0,1,0),x=new d(1,1,1),D=new f,F=new d,R=new d,A=new d,M=new d,T=new d,W=new f,O=new f,V=new f,C=new f,E=new g,q=new g,H=new d(1,0,0),z=new d(0,1,0),N=new d(0,0,1);function U(){return{point:new d,normal:new d,hasNormal:!1}}const j=["mixamorigHips","Hips","hips","Pelvis","pelvis"],Q={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},G={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},_=["left","right"];let K=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.poseProcessors=new B,this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new d,normal:new d(0,1,0),forward:new d(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new d,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new d,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:U(),toe:U(),heel:U(),side:U()},this.footIkAxesScratch={up:new d,forward:new d,right:new d},this.footIkSampleAxesScratch={forward:new d,right:new d},this.footIkScratch={footWorldPos:new d,centerRayStart:new d,toeRayStart:new d,heelRayStart:new d,sideRayStart:new d,desiredTargetPos:new d,desiredNormal:new d,desiredForward:new d,debugRayEndA:new d,debugRayEndB:new d,debugRayEndC:new d,debugRayEndD:new d,debugRayEndE:new d,debugRayEndF:new d},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=X(t=>t.uuid,t=>Y(this.fullBodyMask,t)),this.getUpperBodyClip=X(t=>t.uuid,t=>Y(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,I),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(I,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(tt(t,e)||tt(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof p||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=$(e),this.fullBodyMask=function(t,e){const o=new Set($(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(Z(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}addPoseProcessor(t){const e={id:t.id,phase:t.phase??"afterMixer",order:t.order??0,update:t.update};this.removePoseProcessor(e.id);const o=this.poseProcessors.get(e.phase);let i=o.findIndex(t=>t.order>e.order);return-1===i&&(i=o.length),o.splice(i,0,e),()=>{const t=o.indexOf(e);-1!==t&&(o.splice(t,1),0===o.length&&this.poseProcessors.delete(e.phase))}}removePoseProcessor(t){for(const[e,o]of this.poseProcessors.entries()){const i=o.findIndex(e=>e.id===t);if(-1!==i)return o.splice(i,1),void(0===o.length&&this.poseProcessors.delete(e))}}runPoseProcessors(t,e){if(0===this.poseProcessors.size||null==this.mixer||!this.poseProcessors.present(t))return;const o=this.mixer.getRoot();if(!(o instanceof a))return;const i=this.poseProcessorContext??(this.poseProcessorContext={deltaTime:e,phase:t,animation:this,mixer:this.mixer,root:o});i.deltaTime=e,i.phase=t,i.mixer=this.mixer,i.root=o;const s=this.poseProcessors.get(t);for(let t=0;t<s.length;t++)s[t].update(i)}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.runPoseProcessors("beforeMixer",t),this.mixer.update(t),this.runPoseProcessors("afterMixer",t),this.runPoseProcessors("beforeIk",t),this.updateFootIk(t),this.runPoseProcessors("afterIk",t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,Q),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,G);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(F)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(F)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??Z(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),d=i.getBoneByName("_IKTargetRightFoot"),p=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),p=!0),null==d&&(d=new l,d.name="_IKTargetRightFoot",h.add(d),p=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(F)),this.setBoneWorldPosition(d,r.foot.getWorldPosition(F)),p||i.bones.indexOf(c)<0||i.bones.indexOf(d)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(d)<0&&(t.push(d),e.push((new g).copy(d.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:d};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(d),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof p||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...j]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(F),o=t.lower.getWorldPosition(R),i=t.foot.getWorldPosition(A),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(F.copy(e))),t.quaternion.copy(D),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),d=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,d),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:d}}createDebugArrow(t){const e=new m(P,new d,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){F.subVectors(o,e);const i=F.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(F.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of _){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(F);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of _){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(F),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(R),r=A.copy(s).addScaledVector(P,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(R),h=A.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(W)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=E.copy(t.boneInverses[i]).invert(),n=q.copy(r).multiply(s),d=F.setFromMatrixPosition(n),p=M.copy(d).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,p.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(F),i=t.foot.getWorldPosition(R),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=M.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(P),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),d=r.centerRayStart.copy(l).addScaledVector(P,this.footIkRayStartHeight),p=r.toeRayStart.copy(d).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(d).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(d).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(d,n.center),m=this.getFirstGroundHit(p,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,B=this.footIkWeightOutSpeed;const I=null!=g||null!=m||null!=k;let x=l.y;null!=g?x=g.point.y:null!=m&&null!=k?x=.5*(m.point.y+k.point.y):null!=m?x=m.point.y:null!=k&&(x=k.point.y);const D=this.ikBoneRefs?.[t],F=this.ikLegLengths?.[t],R=null!=D&&null!=F?this.computeLegExtensionRatio(D,F):1,A=Math.max(0,l.y-x,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,I,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,B=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-B*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:d,toeRayStart:p,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),d=this.computeFootVerticalSpeed(s,c,n),p=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,p,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(P,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),B=l.desiredNormal.set(0,1,0),I=l.desiredForward.copy(u.forward);let x=0,D=0,F=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,d,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,B)){this.computeDesiredFootForward(u.forward,u.right,B,w,b,I),x=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(x))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),D=1,F=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,B,null,null,I),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-F*n);s.targetPosition.lerp(v,O),s.normal.lerp(B,O).normalize(),s.forward.lerp(I,O).normalize(),s.pitch=y.lerp(s.pitch,x,O),s.weight=y.lerp(s.weight,D,V),s.planted=W&&D>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:B,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(I,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(I,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(I,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(I,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new d,right:new d},n=this.actor.object.getWorldDirection(M);n.addScaledVector(P,-n.dot(P)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(P,-s.forward.dot(P)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=T.crossVectors(P,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,M);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=R.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=A.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(P),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(P)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(M)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=M.copy(this.actor.object.getWorldDirection(M));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=R.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=W.copy(e.quaternion),l=O.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=V.setFromAxisAngle(t.rightLocal,.15);return A.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=R.subVectors(i,o),r=s.dot(P),n=A.copy(s).addScaledVector(P,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(P,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(F).clone(),c=R.subVectors(i,h),d=c.length(),p=.995*e.total;d>p&&d>1e-6&&i.copy(h).addScaledVector(c,p/d)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(F).clone(),s=e.lower.getWorldPosition(R).clone(),r=e.foot.getWorldPosition(A).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new d).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,p=n+l-1e-4,u=y.clamp(h,c,p),f=a.multiplyScalar(1/h),g=(new d).subVectors(s,i).normalize(),m=(new d).subVectors(r,s).normalize(),k=(new d).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(F).cross(P)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new d).copy(i).addScaledVector(f,S);let v=(new d).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new d).crossVectors(f,P),v.lengthSq()<1e-8&&(v=new d(1,0,0))),v.normalize();const B=(new d).copy(L).addScaledVector(v,b),I=(new d).copy(L).addScaledVector(v,-b),x=(new d).subVectors(s,L).dot(v)>=0?B:I;this.rotateBoneToward(e.upper,i,s,x),e.upper.updateMatrixWorld(!0);const D=e.lower.getWorldPosition(R),M=e.foot.getWorldPosition(A);this.rotateBoneToward(e.lower,D,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,x,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new d).subVectors(o,e),r=(new d).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(W),a=O.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(V),c=C.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(W),o=this.actor.object.getWorldDirection(F);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)},{local:N.clone(),world:N.clone().applyQuaternion(e)}];i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:N.clone().multiplyScalar(-1),world:N.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(P);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new d,forward:new d,right:new d},r=e.getWorldQuaternion(W);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(P),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(P,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){W.copy(t.quaternion),t.quaternion.copy(e).slerp(W,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=F.copy(o.normal).normalize(),n=R.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=A.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(M.crossVectors(l,r)).normalize(),E.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),W.setFromRotationMatrix(E),q.makeBasis(l,r,n),O.setFromRotationMatrix(q);const a=V.copy(O).multiply(C.copy(W).invert()),h=e.parent.getWorldQuaternion(C),c=O.copy(h).invert().multiply(a),d=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(d,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,null==this.fullBodyAction||this.fullBodyAction.isRunning()||(this.fullBodyAction=null),null==this.upperBodyAction||this.upperBodyAction.isRunning()||(this.upperBodyAction=null),this.fullBodyTimer=0}cancelRootMotionAction(t){null!=t&&this.fullBodyAction!==t||(this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyAction?.stop(),this.fullBodyAction=null,this.fullBodyTimer=0)}beginExternalAnimationControl(t,e={}){J(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){J(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){const i=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return t.isRunning()||(t.reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play(),!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0)),t;if(t&&t.isRunning()){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};K=t([o({inEditor:!0})],K);export{K as CharacterAnimationComponent};function Y(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function $(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function J(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function X(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function Z(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function tt(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
|
|
1
|
+
import{__decorate as t}from"tslib";import{ActorComponent as e,Component as o}from"../../../component.js";import{RootMotionClip as i}from"../../../../animation/root-motion.js";import{inject as s}from"../../../../inject.js";import{ViewController as r}from"../../../../services/render.js";import{AnimationMixer as n,Bone as l,Object3D as a,LoopOnce as h,Raycaster as c,Vector3 as p,SkinnedMesh as d,Skeleton as u,Quaternion as f,Matrix4 as g,MathUtils as y,ArrowHelper as m,Group as k}from"three";import{CharacterMovementComponent as S}from"./character-movement.js";import{CCDIKSolver as w}from"three/addons/animation/CCDIKSolver.js";import{World as b}from"../../../../services/world.js";import{PhysicsSystem as L,RayTestResult as v}from"../../../../services/physics/physics-system.js";import{ArrayMap as B}from"../../../../../utils/collections.js";const I=new p(0,-1,0),P=new p(0,1,0),x=new p(1,1,1),F=new f,D=new p,R=new p,A=new p,M=new p,T=new p,W=new f,O=new f,V=new f,C=new f,E=new g,q=new g,H=new p(1,0,0),z=new p(0,1,0),N=new p(0,0,1);function U(){return{point:new p,normal:new p,hasNormal:!1}}const j=["mixamorigHips","Hips","hips","Pelvis","pelvis"],Q={upper:["LeftUpLeg","leftUpLeg","left_up_leg"],lower:["LeftLeg","leftLeg","left_leg"],foot:["LeftFoot","leftFoot","left_foot"]},G={upper:["RightUpLeg","rightUpLeg","right_up_leg"],lower:["RightLeg","rightLeg","right_leg"],foot:["RightFoot","rightFoot","right_foot"]},_=["left","right"];let K=class extends e{constructor(){super(...arguments),this.viewController=s(r),this.poseProcessors=new B,this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.externalControlActive=!1,this.world=s(b),this.physicsSystem=s(L),this.footIkEnabled=!1,this.footIkMoving=!1,this.footIkRayStartHeight=.5,this.footIkRayLength=1.5,this.footIkRaycastMode="physics",this.footIkFootOffset=.08,this.footIkAutoContactOffset=!1,this.footIkPositionLerpSpeed=28,this.footIkRotationLerpSpeed=14,this.footIkWeightInSpeed=34,this.footIkWeightOutSpeed=30,this.footIkMaxSlopeAngleDeg=40,this.footIkForwardSampleDistance=.14,this.footIkSideSampleDistance=.08,this.footIkMaxHorizontalOffset=.22,this.footIkMaxVerticalOffsetDown=.75,this.footIkMaxVerticalOffsetUp=.2,this.footIkPelvisEnabled=!0,this.footIkPelvisBone="mixamorigHips",this.footIkPelvisLerpSpeed=24,this.footIkPelvisMaxOffsetDown=.4,this.footIkPelvisMaxOffsetUp=.08,this.footIkRequireGrounded=!0,this.footIkSimpleTiltOnly=!1,this.footIkDebug=!1,this.footIkDebugNormalLength=.25,this.footIkDebugAxisLength=.2,this.footIkExtraClearance=.01,this.footIkPlantReleaseUpSpeed=.08,this.footIkPlantReleaseExtension=.9,this.footIkPlantAttachExtension=.96,this.footIkPlantReleaseLift=.055,this.footIkPlantAttachLift=.02,this.leftLegIkBones={upperLeg:"mixamorigLeftUpLeg",lowerLeg:"mixamorigLeftLeg",foot:"mixamorigLeftFoot"},this.rightLegIkBones={upperLeg:"mixamorigRightUpLeg",lowerLeg:"mixamorigRightLeg",foot:"mixamorigRightFoot"},this.ikPelvisOffsetY=0,this.ikLegState={left:{targetPosition:new p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1},right:{targetPosition:new p,normal:new p(0,1,0),forward:new p(0,0,1),pitch:0,contactOffset:0,planted:!0,lastFootWorldPos:new p,hasLastFootSample:!1,weight:0,top:!1}},this.ikWarnedMissingBones=!1,this.raycaster=new c,this.raycastIntersections=[],this.footIkRayTo=new p,this.footIkRayTestResult=new v,this.footIkRayTestOptions={excludeTriggers:!0,resolveActor:!1,collisionFilter:-2},this.footIkHits={center:U(),toe:U(),heel:U(),side:U()},this.footIkAxesScratch={up:new p,forward:new p,right:new p},this.footIkSampleAxesScratch={forward:new p,right:new p},this.footIkScratch={footWorldPos:new p,centerRayStart:new p,toeRayStart:new p,heelRayStart:new p,sideRayStart:new p,desiredTargetPos:new p,desiredNormal:new p,desiredForward:new p,debugRayEndA:new p,debugRayEndB:new p,debugRayEndC:new p,debugRayEndD:new p,debugRayEndE:new p,debugRayEndF:new p},this.ikPreSolve={left:{upper:new f,lower:new f,foot:new f},right:{upper:new f,lower:new f,foot:new f}},this.getFullBodyClip=X(t=>t.uuid,t=>Y(this.fullBodyMask,t)),this.getUpperBodyClip=X(t=>t.uuid,t=>Y(this.upperBodyMask,t))}onInit(){this.viewController.onUpdate(this.actor).subscribe(t=>this.updateInternal(t)),this.characterMovement=this.actor.getComponent(S),this.footIkRayTestOptions.excludeActor=this.actor}onEndPlay(){this.disposeFootIkDebug()}raycastDownFirstValid(t,e,o){const i=this.world.scene;this.raycaster.set(t,I),this.raycaster.near=0,this.raycaster.far=e,this.raycastIntersections.length=0,this.raycaster.intersectObject(i,!0,this.raycastIntersections);for(const t of this.raycastIntersections)if(!(this.isFootIkDebugObject(t.object)||this.isRelatedToActorHierarchy(t.object)||this.isSkinnedMeshObject(t.object)))return o.point.copy(t.point),null!=t.face?(o.normal.copy(t.face.normal).transformDirection(t.object.matrixWorld).normalize(),o.hasNormal=!0):o.hasNormal=!1,this.raycastIntersections.length=0,!0;return this.raycastIntersections.length=0,!1}rayTestDown(t,e,o){const i=this.footIkRayTo.copy(t).addScaledVector(I,e),s=this.physicsSystem.rayTest(t,i,this.footIkRayTestResult,this.footIkRayTestOptions);return!!s.hasHit&&(o.point.copy(s.hitPoint),o.normal.copy(s.hitNormal),o.normal.lengthSq()>1e-8?(o.normal.normalize(),o.hasNormal=!0):o.hasNormal=!1,!0)}isRelatedToActorHierarchy(t){const e=this.actor?.object;return null!=e&&null!=t&&(tt(t,e)||tt(e,t))}isFootIkDebugObject(t){let e=t;for(;null!=e;){if(!0===e.userData?.footIkDebug)return!0;e=e.parent}return!1}isSkinnedMeshObject(t){let e=t;for(;null!=e;){if(e instanceof d||!0===e.isSkinnedMesh)return!0;e=e.parent}return!1}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof i)return this.fullBodyAction}getFullBodyAction(){return this.fullBodyAction}setup(t,e,o){null!=e&&(this.upperBodyMask=$(e),this.fullBodyMask=function(t,e){const o=new Set($(e).map(t=>t.uuid)),i=[];return t.traverse(t=>{(t instanceof l||t.isBone)&&!o.has(t.uuid)&&i.push(t)}),i}(Z(t),e)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t),this.ikRoot=t,this.disposeFootIkDebug(),this.initializeFootIk(t,o),this.syncFootIkDebug()}updateStateMachines(t){this.stateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o&&this.play(o,{priority:e.current.options.priority??0,loop:e.current.options.loop??!0})}),this.upperStateMachines.forEach(e=>{e.step(t);const o=e.current.clip;null!=o?this.playUpper(o,{priority:e.current.options.priority??0,loop:e.current.options.loop??!0}):this.play(this.fullBodyClip)})}addPoseProcessor(t){const e={id:t.id,phase:t.phase??"afterMixer",order:t.order??0,update:t.update};this.removePoseProcessor(e.id);const o=this.poseProcessors.get(e.phase);let i=o.findIndex(t=>t.order>e.order);return-1===i&&(i=o.length),o.splice(i,0,e),()=>{const t=o.indexOf(e);-1!==t&&(o.splice(t,1),0===o.length&&this.poseProcessors.delete(e.phase))}}removePoseProcessor(t){for(const[e,o]of this.poseProcessors.entries()){const i=o.findIndex(e=>e.id===t);if(-1!==i)return o.splice(i,1),void(0===o.length&&this.poseProcessors.delete(e))}}runPoseProcessors(t,e){if(0===this.poseProcessors.size||null==this.mixer||!this.poseProcessors.present(t))return;const o=this.mixer.getRoot();if(!(o instanceof a))return;const i=this.poseProcessorContext??(this.poseProcessorContext={deltaTime:e,phase:t,animation:this,mixer:this.mixer,root:o});i.deltaTime=e,i.phase=t,i.mixer=this.mixer,i.root=o;const s=this.poseProcessors.get(t);for(let t=0;t<s.length;t++)s[t].update(i)}updateInternal(t){null!=this.mixer&&(this.externalControlActive||(this.upperBodyTimer+=t*(this.upperBodyAction?.timeScale??1),this.fullBodyTimer+=t*(this.fullBodyAction?.timeScale??1),this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*(this.overrideFadeTimeUpper??this.fadeTime)<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip)),this.upperBodyAction=null,this.overrideFadeTimeUpper=null),this.fullBodyAction&&this.fullBodyAction.loop===h&&this.fullBodyAction.getClip().duration-2*(this.overrideFadeTime??this.fadeTime)<this.fullBodyTimer&&(this.currentFullBodyPriority=-1,this.overrideFadeTime=null),null!=this.characterMovement&&(this.movementSpeed=this.characterMovement.horizontalSpeed),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.runPoseProcessors("beforeMixer",t),this.mixer.update(t),this.runPoseProcessors("afterMixer",t),this.runPoseProcessors("beforeIk",t),this.updateFootIk(t),this.runPoseProcessors("afterIk",t)))}initializeFootIk(t,e){if(this.ikSolver=null,this.ikSkinnedMesh=null,this.ikBoneRefs=null,this.ikLegLengths=null,this.ikPelvisBone=null,this.ikPelvisOffsetY=0,this.ikFootAxes=null,this.ikTargetBones=null,this.ikWarnedMissingBones=!1,this.ikLegState.left.weight=0,this.ikLegState.right.weight=0,!this.footIkEnabled)return;const o=this.findFirstSkinnedMesh(t);if(null==o||null==o.skeleton)return;this.ikSkinnedMesh=o,t.updateWorldMatrix(!0,!0);const i=o.skeleton,s=this.resolveLegBoneRefs(i,this.leftLegIkBones,Q),r=this.resolveLegBoneRefs(i,this.rightLegIkBones,G);if(null==s||null==r)return void(this.ikWarnedMissingBones||(this.ikWarnedMissingBones=!0,console.warn(`[CharacterAnimationComponent] Foot IK disabled: missing leg bones. Left=${this.leftLegIkBones.upperLeg}/${this.leftLegIkBones.lowerLeg}/${this.leftLegIkBones.foot}, Right=${this.rightLegIkBones.upperLeg}/${this.rightLegIkBones.lowerLeg}/${this.rightLegIkBones.foot}`)));this.ikBoneRefs={left:s,right:r},this.ikLegLengths={left:this.computeLegLengths(s),right:this.computeLegLengths(r)},this.ikFootAxes={left:this.detectFootAxisBasis(s.foot),right:this.detectFootAxisBasis(r.foot)},this.ikPelvisBone=this.resolvePelvisBone(i,s,r),this.ikLegState.left.targetPosition.copy(s.foot.getWorldPosition(D)),this.ikLegState.right.targetPosition.copy(r.foot.getWorldPosition(D)),this.ikLegState.left.normal.set(0,1,0),this.ikLegState.right.normal.set(0,1,0),this.ikLegState.left.pitch=0,this.ikLegState.right.pitch=0,this.ikLegState.left.contactOffset=this.estimateFootContactOffset(i,"left",s.foot),this.ikLegState.right.contactOffset=this.estimateFootContactOffset(i,"right",r.foot),this.ikLegState.left.planted=!0,this.ikLegState.right.planted=!0,this.ikLegState.left.lastFootWorldPos.copy(s.foot.getWorldPosition(D)),this.ikLegState.right.lastFootWorldPos.copy(r.foot.getWorldPosition(D)),this.ikLegState.left.hasLastFootSample=!0,this.ikLegState.right.hasLastFootSample=!0;const n=this.resolveFootAxes("left",s.foot),a=this.resolveFootAxes("right",r.foot);this.ikLegState.left.forward.copy(n.forward),this.ikLegState.right.forward.copy(a.forward);const h=e??Z(t);if(null==h)return;let c=i.getBoneByName("_IKTargetLeftFoot"),p=i.getBoneByName("_IKTargetRightFoot"),d=!1;if(null==c&&(c=new l,c.name="_IKTargetLeftFoot",h.add(c),d=!0),null==p&&(p=new l,p.name="_IKTargetRightFoot",h.add(p),d=!0),this.setBoneWorldPosition(c,s.foot.getWorldPosition(D)),this.setBoneWorldPosition(p,r.foot.getWorldPosition(D)),d||i.bones.indexOf(c)<0||i.bones.indexOf(p)<0){const t=i.bones.slice(),e=i.boneInverses.map(t=>t.clone());t.indexOf(c)<0&&(t.push(c),e.push((new g).copy(c.matrixWorld).invert())),t.indexOf(p)<0&&(t.push(p),e.push((new g).copy(p.matrixWorld).invert())),o.bind(new u(t,e),o.bindMatrix)}this.ikTargetBones={left:c,right:p};const f=o.skeleton.bones,y={target:f.indexOf(c),effector:f.indexOf(s.foot),links:[{index:f.indexOf(s.lower)},{index:f.indexOf(s.upper)}],iteration:8},m={target:f.indexOf(p),effector:f.indexOf(r.foot),links:[{index:f.indexOf(r.lower)},{index:f.indexOf(r.upper)}],iteration:8};if(y.target<0||y.effector<0||y.links.some(t=>t.index<0)||m.target<0||m.effector<0||m.links.some(t=>t.index<0))return console.warn("[CharacterAnimationComponent] Foot IK disabled: failed to resolve IK indexes in skeleton."),void(this.ikSolver=null);this.ikSolver=new w(o,[y,m])}findFirstSkinnedMesh(t){let e;return t.traverse(t=>{null==e&&(t instanceof d||!0===t.isSkinnedMesh)&&(e=t)}),e}resolveLegBoneRefs(t,e,o){const i=this.findBoneByNames(t,[e.upperLeg,...o.upper]),s=this.findBoneByNames(t,[e.lowerLeg,...o.lower]),r=this.findBoneByNames(t,[e.foot,...o.foot]);if(null!=i&&null!=s&&null!=r)return{upper:i,lower:s,foot:r}}findBoneByNames(t,e){for(const o of e){const e=t.getBoneByName(o);if(null!=e)return e}}resolvePelvisBone(t,e,o){const i=this.findBoneByNames(t,[this.footIkPelvisBone,...j]);if(null!=i)return i;const s=e.upper.parent,r=o.upper.parent;return null!=s&&s===r&&(s instanceof l||!0===s.isBone)||null!=s&&(s instanceof l||!0===s.isBone)?s:void 0}computeLegLengths(t){const e=t.upper.getWorldPosition(D),o=t.lower.getWorldPosition(R),i=t.foot.getWorldPosition(A),s=e.distanceTo(o),r=o.distanceTo(i);return{upper:s,lower:r,total:s+r}}setBoneWorldPosition(t,e){const o=t.parent;null==o?t.position.copy(e):t.position.copy(o.worldToLocal(D.copy(e))),t.quaternion.copy(F),t.scale.copy(x),t.updateMatrixWorld(!0)}syncFootIkDebug(){this.footIkDebug&&null!=this.ikRoot?(null!=this.ikDebugRoot&&null!=this.ikDebugLegs||(this.ikDebugRoot=new k,this.ikDebugRoot.name="FootIKDebug",this.ikDebugRoot.userData.footIkDebug=!0,this.ikDebugLegs={left:this.createDebugLeg("LeftFootIK",53503),right:this.createDebugLeg("RightFootIK",16755200)},this.ikDebugRoot.add(this.ikDebugLegs.left.root,this.ikDebugLegs.right.root),this.world.scene.add(this.ikDebugRoot)),this.ikDebugRoot.visible=!0):null!=this.ikDebugRoot&&(this.ikDebugRoot.visible=!1)}disposeFootIkDebug(){null!=this.ikDebugRoot&&(this.ikDebugRoot.removeFromParent(),this.ikDebugRoot.clear()),this.ikDebugRoot=null,this.ikDebugLegs=null}createDebugLeg(t,e){const o=new k;o.name=t,o.userData.footIkDebug=!0;const i=this.createDebugArrow(e),s=this.createDebugArrow(e),r=this.createDebugArrow(e),n=this.createDebugArrow(e),l=this.createDebugArrow(65280),a=this.createDebugArrow(6750054),h=this.createDebugArrow(16711935),c=this.createDebugArrow(16776960),p=this.createDebugArrow(16737792);return o.add(i,s,r,n,l,a,h,c,p),{root:o,rayCenter:i,rayToe:s,rayHeel:r,raySide:n,hitNormal:l,footUp:a,footToTarget:h,solveUpper:c,solveLower:p}}createDebugArrow(t){const e=new m(P,new p,.001,t);return e.userData.footIkDebug=!0,e.traverse(t=>{t.userData.footIkDebug=!0,t.raycast=()=>{}}),e.visible=!1,e}setDebugArrow(t,e,o){D.subVectors(o,e);const i=D.length();i<1e-6?t.visible=!1:(t.visible=!0,t.position.copy(e),t.setDirection(D.multiplyScalar(1/i)),t.setLength(i,Math.min(.08,.25*i),Math.min(.05,.2*i)))}resetDebugVisibility(){null!=this.ikDebugLegs&&(this.ikDebugLegs.left.rayCenter.visible=!1,this.ikDebugLegs.left.rayToe.visible=!1,this.ikDebugLegs.left.rayHeel.visible=!1,this.ikDebugLegs.left.raySide.visible=!1,this.ikDebugLegs.left.hitNormal.visible=!1,this.ikDebugLegs.left.footUp.visible=!1,this.ikDebugLegs.left.footToTarget.visible=!1,this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.rayCenter.visible=!1,this.ikDebugLegs.right.rayToe.visible=!1,this.ikDebugLegs.right.rayHeel.visible=!1,this.ikDebugLegs.right.raySide.visible=!1,this.ikDebugLegs.right.hitNormal.visible=!1,this.ikDebugLegs.right.footUp.visible=!1,this.ikDebugLegs.right.footToTarget.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1)}updateFootIk(t){if(this.syncFootIkDebug(),!this.footIkEnabled||null==this.ikBoneRefs||null==this.ikRoot)return void this.resetDebugVisibility();if(!this.footIkMoving&&(this.movementSpeed??0)>.01)return this.resetFootIkState(),void this.resetDebugVisibility();this.ikRoot.updateWorldMatrix(!0,!0);const e=this.characterMovement?.isGrounded??!0;return this.footIkSimpleTiltOnly?(this.updatePelvisOffset(t,!1),this.updateLegTiltSimple("left",this.ikBoneRefs.left.foot,this.ikLegState.left,e,t),void this.updateLegTiltSimple("right",this.ikBoneRefs.right.foot,this.ikLegState.right,e,t)):null==this.ikLegLengths||null==this.ikTargetBones||null==this.ikSkinnedMesh||null==this.ikSolver?(this.updatePelvisOffset(t,!1),void this.resetDebugVisibility()):(this.updateLegIkTarget("left",this.ikBoneRefs.left,this.ikLegLengths.left,this.ikTargetBones.left,this.ikLegState.left,e,t),this.updateLegIkTarget("right",this.ikBoneRefs.right,this.ikLegLengths.right,this.ikTargetBones.right,this.ikLegState.right,e,t),this.updatePelvisOffset(t,!0),this.setBoneWorldPosition(this.ikTargetBones.left,this.ikLegState.left.targetPosition),this.setBoneWorldPosition(this.ikTargetBones.right,this.ikLegState.right.targetPosition),this.ikPreSolve.left.upper.copy(this.ikBoneRefs.left.upper.quaternion),this.ikPreSolve.left.lower.copy(this.ikBoneRefs.left.lower.quaternion),this.ikPreSolve.left.foot.copy(this.ikBoneRefs.left.foot.quaternion),this.ikPreSolve.right.upper.copy(this.ikBoneRefs.right.upper.quaternion),this.ikPreSolve.right.lower.copy(this.ikBoneRefs.right.lower.quaternion),this.ikPreSolve.right.foot.copy(this.ikBoneRefs.right.foot.quaternion),null!=this.ikDebugLegs&&(this.ikDebugLegs.left.solveUpper.visible=!1,this.ikDebugLegs.left.solveLower.visible=!1,this.ikDebugLegs.right.solveUpper.visible=!1,this.ikDebugLegs.right.solveLower.visible=!1),this.ikSolver.update(),this.blendLegAfterSolve(this.ikBoneRefs.left,this.ikPreSolve.left,this.ikLegState.left.weight),this.blendLegAfterSolve(this.ikBoneRefs.right,this.ikPreSolve.right,this.ikLegState.right.weight),this.applySimpleFootPitch("left",this.ikBoneRefs.left.foot,this.ikLegState.left),void this.applySimpleFootPitch("right",this.ikBoneRefs.right.foot,this.ikLegState.right))}resetFootIkState(){if(null!=this.ikBoneRefs){for(const t of _){const e=this.ikBoneRefs[t],o=this.ikLegState[t],i=e.foot.getWorldPosition(D);o.targetPosition.copy(i),o.lastFootWorldPos.copy(i),o.hasLastFootSample=!0,o.weight=0,o.normal.set(0,1,0);const s=this.resolveFootAxes(t,e.foot,this.footIkAxesScratch);o.forward.copy(s.forward),o.pitch=0,this.footIkAutoContactOffset?o.contactOffset=Math.max(o.contactOffset,this.footIkFootOffset+this.footIkExtraClearance):o.contactOffset=this.footIkFootOffset+this.footIkExtraClearance,o.planted=!1}this.ikPelvisOffsetY=0}}updatePelvisOffset(t,e){if(null==this.ikPelvisBone)return;let o=0;if(e&&this.footIkPelvisEnabled&&null!=this.ikBoneRefs&&null!=this.ikLegLengths){this.ikLegState.left.top=!1,this.ikLegState.right.top=!1;for(const t of _){const e=this.ikBoneRefs[t],i=this.ikLegLengths[t],s=this.ikLegState[t];if(!s.planted)continue;const r=e.upper.getWorldPosition(D),n=.998*i.total,l=this.computeRequiredPelvisDrop(r,s.targetPosition,n);if(l>0){const e="left"===t?"right":"left";this.ikLegState[e].top=!0}o=Math.min(o,-l)}o=y.clamp(o,-this.footIkPelvisMaxOffsetDown,this.footIkPelvisMaxOffsetUp)}const i=1-Math.exp(-this.footIkPelvisLerpSpeed*t);this.ikPelvisOffsetY=y.lerp(this.ikPelvisOffsetY,o,i);const s=this.ikPelvisBone.getWorldPosition(R),r=A.copy(s).addScaledVector(P,this.ikPelvisOffsetY);null==this.ikPelvisBone.parent?this.ikPelvisBone.position.copy(r):this.ikPelvisBone.position.copy(this.ikPelvisBone.parent.worldToLocal(r)),this.ikPelvisBone.updateMatrixWorld(!0)}computeFootVerticalSpeed(t,e,o){return!t.hasLastFootSample||o<=1e-6?0:(e.y-t.lastFootWorldPos.y)/o}updateFootSample(t,e){t.lastFootWorldPos.copy(e),t.hasLastFootSample=!0}estimateFootContactOffset(t,e,o){const i=this.footIkFootOffset+this.footIkExtraClearance;if(!this.footIkAutoContactOffset)return i;const s=t.bones.indexOf(o);if(s<0)return i;const r=t.boneInverses[s];if(null==r)return i;const n=this.ikFootAxes?.[e]??this.detectFootAxisBasis(o),a=o.getWorldPosition(R),h=A.copy(n.upLocal).applyQuaternion(o.getWorldQuaternion(W)).normalize();let c=0;return o.traverse(e=>{if(!(e instanceof l)||e===o)return;const i=t.bones.indexOf(e);if(i<0)return;const s=E.copy(t.boneInverses[i]).invert(),n=q.copy(r).multiply(s),p=D.setFromMatrixPosition(n),d=M.copy(p).applyMatrix4(o.matrixWorld).sub(a);c=Math.min(c,d.dot(h))}),Math.max(i,-c+this.footIkExtraClearance)}shouldPlantFoot(t,e,o,i,s,r){if(!e||!o)return!1;const n=this.footIkPlantReleaseExtension,l=this.footIkPlantAttachExtension,a=this.footIkPlantReleaseLift,h=this.footIkPlantAttachLift;return t.planted?!(i>this.footIkPlantReleaseUpSpeed&&(s<n||r>a)):s>=l&&r<=h||i<=0&&s>=n}computeLegExtensionRatio(t,e){const o=t.upper.getWorldPosition(D),i=t.foot.getWorldPosition(R),s=o.distanceTo(i);return e.total<=1e-6?1:y.clamp(s/e.total,0,1.2)}computeRequiredPelvisDrop(t,e,o){const i=M.subVectors(t,e),s=i.length();if(s<=o+1e-6)return 0;const r=i.dot(P),n=o*o-Math.max(s*s-r*r,0);if(n<=0)return s-o;const l=Math.sqrt(n),a=r-l,h=r+l;return a>=0?a:h>=0?h:0}updateLegTiltSimple(t,e,o,i,s){const r=this.footIkScratch,n=this.footIkHits,l=e.getWorldPosition(r.footWorldPos),a=this.computeFootVerticalSpeed(o,l,s),h=this.resolveFootAxes(t,e,this.footIkAxesScratch),c=this.resolveGroundSampleAxes(t,e,h,this.footIkSampleAxesScratch),p=r.centerRayStart.copy(l).addScaledVector(P,this.footIkRayStartHeight),d=r.toeRayStart.copy(p).addScaledVector(c.forward,this.footIkForwardSampleDistance),u=r.heelRayStart.copy(p).addScaledVector(c.forward,-this.footIkForwardSampleDistance),f=r.sideRayStart.copy(p).addScaledVector(c.right,this.footIkSideSampleDistance),g=this.getFirstGroundHit(p,n.center),m=this.getFirstGroundHit(d,n.toe),k=this.getFirstGroundHit(u,n.heel),S=this.getFirstGroundHit(f,n.side),w=r.desiredNormal.set(0,1,0),b=r.desiredForward.copy(c.forward);let L=0,v=0,B=this.footIkWeightOutSpeed;const I=null!=g||null!=m||null!=k;let x=l.y;null!=g?x=g.point.y:null!=m&&null!=k?x=.5*(m.point.y+k.point.y):null!=m?x=m.point.y:null!=k&&(x=k.point.y);const F=this.ikBoneRefs?.[t],D=this.ikLegLengths?.[t],R=null!=F&&null!=D?this.computeLegExtensionRatio(F,D):1,A=Math.max(0,l.y-x,l.y-o.targetPosition.y),M=this.shouldPlantFoot(o,!this.footIkRequireGrounded||i,I,a,R,A);M?this.computeDesiredGroundNormal(c,g,m,k,S,w)&&(this.computeDesiredFootForward(c.forward,c.right,w,m,k,b),L=this.computeDesiredPitchAngle(m,k,c.forward),v=1,B=this.footIkWeightInSpeed):this.computeDesiredFootForward(c.forward,c.right,w,null,null,b);const T=1-Math.exp(-this.footIkPositionLerpSpeed*s),W=1-Math.exp(-B*s);o.normal.lerp(w,T).normalize(),o.forward.lerp(b,T).normalize(),o.pitch=y.lerp(o.pitch,L,T),o.weight=y.lerp(o.weight,v,W),o.planted=M&&v>.001,this.updateFootSample(o,l),this.applySimpleFootPitch(t,e,o),this.updateLegDebug(t,{footWorldPos:l,centerRayStart:p,toeRayStart:d,heelRayStart:u,sideRayStart:f,centerHit:g,toeHit:m,heelHit:k,sideHit:S,desiredNormal:o.normal,desiredTargetPos:r.footWorldPos,weight:o.weight})}updateLegIkTarget(t,e,o,i,s,r,n){const l=this.footIkScratch,a=this.footIkHits,h=e.foot,c=h.getWorldPosition(l.footWorldPos),p=this.computeFootVerticalSpeed(s,c,n),d=this.resolveFootAxes(t,h,this.footIkAxesScratch),u=this.resolveGroundSampleAxes(t,h,d,this.footIkSampleAxesScratch),f=l.centerRayStart.copy(c).addScaledVector(P,this.footIkRayStartHeight),g=l.toeRayStart.copy(f).addScaledVector(u.forward,this.footIkForwardSampleDistance),m=l.heelRayStart.copy(f).addScaledVector(u.forward,-this.footIkForwardSampleDistance),k=l.sideRayStart.copy(f).addScaledVector(u.right,this.footIkSideSampleDistance),S=this.getFirstGroundHit(f,a.center),w=this.getFirstGroundHit(g,a.toe),b=this.getFirstGroundHit(m,a.heel),L=this.getFirstGroundHit(k,a.side),v=l.desiredTargetPos.copy(c),B=l.desiredNormal.set(0,1,0),I=l.desiredForward.copy(u.forward);let x=0,F=0,D=this.footIkWeightOutSpeed;const R=null!=S||null!=w||null!=b;let A=c.y;null!=S?A=S.point.y:null!=w&&null!=b?A=.5*(w.point.y+b.point.y):null!=w?A=w.point.y:null!=b&&(A=b.point.y);const M=this.computeLegExtensionRatio(e,o),T=Math.max(0,c.y-A,c.y-s.targetPosition.y),W=this.shouldPlantFoot(s,!this.footIkRequireGrounded||r,R,p,M,T);if(W){if(v.copy(c),this.computeDesiredGroundNormal(u,S,w,b,L,B)){this.computeDesiredFootForward(u.forward,u.right,B,w,b,I),x=this.computeDesiredPitchAngle(w,b,u.forward);const t=Math.max(0,Math.sin(x))*this.footIkForwardSampleDistance*.45,e=Math.max(this.footIkFootOffset+this.footIkExtraClearance,s.contactOffset);v.y=A+e+t,s.top&&(v.y-=this.ikPelvisOffsetY/2),F=1,D=this.footIkWeightInSpeed}}else this.computeDesiredFootForward(u.forward,u.right,B,null,null,I),v.copy(c),v.y+=this.footIkFootOffset;this.clampDesiredFootTarget(e,o,c,v);const O=1-Math.exp(-this.footIkPositionLerpSpeed*n),V=1-Math.exp(-D*n);s.targetPosition.lerp(v,O),s.normal.lerp(B,O).normalize(),s.forward.lerp(I,O).normalize(),s.pitch=y.lerp(s.pitch,x,O),s.weight=y.lerp(s.weight,F,V),s.planted=W&&F>.001,this.updateFootSample(s,c),this.setBoneWorldPosition(i,s.targetPosition),this.updateLegDebug(t,{footWorldPos:c,centerRayStart:f,toeRayStart:g,heelRayStart:m,sideRayStart:k,centerHit:S,toeHit:w,heelHit:b,sideHit:L,desiredNormal:B,desiredTargetPos:s.targetPosition,weight:s.weight})}updateLegDebug(t,e){if(!this.footIkDebug||null==this.ikDebugLegs||null==this.ikBoneRefs)return;const o=this.ikDebugLegs[t],i=this.ikBoneRefs[t],s=this.resolveFootAxes(t,i.foot,this.footIkAxesScratch),r=this.footIkScratch,n=e.centerHit?.point??r.debugRayEndA.copy(e.centerRayStart).addScaledVector(I,this.footIkRayLength),l=e.toeHit?.point??r.debugRayEndB.copy(e.toeRayStart).addScaledVector(I,this.footIkRayLength),a=e.heelHit?.point??r.debugRayEndC.copy(e.heelRayStart).addScaledVector(I,this.footIkRayLength),h=e.sideHit?.point??r.debugRayEndD.copy(e.sideRayStart).addScaledVector(I,this.footIkRayLength);this.setDebugArrow(o.rayCenter,e.centerRayStart,n),this.setDebugArrow(o.rayToe,e.toeRayStart,l),this.setDebugArrow(o.rayHeel,e.heelRayStart,a),this.setDebugArrow(o.raySide,e.sideRayStart,h);const c=e.centerHit?.point??e.toeHit?.point??e.heelHit?.point??e.sideHit?.point??e.footWorldPos;this.setDebugArrow(o.hitNormal,c,r.debugRayEndE.copy(c).addScaledVector(e.desiredNormal,this.footIkDebugNormalLength)),this.setDebugArrow(o.footUp,e.footWorldPos,r.debugRayEndF.copy(e.footWorldPos).addScaledVector(s.up,this.footIkDebugAxisLength*(.15+e.weight))),this.setDebugArrow(o.footToTarget,e.footWorldPos,e.desiredTargetPos)}getFirstGroundHit(t,e){return"physics"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)?e:null:"physicsThenRender"===this.footIkRaycastMode?this.rayTestDown(t,this.footIkRayLength,e)||this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null:this.raycastDownFirstValid(t,this.footIkRayLength,e)?e:null}resolveGroundSampleAxes(t,e,o,i){const s=o??this.resolveFootAxes(t,e),r=i??{forward:new p,right:new p},n=this.actor.object.getWorldDirection(M);n.addScaledVector(P,-n.dot(P)),n.lengthSq()<1e-8&&n.copy(s.forward).addScaledVector(P,-s.forward.dot(P)),n.lengthSq()<1e-8&&n.set(0,0,1),n.normalize();const l=T.crossVectors(P,n);return l.lengthSq()<1e-8?l.copy(s.right):l.normalize(),l.dot(s.right)<0&&l.multiplyScalar(-1),r.forward.copy(n),r.right.copy(l),r}computeDesiredGroundNormal(t,e,o,i,s,r){const n=this.computeAverageHitNormal(e,o,i,s,M);let l=!1,a=0,h=0;if(null!=o&&null!=i){const e=R.subVectors(o.point,i.point).dot(t.forward);Math.abs(e)>1e-5&&(a=(o.point.y-i.point.y)/e,l=!0)}if(null!=s&&null!=e){const o=A.subVectors(s.point,e.point).dot(t.right);Math.abs(o)>1e-5&&(h=(s.point.y-e.point.y)/o,l=!0)}if(l&&(r.copy(P),r.addScaledVector(t.forward,-a),r.addScaledVector(t.right,-h),r.lengthSq()>1e-8?r.normalize():l=!1),l)null!=n&&r.dot(n)<0&&r.multiplyScalar(-1);else{if(null==n)return!1;r.copy(n),l=!0}return r.dot(P)<0&&r.multiplyScalar(-1),this.clampSlopeNormal(r),!0}computeAverageHitNormal(t,e,o,i,s){s.set(0,0,0);let r=0;return null!=t&&t.hasNormal&&(s.add(t.normal),r++),null!=e&&e.hasNormal&&(s.add(e.normal),r++),null!=o&&o.hasNormal&&(s.add(o.normal),r++),null!=i&&i.hasNormal&&(s.add(i.normal),r++),0===r||s.lengthSq()<1e-8?null:(s.multiplyScalar(1/r).normalize(),s)}computeDesiredFootForward(t,e,o,i,s,r){null!=i&&null!=s?r.subVectors(i.point,s.point):r.copy(t),r.addScaledVector(o,-r.dot(o)),r.lengthSq()<1e-8&&(r.copy(this.actor.object.getWorldDirection(M)),r.addScaledVector(o,-r.dot(o))),r.lengthSq()<1e-8&&r.crossVectors(o,e),r.lengthSq()<1e-8&&r.set(0,0,1),r.normalize();const n=M.copy(this.actor.object.getWorldDirection(M));n.addScaledVector(o,-n.dot(o)),n.lengthSq()<1e-8&&(n.copy(t),n.addScaledVector(o,-n.dot(o))),n.lengthSq()>1e-8&&n.normalize(),r.dot(n)<0&&r.multiplyScalar(-1)}computeDesiredPitchAngle(t,e,o){if(null==t||null==e)return 0;const i=R.subVectors(t.point,e.point),s=Math.abs(i.dot(o));if(s<1e-5)return 0;const r=t.point.y-e.point.y,n=y.degToRad(this.footIkMaxSlopeAngleDeg);return y.clamp(-Math.atan2(r,s),-n,n)}applySimpleFootPitch(t,e,o){if(null==e.parent||o.weight<=.001)return;const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o.pitch*o.weight;if(Math.abs(s)<=1e-5)return;const r=this.resolveLocalPitchSign(i),n=W.copy(e.quaternion),l=O.setFromAxisAngle(i.rightLocal,s*r);e.quaternion.copy(n.multiply(l))}resolveLocalPitchSign(t){const e=V.setFromAxisAngle(t.rightLocal,.15);return A.copy(t.upLocal).applyQuaternion(e).sub(t.upLocal).dot(t.forwardLocal)>=0?1:-1}clampDesiredFootTarget(t,e,o,i){const s=R.subVectors(i,o),r=s.dot(P),n=A.copy(s).addScaledVector(P,-r),l=n.length();l>this.footIkMaxHorizontalOffset&&l>1e-6&&n.multiplyScalar(this.footIkMaxHorizontalOffset/l);const a=y.clamp(r,-this.footIkMaxVerticalOffsetDown,this.footIkMaxVerticalOffsetUp);if(i.copy(o),i.add(n),i.addScaledVector(P,a),this.footIkPelvisEnabled)return;const h=t.upper.getWorldPosition(D).clone(),c=R.subVectors(i,h),p=c.length(),d=.995*e.total;p>d&&p>1e-6&&i.copy(h).addScaledVector(c,d/p)}solveTwoBoneLeg(t,e,o){const i=e.upper.getWorldPosition(D).clone(),s=e.lower.getWorldPosition(R).clone(),r=e.foot.getWorldPosition(A).clone(),n=i.distanceTo(s),l=s.distanceTo(r);if(n<1e-5||l<1e-5)return;const a=(new p).subVectors(o,i),h=a.length();if(h<1e-5)return;const c=Math.abs(n-l)+1e-4,d=n+l-1e-4,u=y.clamp(h,c,d),f=a.multiplyScalar(1/h),g=(new p).subVectors(s,i).normalize(),m=(new p).subVectors(r,s).normalize(),k=(new p).crossVectors(g,m);k.lengthSq()<1e-8&&(k.copy(this.actor.object.getWorldDirection(D).cross(P)),k.lengthSq()<1e-8&&k.set(1,0,0)),k.normalize();const S=(u*u+n*n-l*l)/(2*u),w=Math.max(n*n-S*S,0),b=Math.sqrt(w),L=(new p).copy(i).addScaledVector(f,S);let v=(new p).crossVectors(k,f);v.lengthSq()<1e-8&&(v=(new p).crossVectors(f,P),v.lengthSq()<1e-8&&(v=new p(1,0,0))),v.normalize();const B=(new p).copy(L).addScaledVector(v,b),I=(new p).copy(L).addScaledVector(v,-b),x=(new p).subVectors(s,L).dot(v)>=0?B:I;this.rotateBoneToward(e.upper,i,s,x),e.upper.updateMatrixWorld(!0);const F=e.lower.getWorldPosition(R),M=e.foot.getWorldPosition(A);this.rotateBoneToward(e.lower,F,M,o),e.lower.updateMatrixWorld(!0),this.updateSolveDebug(t,i,x,o)}updateSolveDebug(t,e,o,i){if(!this.footIkDebug||null==this.ikDebugLegs)return;const s=this.ikDebugLegs[t];this.setDebugArrow(s.solveUpper,e,o),this.setDebugArrow(s.solveLower,o,i)}rotateBoneToward(t,e,o,i){const s=(new p).subVectors(o,e),r=(new p).subVectors(i,e);if(s.lengthSq()<1e-10||r.lengthSq()<1e-10)return;if(s.normalize(),r.normalize(),s.dot(r)>.9999)return;const n=(new f).setFromUnitVectors(s,r),l=t.getWorldQuaternion(W),a=O.copy(n).multiply(l);if(null==t.parent)return void t.quaternion.copy(a);const h=t.parent.getWorldQuaternion(V),c=C.copy(h).invert().multiply(a);t.quaternion.copy(c)}detectFootAxisBasis(t){const e=t.getWorldQuaternion(W),o=this.actor.object.getWorldDirection(D);o.lengthSq()<1e-6&&o.set(0,0,1),o.normalize();const i=[{local:H.clone(),world:H.clone().applyQuaternion(e)},{local:z.clone(),world:z.clone().applyQuaternion(e)},{local:N.clone(),world:N.clone().applyQuaternion(e)}];i.push({local:H.clone().multiplyScalar(-1),world:H.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:z.clone().multiplyScalar(-1),world:z.clone().multiplyScalar(-1).applyQuaternion(e)}),i.push({local:N.clone().multiplyScalar(-1),world:N.clone().multiplyScalar(-1).applyQuaternion(e)});let s=i[0],r=-1/0;for(const t of i){const e=t.world.dot(P);e>r&&(r=e,s=t)}let n=i[0],l=-1/0;for(const t of i){if(Math.abs(t.world.dot(s.world))>.6)continue;const e=Math.abs(t.world.dot(o));e>l&&(l=e,n=t)}n.world.dot(o)<0&&(n={local:n.local.clone().multiplyScalar(-1),world:n.world.clone().multiplyScalar(-1)});const a=s.local.clone().normalize(),h=n.local.clone().normalize(),c=a.clone().cross(h).normalize();return{upLocal:a,forwardLocal:c.clone().cross(a).normalize(),rightLocal:c}}resolveFootAxes(t,e,o){const i=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),s=o??{up:new p,forward:new p,right:new p},r=e.getWorldQuaternion(W);return s.up.copy(i.upLocal).applyQuaternion(r).normalize(),s.forward.copy(i.forwardLocal).applyQuaternion(r).normalize(),s.right.copy(i.rightLocal).applyQuaternion(r).normalize(),s}clampSlopeNormal(t){const e=y.clamp(t.dot(P),-1,1),o=Math.acos(e),i=y.degToRad(this.footIkMaxSlopeAngleDeg);if(o<=i||o<1e-5)return;const s=i/o;t.lerpVectors(P,t,s).normalize()}blendLegAfterSolve(t,e,o){if(!(o>=.999)){if(o<=.001)return t.upper.quaternion.copy(e.upper),t.lower.quaternion.copy(e.lower),void t.foot.quaternion.copy(e.foot);this.blendBoneQuaternion(t.upper,e.upper,o),this.blendBoneQuaternion(t.lower,e.lower,o),this.blendBoneQuaternion(t.foot,e.foot,o)}}blendBoneQuaternion(t,e,o){W.copy(t.quaternion),t.quaternion.copy(e).slerp(W,o)}alignFootToGroundNormal(t,e,o,i){if(o.weight<=.001||null==e.parent)return;const s=this.ikFootAxes?.[t]??this.detectFootAxisBasis(e),r=D.copy(o.normal).normalize(),n=R.copy(o.forward);if(n.addScaledVector(r,-n.dot(r)),n.lengthSq()<1e-8){const o=this.resolveFootAxes(t,e);n.copy(o.forward).addScaledVector(r,-o.forward.dot(r))}if(n.lengthSq()<1e-8)return;n.normalize();const l=A.crossVectors(r,n);if(l.lengthSq()<1e-8)return;l.normalize(),n.copy(M.crossVectors(l,r)).normalize(),E.makeBasis(s.rightLocal,s.upLocal,s.forwardLocal),W.setFromRotationMatrix(E),q.makeBasis(l,r,n),O.setFromRotationMatrix(q);const a=V.copy(O).multiply(C.copy(W).invert()),h=e.parent.getWorldQuaternion(C),c=O.copy(h).invert().multiply(a),p=(1-Math.exp(-this.footIkRotationLerpSpeed*i))*o.weight;e.quaternion.slerp(c,y.clamp(p,0,1))}getMixer(){return this.mixer}beginExternalControl(){this.externalControlActive=!0}endExternalControl(){this.externalControlActive=!1}stopSequenceAnimation(){this.currentFullBodyPriority=-1,this.externalControlActive=!1,null==this.fullBodyAction||this.fullBodyAction.isRunning()||(this.fullBodyAction=null),null==this.upperBodyAction||this.upperBodyAction.isRunning()||(this.upperBodyAction=null),this.fullBodyTimer=0}cancelRootMotionAction(t){null!=t&&this.fullBodyAction!==t||(this.currentFullBodyPriority=-1,this.externalControlActive=!1,this.fullBodyAction?.stop(),this.fullBodyAction=null,this.fullBodyTimer=0)}beginExternalAnimationControl(t,e={}){J(null!=this.mixer,"Can't begin external control before setup is called"),this.mixer.stopAllAction(),this.currentFullBodyPriority=99,this.fullBodyTimer=0;const o=this.mixer.clipAction(t);return o.setLoop(h,1),o.clampWhenFinished=!0,o.timeScale=e.timeScale??1,o.reset(),o.play(),this.fullBodyAction=o,this.externalControlActive=!0,o}syncMovementSpeed(t){if(null!=t){const e=t.getClip();if(e instanceof i&&e.fixedInPlace&&null!=this.movementSpeed){t.timeScale=e.duration/e.displacement*this.movementSpeed;const o=this.mixer.getRoot();o instanceof a&&(t.timeScale/=o.scale.x)}}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const e=this.stateMachines.indexOf(t);e>=0&&this.stateMachines.splice(e,1)}removeUpperStateMachine(t){const e=this.upperStateMachines.indexOf(t);e>=0&&this.upperStateMachines.splice(e,1)}playUpper(t,e={}){const o=e?.priority??1;o<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=o,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1,this.upperBodyTimer=0,this.upperBodyOverride=!0,this.overrideFadeTimeUpper=e.fadeTime)}play(t,e={}){J(null!=this.mixer,"Can't play animation before setup is called");const o=e.priority??1;o<this.currentFullBodyPriority||(this.currentFullBodyPriority=o,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),e),this.upperBodyAction.timeScale=e?.timeScale??1),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),e),this.fullBodyAction.timeScale=e?.timeScale??1,this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction),this.overrideFadeTime=e.fadeTime)}onActionDone(t){return new Promise(e=>{const o=i=>{i.action===t&&(e(i.action),this.mixer.removeEventListener("finished",o))};this.mixer.addEventListener("finished",o)})}transition(t,e,o={}){const i=o?.fadeTime??this.fadeTime;if(null!=t&&t.getClip().uuid===e.uuid)return!t.isRunning()&&!1===o.loop&&t.clampWhenFinished||t.isRunning()||(t.reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play(),!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0)),t;if(t&&t.isRunning()){const s=t,r=this.mixer.clipAction(e);r.reset(),null!=o.offset&&(r.time=o.offset),r.play(),r.enabled=!0,r.setEffectiveTimeScale(1),r.weight=1,s.crossFadeTo(r,i,!0),t=r}else(t=this.mixer.clipAction(e)).reset(),null!=o.offset&&(t.time=o.offset),t.enabled=!0,t.weight=1,t.setEffectiveWeight(1),t.setEffectiveTimeScale(1),t.play();return!1===o.loop&&(t.setLoop(h,1),t.clampWhenFinished=!0),t}};K=t([o({inEditor:!0})],K);export{K as CharacterAnimationComponent};function Y(t,e){if(null==t)return e;const o=e.clone(),i=new Set(t.map(t=>t.name));return o.tracks=o.tracks.filter(t=>i.has(t.name.split(".")[0])),o}function $(t){return t.flatMap(t=>function(t){const e=[];return t.traverse(t=>{e.push(t)}),e}(t)).filter(t=>t instanceof l)}function J(t,e){if(!1===t||"function"==typeof t&&!1===t())throw new Error(e)}function X(t,e){const o=new Map;return(i,...s)=>{const r=t(i);return o.has(r)||o.set(r,e(i,...s)),o.get(r)}}function Z(t){let e;return t.traverse(t=>{(t instanceof l||t.isBone)&&null==e&&(e=t)}),e}function tt(t,e){let o=e;for(;null!=o;){if(o===t)return!0;o=o.parent}return!1}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -8,6 +8,7 @@ export declare class ActorFactory implements ActorProvider<BaseActor> {
|
|
|
8
8
|
private env;
|
|
9
9
|
classes: Record<string, Constructable<BaseActor>>;
|
|
10
10
|
constructor(container: ContainerInstance, env: EngineEnvironment);
|
|
11
|
+
get inEditor(): boolean;
|
|
11
12
|
create<T extends BaseActor>(type: Constructable<T>, position?: Vector3, rotation?: Euler, delayInit?: boolean): Promise<T>;
|
|
12
13
|
private _createActor;
|
|
13
14
|
initActor(actor: BaseActor): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t,__metadata as i}from"tslib";import{ContainerInstance as n}from"typedi";import{Service as
|
|
1
|
+
import{__decorate as t,__metadata as i}from"tslib";import{ContainerInstance as n}from"typedi";import{Service as r}from"typedi";import{initComponents as e,initComponentsSync as o}from"./internal/component-init.js";import{activeContainerInstance as s,containerRefMap as c}from"./internal/container-map.js";let a=class{constructor(t,i){this.container=t,this.env=i,this.classes={}}get inEditor(){return this.env.inEditor??!1}async create(t,i,n,r){const e=this._createActor(t,i,n);return!0!==r&&await this.initActor(e),e}createSync(t,i,n,r){const e=this._createActor(t,i,n);return!0!==r&&this.initActorSync(e),e}_createActor(t,i,n){const r=this.container;s.value=r;const e=(1e4*Math.random()).toString();r.set({id:e,type:t,transient:!0});const o=r.get(e);return s.value=null,r.remove(t),c.set(o,r),i&&o.object.position.copy(i),n&&o.object.rotation.copy(n),o}async initActor(t){await e(t,t,this.env.inEditor??!1),await t.onInit(),t.__isInitialised=!0}initActorSync(t){o(t,t,this.env.inEditor??!1),t.onInit(),t.__isInitialised=!0}};a=t([r(),i("design:paramtypes",[n,Object])],a);export{a as ActorFactory};/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -2,4 +2,5 @@ import { BaseActor } from '../actor.js';
|
|
|
2
2
|
import { ActorComponent } from '../component.js';
|
|
3
3
|
export declare function initComponents(a: BaseActor | ActorComponent, actor: BaseActor, inEditor?: boolean): Promise<any[]>;
|
|
4
4
|
export declare function initComponentsSync(a: BaseActor | ActorComponent, actor: BaseActor, inEditor?: boolean): void;
|
|
5
|
+
export declare function isComponentEnabledInEnvironment(component: ActorComponent, inEditor?: boolean): boolean;
|
|
5
6
|
//# sourceMappingURL=component-init.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{ActorComponent as n}from"../component.js";const o=new WeakMap;export async function initComponents(n,c,s=!1){const i=[];for(const
|
|
1
|
+
import{ActorComponent as n}from"../component.js";const o=new WeakMap;export async function initComponents(n,c,s=!1){const i=[];for(const e of t(n,c,s)){if(o.has(e))continue;o.set(e,!0);const n=(async()=>{await e.onInit(),await initComponents(e,c,s)})();i.push(n)}return Promise.all(i)}export function initComponentsSync(n,c,s=!1){for(const i of t(n,c,s))o.has(i)||(o.set(i,!0),i.onInit(),initComponentsSync(i,c,s))}function t(o,t,c=!1){const s=[...Object.values(o)];o===t&&t.attachedComponents.forEach(n=>s.push(n));const i=[];for(const o of s)if(o instanceof n||null!=o?.constructor&&!0===o.constructor.__isActorComponent){const n=o;if(!isComponentEnabledInEnvironment(n,c))continue;n.actor=t,i.push(n)}return i}export function isComponentEnabledInEnvironment(n,o=!1){return!(o&&!n.constructor.__inEditor)&&!(!o&&n.constructor.__onlyEditor)}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -8,6 +8,8 @@ declare class Transition {
|
|
|
8
8
|
export type AnimationStateOptions = {
|
|
9
9
|
/** Whether the animation should loop. Default: true */
|
|
10
10
|
loop: boolean;
|
|
11
|
+
/** Priority passed to the animation player. Higher priority can override lower priority one-off animations. Default: 0 */
|
|
12
|
+
priority?: number;
|
|
11
13
|
};
|
|
12
14
|
export declare class AnimationState {
|
|
13
15
|
readonly clip?: AnimationClip;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let t=0;class i{constructor(t,i){this.state=t,this.predicate=i}}const s={loop:!0};export class AnimationState{constructor(i,n=s){this.clip=i,this.options=n,this.uuid=t++,this.transitions=[],this.options={...s,...n}}named(t){return this.name=t,this}getAncestors(){return null!=this.parent?[this,...this.parent.getAncestors()]:[this]}getRoot(){return null!=this.parent?this.parent.getRoot():this}createChild(t,i){const s=new AnimationState(t);return s.parent=this,this.transitionsTo(s,i),s}split(t,i=null,s=null){return[this.createChild(i,t),this.createChild(s,e(t))]}transitionsTo(t,s=()=>!0){this.transitions.push(new i(t,s))}transitionsOnComplete(t,i){this.transitionsTo(t,t=>!!i&&i(t)||t>=this.clip.duration-.5)}transitionsBetween(t,i){this.transitionsTo(t,i),t.transitionsTo(this,e(i))}}export class AnimationStateMachine{constructor(t){this.initialState=t,this.timer=0,this.current=t}step(t){return this.timer+=t,this._getNext()}_getNext(t=1){const i=n(this.current.getRoot(),this.timer,this.current);return i.uuid!==this.current.uuid&&(this.timer=0,this.current=i),--t>0?this._getNext(t):this.current}}function n(t,i,s){for(const e of t.transitions)if(e.predicate(i))return n(e.state,e.state.uuid===s.uuid?i:0,s);return null==t.clip?t.getAncestors().find(t=>null!=t.clip)??t:t}const e=t=>i=>!t(i);/*
|
|
1
|
+
let t=0;class i{constructor(t,i){this.state=t,this.predicate=i}}const s={loop:!0,priority:0};export class AnimationState{constructor(i,n=s){this.clip=i,this.options=n,this.uuid=t++,this.transitions=[],this.options={...s,...n}}named(t){return this.name=t,this}getAncestors(){return null!=this.parent?[this,...this.parent.getAncestors()]:[this]}getRoot(){return null!=this.parent?this.parent.getRoot():this}createChild(t,i){const s=new AnimationState(t);return s.parent=this,this.transitionsTo(s,i),s}split(t,i=null,s=null){return[this.createChild(i,t),this.createChild(s,e(t))]}transitionsTo(t,s=()=>!0){this.transitions.push(new i(t,s))}transitionsOnComplete(t,i){this.transitionsTo(t,t=>!!i&&i(t)||t>=this.clip.duration-.5)}transitionsBetween(t,i){this.transitionsTo(t,i),t.transitionsTo(this,e(i))}}export class AnimationStateMachine{constructor(t){this.initialState=t,this.timer=0,this.current=t}step(t){return this.timer+=t,this._getNext()}_getNext(t=1){const i=n(this.current.getRoot(),this.timer,this.current);return i.uuid!==this.current.uuid&&(this.timer=0,this.current=i),--t>0?this._getNext(t):this.current}}function n(t,i,s){for(const e of t.transitions)if(e.predicate(i))return n(e.state,e.state.uuid===s.uuid?i:0,s);return null==t.clip?t.getAncestors().find(t=>null!=t.clip)??t:t}const e=t=>i=>!t(i);/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Constructable, ContainerInstance } from "typedi";
|
|
2
2
|
import { ShaderType, ActorType, ActorComponentType } from '../shader/shader.js';
|
|
3
3
|
import { World } from './services/world.js';
|
|
4
|
+
import { type DynamicResolutionOptions, type UpscalingOptions } from '../rendering.js';
|
|
4
5
|
import { Observable } from 'rxjs';
|
|
5
6
|
import { DetailTier } from "../scene/model.js";
|
|
6
7
|
import type { ParameterType } from "../shader/parameter.js";
|
|
@@ -32,6 +33,8 @@ export type InitiateGameConfig = {
|
|
|
32
33
|
rendering?: Partial<{
|
|
33
34
|
resolutionScale: number;
|
|
34
35
|
maxPixelRatio: number;
|
|
36
|
+
dynamicResolution: DynamicResolutionOptions;
|
|
37
|
+
upscaling: UpscalingOptions;
|
|
35
38
|
msaa: number;
|
|
36
39
|
fpsCap: number | null;
|
|
37
40
|
depthPrepass: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as s}from"./actors/factory.js";import{World as n}from"./services/world.js";import{SceneMaterializer as r}from"../scene/materializer.js";import{ViewController as o}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as h}from"../scene/asset-resource-loader.js";import{AssetLoader as u}from"./services/asset-loader.js";import{polyfillClient as f}from"./polyfill.js";import{Subject as g}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as j}from"three";import{ShaderProvider as v}from"./services/shader-provider.js";import{SceneDataService as
|
|
1
|
+
import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as s}from"./actors/factory.js";import{World as n}from"./services/world.js";import{SceneMaterializer as r}from"../scene/materializer.js";import{ViewController as o}from"./services/render.js";import{RenderingView as i}from"../rendering.js";import{PhysicsSystem as a}from"./services/physics/physics-system.js";import{MeshComponent as c}from"./actors/builtin/components/mesh-component.js";import{builtInComponents as d}from"./actors/builtin/components/index.js";import{activeContainerInstance as m}from"./actors/internal/container-map.js";import{InputService as l}from"./input/index.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as h}from"../scene/asset-resource-loader.js";import{AssetLoader as u}from"./services/asset-loader.js";import{polyfillClient as f}from"./polyfill.js";import{Subject as g}from"rxjs";import{PointerEvents as w}from"./services/pointer-events.js";import{RuntimeBundledBackendService as b}from"../scene/runtime-bundled-backend-service.js";import{Scene as j}from"three";import{ShaderProvider as v}from"./services/shader-provider.js";import{SceneDataService as y}from"../scene/scene-data-service.js";import{AssetsProvider as S}from"../scene/assets-provider.js";export function initiateGame(g,x){if(f(),0!=x.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const I=e.of("default"),R=new HologyRuntime(I),P=new s(I,{inEditor:!1});var D;P.classes=x.actors,e.set(s,P),D=x.element,Object.assign(D.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",overflow:"hidden"});const A=new i(x.element,{enableXR:!0===x.xr?.enabled,maxPixelRatio:x.rendering?.maxPixelRatio,resolutionScale:x.rendering?.resolutionScale,dynamicResolution:x.rendering?.dynamicResolution,upscaling:x.rendering?.upscaling,msaa:x.rendering?.msaa,fpsCap:x.rendering?.fpsCap,depthPrepass:{enabled:!0===x.rendering?.depthPrepass?.enabled},bloom:{enabled:!1!==x?.rendering?.bloom?.enabled},reflection:{enabled:!1!==x?.rendering?.reflection?.enabled},shadows:{cascadeUpdateIntervals:[22,40,60,120]}});A.renderer.shadowMap.enabled=x.rendering?.shadows?.enabled??!0,A.renderer.shadowMap.autoUpdate=x.rendering?.shadows?.autoUpdate??!0,A.renderer.debug.checkShaderErrors=!1,e.set(i,A);const E=new o(A);e.set(o,E);const G=new b,O=new p(G),z=new h;z.setDataDir(x.dataDir),z.initKtx2(A.renderer);const C=Object.entries(x.shaders).map(([e,t])=>({name:e,type:t})),H=Object.entries(x.actors).map(([e,t])=>({name:e,type:t})),M={...d,...x.components??{}},T=Object.entries(M).map(([e,t])=>({name:e,type:t})),U=new v(C);e.set(v,U);const W=new u(z,O,C);e.set(S,O),e.set(h,z),e.set(u,W);const k=new j,F=new r(k,new y,O,z,A,C,H,P,T);e.set(r,F);const N=e.get(n);return e.set(n,N),N.materializer=F,(async()=>{const s=e.get(a);if(await s.start(),R.isShutdown)return;if(await G.preloadData(),R.isShutdown)return;N.scene=k;const{scene:n,actors:r}=await t(A,x.sceneName,x.dataDir,x.shaders,x.actors,M,P,G,O,z,{detailTier:x.detailTier});N.scene=n,s.scene=N.scene;for(const e of k.children)N.scene.add(e);if(R.isShutdown)return void A.stop();e.import([c]);for(const e of r)N.addActor(e);s.addFromScene(n),console.log("Start compile shaders"),console.time("compile shaders"),await A.compileAsync(),console.timeEnd("compile shaders"),console.log("Finished compile shaders. Programs: ",A.renderer.info.programs?.length??0),console.log("Start init scene textures"),console.time("init scene textures"),A.initTextures(),console.timeEnd("init scene textures");const o=I.get(l);A.loop(e=>{o.update(e)}),R.status=5,R.shutdownStarted.subscribe(()=>{z.disposeAll()}),m.value=I,I.remove(g),I.set({id:g,type:g});const i=I.get(g);m.value=null,R.gameInstance=i,I.get(w).start(),i instanceof GameInstance&&await i.onStart(),R._resolver(!0)})(),R}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new g,this.ready=new Promise(e=>{this._resolver=e})}getWorld(){return this.containerInstance.get(n)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0;const e=this.shutdownStarted;e.next(),e.complete(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(l).stop();const t=this.containerInstance.get(i);t?.stop();const s=this.containerInstance.get(o);s.setMuted(!0),s.dispose();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(a).stop(),this.containerInstance.get(r).dispose(),this.containerInstance.get(w).stop(),this.containerInstance.reset()}}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as t}from"tslib";import{Service as r}from"typedi";import{BaseActor as
|
|
1
|
+
import{__decorate as t}from"tslib";import{Service as r}from"typedi";import{BaseActor as o}from"../actors/actor.js";import{ActorFactory as e}from"../actors/factory.js";import{Vector3 as i}from"three";import{ActorComponent as s}from"../../gameplay/actors/component.js";import{Subject as n}from"rxjs";import{RenderingView as c}from"../../rendering.js";import{randomUUID as a}from"../../utils/uuid";import{PrefabInstance as h}from"../../scene/objects/prefab";import{PhysicsSystem as m}from"./physics/physics-system.js";import{inject as p}from"../../gameplay/inject.js";import{isComponentEnabledInEnvironment as l}from"../actors/internal/component-init.js";const f=new i;class d{constructor(t){this.view=t}get direction(){return this.view.csm.lightDirection}set intensity(t){this.view.csm.lightIntensity=t,this.view.csm.lights.forEach(t=>t.intensity=this.view.csm.lightIntensity)}get intensity(){return this.view.csm.lightIntensity}get position(){return 0==this.view.csm.lights.length?f:this.view.csm.lights[0].position}}let y=class{constructor(){this.actorFactory=p(e),this.view=p(c),this.physics=p(m),this.actors=[],this.actorAdded=new n,this.actorRemoved=new n,this.directionalLight=new d(this.view)}async spawnActor(t,r,o){if(null==t)throw new Error("Cannot spawn actor with null type");if("prefab"in t){const e=await this.spawnPrefab(t.prefab,r,o),i=e.mainActor;if(null==i)throw new Error(`Prefab has no main actor or there was an error when spwaning it. Prefab: ${JSON.stringify(t.prefab)}`);return i.disposed.subscribe(()=>{const t=e.actors.findIndex(t=>t===i);t>=0&&e.actors.splice(t,1),this.removePrefab(e)}),i}const e=await this.actorFactory.create(t,r,o);return this.addActor(e,r,o),e}spawnActorSync(t,r,o){if(null==t)throw new Error("Cannot spawn actor with null type");const e=this.actorFactory.createSync(t,r,o);return this.addActor(e,r,o),e}addActor(t,r,o){r&&t.object.position.copy(r),o&&t.object.rotation.copy(o),null==t.object.parent&&this.scene.add(t.object),this.actors.push(t),w(t,t=>t.onBeginPlay(),this.actorFactory.inEditor),this.actorAdded.next(t)}removeActor(t){w(t,t=>t.onEndPlay(),this.actorFactory.inEditor);const r=this.actors.indexOf(t);r>=0&&this.actors.splice(r,1),t.object.removeFromParent(),t.disposed.next(!0),this.actorRemoved.next(t),this.physics.removeActor(t)}findActorByType(t,r){return this.actors.find(o=>o instanceof t&&(null==r||o.object.name==r))}findActorsByType(t,r){return this.actors.filter(o=>o instanceof t&&(null==r||o.object.name==r))}async spawnPrefab(t,r,o){if(null==this.materializer)return console.error("Internal error: Materializer is missing on World"),null;const e=new h,{object:i,actors:s,mainActor:n}=await this.materializer.createFromPrefabAsset(t.asset,{sceneObjectChain:["r-"+a()]},void 0,void 0,!1);return e.object=i,e.actors=s,e.mainActor=n,this.scene.add(i),null!=r&&i.position.copy(r),null!=o&&i.rotation.copy(o),s.forEach(t=>{this.addActor(t)}),this.physics.addFromScene(i),e}removePrefab(t){t.actors.forEach(t=>this.removeActor(t)),t.object?.removeFromParent(),this.physics.removeRemoved(t.object)}};y=t([r()],y);export{y as World};function w(t,r,e=!1,i=new WeakSet){if(!i.has(t))return i.add(t),r(t),t instanceof o&&t.attachedComponents.forEach(t=>{l(t,e)&&w(t,r,e,i)}),Object.entries(t).filter(([t,r])=>r instanceof s&&l(r,e)).forEach(([t,o])=>{w(o,r,e,i)})}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { Pass } from 'three/examples/jsm/postprocessing/Pass.js';
|
|
3
|
+
export type UpscalingMethod = 'linear' | 'spatial' | 'catmull-rom' | 'temporal';
|
|
4
|
+
export type TemporalUpscalingOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* How strongly history contributes to the current frame. Defaults to 0.88.
|
|
7
|
+
*/
|
|
8
|
+
feedback?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Sub-pixel jitter strength in render pixels. Defaults to 1.
|
|
11
|
+
*/
|
|
12
|
+
jitterScale?: number;
|
|
13
|
+
};
|
|
14
|
+
export type UpscalingOptions = {
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* `temporal` jitters the projection and accumulates history using depth reprojection.
|
|
18
|
+
* `spatial` and `catmull-rom` are single-frame upscalers with sharpening.
|
|
19
|
+
* `linear` only decouples render and presentation resolutions.
|
|
20
|
+
*/
|
|
21
|
+
method?: UpscalingMethod;
|
|
22
|
+
/**
|
|
23
|
+
* Contrast-limited sharpening amount for spatial and temporal upscaling. Defaults to 0.2.
|
|
24
|
+
*/
|
|
25
|
+
sharpness?: number;
|
|
26
|
+
temporal?: TemporalUpscalingOptions;
|
|
27
|
+
};
|
|
28
|
+
export type TemporalUpscalingFrameState = {
|
|
29
|
+
depthTexture: THREE.Texture | null;
|
|
30
|
+
currentJitterUv: THREE.Vector2;
|
|
31
|
+
currentViewProjectionInverse: THREE.Matrix4;
|
|
32
|
+
previousViewProjection: THREE.Matrix4;
|
|
33
|
+
};
|
|
34
|
+
export declare function getUpscalingMethod(options?: UpscalingOptions): UpscalingMethod;
|
|
35
|
+
export declare function getTemporalUpscalingJitter(frameIndex: number, target: THREE.Vector2, scale?: number): THREE.Vector2;
|
|
36
|
+
export declare class UpscaleOutputPass extends Pass {
|
|
37
|
+
private readonly options;
|
|
38
|
+
readonly uniforms: {
|
|
39
|
+
tDiffuse: {
|
|
40
|
+
value: THREE.Texture | null;
|
|
41
|
+
};
|
|
42
|
+
tDepth: {
|
|
43
|
+
value: THREE.Texture | null;
|
|
44
|
+
};
|
|
45
|
+
tHistory: {
|
|
46
|
+
value: THREE.Texture | null;
|
|
47
|
+
};
|
|
48
|
+
toneMappingExposure: {
|
|
49
|
+
value: number;
|
|
50
|
+
};
|
|
51
|
+
inputSize: {
|
|
52
|
+
value: THREE.Vector2;
|
|
53
|
+
};
|
|
54
|
+
sharpness: {
|
|
55
|
+
value: number;
|
|
56
|
+
};
|
|
57
|
+
temporalFeedback: {
|
|
58
|
+
value: number;
|
|
59
|
+
};
|
|
60
|
+
historyValid: {
|
|
61
|
+
value: number;
|
|
62
|
+
};
|
|
63
|
+
currentJitterUv: {
|
|
64
|
+
value: THREE.Vector2;
|
|
65
|
+
};
|
|
66
|
+
currentViewProjectionInverse: {
|
|
67
|
+
value: THREE.Matrix4;
|
|
68
|
+
};
|
|
69
|
+
previousViewProjection: {
|
|
70
|
+
value: THREE.Matrix4;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
readonly material: THREE.RawShaderMaterial;
|
|
74
|
+
private readonly fsQuad;
|
|
75
|
+
private readonly drawingBufferSize;
|
|
76
|
+
private historyRead;
|
|
77
|
+
private historyWrite;
|
|
78
|
+
private historyValid;
|
|
79
|
+
private frameState;
|
|
80
|
+
private _outputColorSpace;
|
|
81
|
+
private _toneMapping;
|
|
82
|
+
private _method;
|
|
83
|
+
private _usesCatmullRom;
|
|
84
|
+
private _usesTemporal;
|
|
85
|
+
constructor(options?: UpscalingOptions);
|
|
86
|
+
setFrameState(frameState: TemporalUpscalingFrameState | null): void;
|
|
87
|
+
resetHistory(): void;
|
|
88
|
+
render(renderer: THREE.WebGLRenderer, writeBuffer: THREE.WebGLRenderTarget, readBuffer: THREE.WebGLRenderTarget): void;
|
|
89
|
+
dispose(): void;
|
|
90
|
+
private updateDefines;
|
|
91
|
+
private ensureHistoryTargets;
|
|
92
|
+
private createHistoryTarget;
|
|
93
|
+
private disposeHistoryTargets;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=upscaling-pass.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import*as e from"three";import{Pass as t,FullScreenQuad as r}from"three/examples/jsm/postprocessing/Pass.js";export function getUpscalingMethod(e){return e?.method??"spatial"}export function getTemporalUpscalingJitter(e,t,r=1){return t.set((n(e%1024+1,2)-.5)*r,(n(e%1024+1,3)-.5)*r),t}export class UpscaleOutputPass extends t{constructor(t={}){super(),this.options=t,this.uniforms={tDiffuse:{value:null},tDepth:{value:null},tHistory:{value:null},toneMappingExposure:{value:1},inputSize:{value:new e.Vector2(1,1)},sharpness:{value:.2},temporalFeedback:{value:.88},historyValid:{value:0},currentJitterUv:{value:new e.Vector2},currentViewProjectionInverse:{value:new e.Matrix4},previousViewProjection:{value:new e.Matrix4}},this.drawingBufferSize=new e.Vector2,this.historyRead=null,this.historyWrite=null,this.historyValid=!1,this.frameState=null,this._outputColorSpace=null,this._toneMapping=null,this._method=null,this._usesCatmullRom=null,this._usesTemporal=null,this.material=new e.RawShaderMaterial({name:"UpscaleOutputPass",uniforms:this.uniforms,vertexShader:o,fragmentShader:a}),this.fsQuad=new r(this.material)}setFrameState(e){this.frameState=e}resetHistory(){this.historyValid=!1}render(t,r,n){t.getDrawingBufferSize(this.drawingBufferSize);const o=getUpscalingMethod(this.options),a=n.width<this.drawingBufferSize.x-.5||n.height<this.drawingBufferSize.y-.5,s="temporal"===o&&null!=this.frameState&&null!=this.frameState.depthTexture,l=a&&(s||"spatial"===o||"catmull-rom"===o);if(this.uniforms.tDiffuse.value=n.texture,this.uniforms.tDepth.value=this.frameState?.depthTexture??null,this.uniforms.toneMappingExposure.value=t.toneMappingExposure,this.uniforms.inputSize.value.set(n.width,n.height),this.uniforms.sharpness.value=e.MathUtils.clamp(i(this.options.sharpness,.2),0,1),this.uniforms.temporalFeedback.value=e.MathUtils.clamp(i(this.options.temporal?.feedback,.88),0,.97),s?(this.ensureHistoryTargets(this.drawingBufferSize.x,this.drawingBufferSize.y),this.uniforms.tHistory.value=this.historyRead?.texture??null,this.uniforms.historyValid.value=this.historyValid?1:0,this.uniforms.currentJitterUv.value.copy(this.frameState.currentJitterUv),this.uniforms.currentViewProjectionInverse.value.copy(this.frameState.currentViewProjectionInverse),this.uniforms.previousViewProjection.value.copy(this.frameState.previousViewProjection)):(this.uniforms.tHistory.value=null,this.uniforms.historyValid.value=0,this.uniforms.currentJitterUv.value.set(0,0)),this.updateDefines(t,o,l,s),!0===this.renderToScreen?(t.setRenderTarget(null),this.fsQuad.render(t)):(t.setRenderTarget(r),this.clear&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),this.fsQuad.render(t)),s&&null!=this.historyWrite){t.setRenderTarget(this.historyWrite),this.fsQuad.render(t);const e=this.historyRead;this.historyRead=this.historyWrite,this.historyWrite=e,this.historyValid=!0}else s||(this.historyValid=!1)}dispose(){this.material.dispose(),this.fsQuad.dispose(),this.disposeHistoryTargets()}updateDefines(t,r,i,n){this._outputColorSpace===t.outputColorSpace&&this._toneMapping===t.toneMapping&&this._method===r&&this._usesCatmullRom===i&&this._usesTemporal===n||(this._outputColorSpace=t.outputColorSpace,this._toneMapping=t.toneMapping,this._method=r,this._usesCatmullRom=i,this._usesTemporal=n,this.material.defines={},i&&(this.material.defines.CATMULL_ROM_UPSCALE=""),n&&(this.material.defines.TEMPORAL_UPSCALE=""),e.ColorManagement.getTransfer(t.outputColorSpace)===e.SRGBTransfer&&(this.material.defines.SRGB_TRANSFER=""),t.toneMapping===e.LinearToneMapping?this.material.defines.LINEAR_TONE_MAPPING="":t.toneMapping===e.ReinhardToneMapping?this.material.defines.REINHARD_TONE_MAPPING="":t.toneMapping===e.CineonToneMapping?this.material.defines.CINEON_TONE_MAPPING="":t.toneMapping===e.ACESFilmicToneMapping?this.material.defines.ACES_FILMIC_TONE_MAPPING="":t.toneMapping===e.AgXToneMapping?this.material.defines.AGX_TONE_MAPPING="":t.toneMapping===e.NeutralToneMapping&&(this.material.defines.NEUTRAL_TONE_MAPPING=""),this.material.needsUpdate=!0)}ensureHistoryTargets(e,t){const r=Math.max(1,Math.floor(e)),i=Math.max(1,Math.floor(t));null!=this.historyRead&&null!=this.historyWrite&&this.historyRead.width===r&&this.historyRead.height===i||(this.disposeHistoryTargets(),this.historyRead=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyRead"),this.historyWrite=this.createHistoryTarget(r,i,"UpscaleOutputPass.historyWrite"),this.historyValid=!1)}createHistoryTarget(t,r,i){const n=new e.WebGLRenderTarget(t,r,{type:e.HalfFloatType,minFilter:e.LinearFilter,magFilter:e.LinearFilter,format:e.RGBAFormat,depthBuffer:!1,stencilBuffer:!1});return n.texture.name=i,n.texture.generateMipmaps=!1,n}disposeHistoryTargets(){this.historyRead?.dispose(),this.historyWrite?.dispose(),this.historyRead=null,this.historyWrite=null,this.historyValid=!1}}function i(e,t){return null!=e&&Number.isFinite(e)?e:t}function n(e,t){let r=0,i=1/t;for(;e>0;)r+=i*(e%t),e=Math.floor(e/t),i/=t;return r}const o="\n precision highp float;\n\n uniform mat4 modelViewMatrix;\n uniform mat4 projectionMatrix;\n\n attribute vec3 position;\n attribute vec2 uv;\n\n varying vec2 vUv;\n\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n",a="\n precision highp float;\n\n uniform sampler2D tDiffuse;\n uniform sampler2D tDepth;\n uniform sampler2D tHistory;\n uniform vec2 inputSize;\n uniform float sharpness;\n uniform float temporalFeedback;\n uniform float historyValid;\n uniform vec2 currentJitterUv;\n uniform mat4 currentViewProjectionInverse;\n uniform mat4 previousViewProjection;\n\n #include <common>\n #include <tonemapping_pars_fragment>\n #include <colorspace_pars_fragment>\n #include <dithering_pars_fragment>\n\n varying vec2 vUv;\n\n vec4 applyOutputTransform(vec4 color) {\n #ifdef LINEAR_TONE_MAPPING\n color.rgb = LinearToneMapping(color.rgb);\n #elif defined(REINHARD_TONE_MAPPING)\n color.rgb = ReinhardToneMapping(color.rgb);\n #elif defined(CINEON_TONE_MAPPING)\n color.rgb = CineonToneMapping(color.rgb);\n #elif defined(ACES_FILMIC_TONE_MAPPING)\n color.rgb = ACESFilmicToneMapping(color.rgb);\n #elif defined(AGX_TONE_MAPPING)\n color.rgb = AgXToneMapping(color.rgb);\n #elif defined(NEUTRAL_TONE_MAPPING)\n color.rgb = NeutralToneMapping(color.rgb);\n #endif\n\n #ifdef SRGB_TRANSFER\n color = sRGBTransferOETF(color);\n #endif\n\n return color;\n }\n\n vec4 readOutputColor(vec2 uv) {\n return applyOutputTransform(texture2D(tDiffuse, clamp(uv, vec2(0.0), vec2(1.0))));\n }\n\n float cubicWeight(float value) {\n value = abs(value);\n float value2 = value * value;\n float value3 = value2 * value;\n if (value <= 1.0) {\n return 1.5 * value3 - 2.5 * value2 + 1.0;\n }\n if (value < 2.0) {\n return -0.5 * value3 + 2.5 * value2 - 4.0 * value + 2.0;\n }\n return 0.0;\n }\n\n vec4 sampleCatmullRom(vec2 uv) {\n vec2 texelSize = 1.0 / inputSize;\n vec2 pixel = uv * inputSize - 0.5;\n vec2 basePixel = floor(pixel);\n vec2 fraction = pixel - basePixel;\n vec4 color = vec4(0.0);\n float weightSum = 0.0;\n\n for (int y = -1; y <= 2; y++) {\n float wy = cubicWeight(float(y) - fraction.y);\n for (int x = -1; x <= 2; x++) {\n float wx = cubicWeight(float(x) - fraction.x);\n float weight = wx * wy;\n vec2 sampleUv = (basePixel + vec2(float(x), float(y)) + 0.5) * texelSize;\n color += readOutputColor(sampleUv) * weight;\n weightSum += weight;\n }\n }\n\n return color / max(weightSum, 0.00001);\n }\n\n void getNeighborhoodBounds(vec2 uv, out vec3 minColor, out vec3 maxColor, out vec3 blurColor) {\n vec2 texelSize = 1.0 / inputSize;\n vec3 center = readOutputColor(uv).rgb;\n vec3 north = readOutputColor(uv + vec2(0.0, texelSize.y)).rgb;\n vec3 south = readOutputColor(uv - vec2(0.0, texelSize.y)).rgb;\n vec3 east = readOutputColor(uv + vec2(texelSize.x, 0.0)).rgb;\n vec3 west = readOutputColor(uv - vec2(texelSize.x, 0.0)).rgb;\n minColor = min(center, min(min(north, south), min(east, west)));\n maxColor = max(center, max(max(north, south), max(east, west)));\n blurColor = (north + south + east + west) * 0.25;\n }\n\n vec3 applyContrastLimitedSharpen(vec2 uv, vec3 color) {\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(uv, minColor, maxColor, blurColor);\n return clamp(color + (color - blurColor) * sharpness, minColor, maxColor);\n }\n\n vec2 reprojectHistoryUv(vec2 uv, float depth) {\n vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);\n vec4 world = currentViewProjectionInverse * clip;\n world /= max(abs(world.w), 0.00001);\n vec4 previousClip = previousViewProjection * world;\n vec3 previousNdc = previousClip.xyz / max(abs(previousClip.w), 0.00001);\n return previousNdc.xy * 0.5 + 0.5;\n }\n\n vec4 applyTemporal(vec2 currentUv, vec4 currentColor) {\n if (historyValid < 0.5) {\n return currentColor;\n }\n\n float depth = texture2D(tDepth, clamp(currentUv, vec2(0.0), vec2(1.0))).x;\n if (depth <= 0.0 || depth >= 1.0) {\n return currentColor;\n }\n\n vec2 historyUv = reprojectHistoryUv(currentUv, depth);\n if (\n historyUv.x < 0.0 || historyUv.x > 1.0 ||\n historyUv.y < 0.0 || historyUv.y > 1.0\n ) {\n return currentColor;\n }\n\n vec3 minColor;\n vec3 maxColor;\n vec3 blurColor;\n getNeighborhoodBounds(currentUv, minColor, maxColor, blurColor);\n vec4 historyColor = texture2D(tHistory, historyUv);\n historyColor.rgb = clamp(historyColor.rgb, minColor, maxColor);\n return mix(currentColor, historyColor, temporalFeedback);\n }\n\n void main() {\n vec2 currentUv = vUv;\n #ifdef TEMPORAL_UPSCALE\n currentUv -= currentJitterUv;\n #endif\n\n #ifdef CATMULL_ROM_UPSCALE\n gl_FragColor = sampleCatmullRom(currentUv);\n gl_FragColor.rgb = applyContrastLimitedSharpen(currentUv, gl_FragColor.rgb);\n #else\n gl_FragColor = readOutputColor(currentUv);\n #endif\n\n #ifdef TEMPORAL_UPSCALE\n gl_FragColor = applyTemporal(currentUv, gl_FragColor);\n #endif\n\n #include <dithering_fragment>\n }\n";/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
package/dist/rendering.d.ts
CHANGED
|
@@ -9,11 +9,50 @@ import { type PostProcessSettings, type PostProcessVolume } from "./gameplay/act
|
|
|
9
9
|
import { type PostProcessEffect, type PostProcessEffectOptions } from "./rendering/post-process-effect.js";
|
|
10
10
|
import { LightVolume } from "./rendering/light-probes/light-volume-capture.js";
|
|
11
11
|
import type { PostProcessMaterialSource } from "./shader/post-process-shader.js";
|
|
12
|
+
import { type UpscalingOptions } from "./rendering/upscaling-pass.js";
|
|
13
|
+
export type { UpscalingOptions } from "./rendering/upscaling-pass.js";
|
|
14
|
+
export type DynamicResolutionOptions = {
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Lowest resolution scale dynamic resolution may use. Defaults to 0.7.
|
|
18
|
+
* The effective scale will never go above `resolutionScale`.
|
|
19
|
+
*/
|
|
20
|
+
minScale?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Frame rate target used to decide when to scale down or recover.
|
|
23
|
+
* Defaults to 60, capped by `fpsCap` when one is set.
|
|
24
|
+
*/
|
|
25
|
+
targetFps?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Scale amount removed when frame time is consistently above target.
|
|
28
|
+
* Defaults to 0.05.
|
|
29
|
+
*/
|
|
30
|
+
decreaseStep?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Scale amount restored when frame time has enough headroom.
|
|
33
|
+
* Defaults to 0.025.
|
|
34
|
+
*/
|
|
35
|
+
increaseStep?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Minimum frames to average before changing the scale. Defaults to 20.
|
|
38
|
+
*/
|
|
39
|
+
sampleFrames?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Minimum milliseconds between scale-down adjustments. Defaults to 500.
|
|
42
|
+
*/
|
|
43
|
+
decreaseCooldown?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Minimum milliseconds between scale-up adjustments. Defaults to 2000.
|
|
46
|
+
*/
|
|
47
|
+
increaseCooldown?: number;
|
|
48
|
+
};
|
|
12
49
|
export type RenderingViewOptions = {
|
|
13
50
|
enableOutlines?: boolean;
|
|
14
51
|
enableXR?: boolean;
|
|
15
52
|
maxPixelRatio?: number;
|
|
16
53
|
resolutionScale?: number;
|
|
54
|
+
dynamicResolution?: DynamicResolutionOptions;
|
|
55
|
+
upscaling?: UpscalingOptions;
|
|
17
56
|
msaa?: number;
|
|
18
57
|
fpsCap?: number | null;
|
|
19
58
|
depthPrepass?: {
|
|
@@ -101,10 +140,45 @@ export declare class RenderingView {
|
|
|
101
140
|
setPaused(value: boolean): void;
|
|
102
141
|
resolutionScale: number;
|
|
103
142
|
maxPixelRatio: number;
|
|
143
|
+
private dynamicResolutionScale;
|
|
144
|
+
private dynamicResolutionFrameTimeAverage;
|
|
145
|
+
private dynamicResolutionFrameSamples;
|
|
146
|
+
private dynamicResolutionLastAdjustmentAt;
|
|
147
|
+
private upscaleOutputPass;
|
|
148
|
+
private readonly unjitteredProjectionMatrix;
|
|
149
|
+
private readonly temporalJitter;
|
|
150
|
+
private readonly temporalJitterUv;
|
|
151
|
+
private readonly currentUnjitteredViewProjectionMatrix;
|
|
152
|
+
private readonly currentViewProjectionMatrix;
|
|
153
|
+
private readonly currentViewProjectionMatrixInverse;
|
|
154
|
+
private readonly previousViewProjectionMatrix;
|
|
155
|
+
private readonly temporalUpscalingFrameState;
|
|
156
|
+
private temporalUpscalingFrameIndex;
|
|
157
|
+
private hasPreviousTemporalViewProjection;
|
|
158
|
+
private projectionJitterApplied;
|
|
159
|
+
get currentResolutionScale(): number;
|
|
160
|
+
get currentRenderPixelRatio(): number;
|
|
161
|
+
get currentPresentationPixelRatio(): number;
|
|
162
|
+
getRenderSize(target?: THREE.Vector2): THREE.Vector2;
|
|
163
|
+
private isUpscalingEnabled;
|
|
164
|
+
private isTemporalUpscalingEnabled;
|
|
165
|
+
resetUpscalingHistory(): void;
|
|
166
|
+
private prepareUpscalingFrame;
|
|
167
|
+
private finishUpscalingFrame;
|
|
168
|
+
private getBasePixelRatio;
|
|
169
|
+
private getBaseResolutionScale;
|
|
170
|
+
private getDynamicResolutionMinScale;
|
|
171
|
+
private getEffectiveResolutionScale;
|
|
172
|
+
private getRenderPixelRatio;
|
|
173
|
+
private getPresentationPixelRatio;
|
|
174
|
+
private resetDynamicResolutionAverage;
|
|
175
|
+
private updateDynamicResolution;
|
|
104
176
|
private onResize;
|
|
105
177
|
private previousClientWith;
|
|
106
178
|
private previousClientHeight;
|
|
107
|
-
|
|
179
|
+
private previousRenderPixelRatio;
|
|
180
|
+
private previousPresentationPixelRatio;
|
|
181
|
+
resizeRender(force?: boolean): void;
|
|
108
182
|
addPostProcessVolume(volume: PostProcessVolume): void;
|
|
109
183
|
removePostProcessVolume(volume: PostProcessVolume): void;
|
|
110
184
|
addPostProcessEffect(source: PostProcessMaterialSource, options?: PostProcessEffectOptions): PostProcessEffect;
|
|
@@ -171,6 +245,7 @@ export declare class RenderingView {
|
|
|
171
245
|
private createGBufferMaterial;
|
|
172
246
|
private isDepthPrepassEnabled;
|
|
173
247
|
private usesSceneFeedbackUniforms;
|
|
248
|
+
private usesShaderUniform;
|
|
174
249
|
private isDepthPrepassEligibleMaterial;
|
|
175
250
|
private isDepthPrepassEligibleMesh;
|
|
176
251
|
private createDepthPrepassMaterial;
|
|
@@ -215,6 +290,7 @@ export declare class RenderingView {
|
|
|
215
290
|
private hasBloom;
|
|
216
291
|
private darkenNonBloomed;
|
|
217
292
|
private restoreMaterial;
|
|
293
|
+
private initSceneColorUniform;
|
|
218
294
|
private initDepthUniform;
|
|
219
295
|
private initNormalUniform;
|
|
220
296
|
private initShadowUniform;
|