@babylonjs/core 7.8.2 → 7.10.0
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/Behaviors/Cameras/framingBehavior.d.ts +1 -1
- package/Behaviors/Cameras/framingBehavior.js +1 -1
- package/Behaviors/Cameras/framingBehavior.js.map +1 -1
- package/Behaviors/Meshes/baseSixDofDragBehavior.d.ts +5 -5
- package/Behaviors/Meshes/baseSixDofDragBehavior.js +4 -4
- package/Behaviors/Meshes/baseSixDofDragBehavior.js.map +1 -1
- package/Cameras/touchCamera.js +4 -2
- package/Cameras/touchCamera.js.map +1 -1
- package/Collisions/gpuPicker.d.ts +38 -0
- package/Collisions/gpuPicker.js +256 -0
- package/Collisions/gpuPicker.js.map +1 -0
- package/Collisions/index.d.ts +1 -0
- package/Collisions/index.js +1 -0
- package/Collisions/index.js.map +1 -1
- package/Debug/physicsViewer.d.ts +4 -2
- package/Debug/physicsViewer.js +16 -4
- package/Debug/physicsViewer.js.map +1 -1
- package/Engines/Extensions/engine.views.d.ts +1 -0
- package/Engines/Extensions/engine.views.js +3 -0
- package/Engines/Extensions/engine.views.js.map +1 -0
- package/Engines/abstractEngine.js +3 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/thinEngine.js +8 -7
- package/Engines/thinEngine.js.map +1 -1
- package/Gizmos/boundingBoxGizmo.d.ts +6 -5
- package/Gizmos/boundingBoxGizmo.js +5 -5
- package/Gizmos/boundingBoxGizmo.js.map +1 -1
- package/Gizmos/lightGizmo.js +1 -2
- package/Gizmos/lightGizmo.js.map +1 -1
- package/Helpers/environmentHelper.js +2 -0
- package/Helpers/environmentHelper.js.map +1 -1
- package/LensFlares/lensFlareSystem.js +2 -2
- package/LensFlares/lensFlareSystem.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js +2 -2
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js.map +1 -1
- package/Materials/Node/nodeMaterial.d.ts +2 -2
- package/Materials/Node/nodeMaterial.js +6 -6
- package/Materials/Node/nodeMaterial.js.map +1 -1
- package/Materials/Textures/Procedurals/proceduralTexture.js +20 -8
- package/Materials/Textures/Procedurals/proceduralTexture.js.map +1 -1
- package/Materials/material.d.ts +1 -1
- package/Materials/material.js.map +1 -1
- package/Materials/pushMaterial.d.ts +1 -1
- package/Materials/pushMaterial.js.map +1 -1
- package/Materials/shaderMaterial.d.ts +6 -1
- package/Materials/shaderMaterial.js +8 -1
- package/Materials/shaderMaterial.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +0 -2
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/Node/Blocks/mergeGeometryBlock.js +15 -11
- package/Meshes/Node/Blocks/mergeGeometryBlock.js.map +1 -1
- package/Meshes/abstractMesh.d.ts +6 -16
- package/Meshes/abstractMesh.js +5 -21
- package/Meshes/abstractMesh.js.map +1 -1
- package/Meshes/mesh.vertexData.js +19 -1
- package/Meshes/mesh.vertexData.js.map +1 -1
- package/Meshes/trailMesh.d.ts +40 -1
- package/Meshes/trailMesh.js +50 -21
- package/Meshes/trailMesh.js.map +1 -1
- package/Meshes/transformNode.d.ts +14 -0
- package/Meshes/transformNode.js +20 -0
- package/Meshes/transformNode.js.map +1 -1
- package/Misc/dumpTools.js +3 -2
- package/Misc/dumpTools.js.map +1 -1
- package/Particles/EmitterTypes/coneParticleEmitter.d.ts +60 -0
- package/Particles/EmitterTypes/coneParticleEmitter.js +88 -0
- package/Particles/EmitterTypes/coneParticleEmitter.js.map +1 -1
- package/Particles/IParticleSystem.d.ts +4 -2
- package/Particles/IParticleSystem.js.map +1 -1
- package/Particles/baseParticleSystem.d.ts +2 -1
- package/Particles/baseParticleSystem.js +3 -0
- package/Particles/baseParticleSystem.js.map +1 -1
- package/Particles/gpuParticleSystem.d.ts +4 -2
- package/Particles/gpuParticleSystem.js +9 -3
- package/Particles/gpuParticleSystem.js.map +1 -1
- package/Particles/particleSystem.d.ts +2 -1
- package/Particles/particleSystem.functions.d.ts +2 -1
- package/Particles/particleSystem.functions.js +4 -1
- package/Particles/particleSystem.functions.js.map +1 -1
- package/Particles/particleSystem.js +10 -2
- package/Particles/particleSystem.js.map +1 -1
- package/Particles/thinParticleSystem.d.ts +2 -1
- package/Particles/thinParticleSystem.js +3 -2
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Physics/v2/IPhysicsEnginePlugin.d.ts +3 -0
- package/Physics/v2/IPhysicsEnginePlugin.js.map +1 -1
- package/Physics/v2/Plugins/havokPlugin.d.ts +14 -0
- package/Physics/v2/Plugins/havokPlugin.js +42 -18
- package/Physics/v2/Plugins/havokPlugin.js.map +1 -1
- package/Physics/v2/physicsEngine.d.ts +14 -0
- package/Physics/v2/physicsEngine.js +20 -0
- package/Physics/v2/physicsEngine.js.map +1 -1
- package/Rendering/edgesRenderer.js +2 -1
- package/Rendering/edgesRenderer.js.map +1 -1
- package/Shaders/ShadersInclude/lineUboDeclaration.d.ts +7 -0
- package/Shaders/ShadersInclude/lineUboDeclaration.js +14 -0
- package/Shaders/ShadersInclude/lineUboDeclaration.js.map +1 -0
- package/Shaders/ShadersInclude/lineVertexDeclaration.d.ts +5 -0
- package/Shaders/ShadersInclude/lineVertexDeclaration.js +11 -0
- package/Shaders/ShadersInclude/lineVertexDeclaration.js.map +1 -0
- package/Shaders/gpuUpdateParticles.vertex.js +12 -2
- package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
- package/Shaders/line.vertex.d.ts +2 -0
- package/Shaders/line.vertex.js +5 -2
- package/Shaders/line.vertex.js.map +1 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js +11 -1
- package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
- package/XR/features/WebXRControllerMovement.d.ts +14 -1
- package/XR/features/WebXRControllerMovement.js +21 -3
- package/XR/features/WebXRControllerMovement.js.map +1 -1
- package/XR/webXRInputSource.d.ts +1 -1
- package/XR/webXRInputSource.js +3 -3
- package/XR/webXRInputSource.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gpuUpdateParticles.vertex.js","sourceRoot":"","sources":["../../../../dev/core/src/Shaders/gpuUpdateParticles.vertex.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,IAAI,GAAG,gCAAgC,CAAC;AAC9C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwPZ,CAAC;AACJ,aAAa;AACb,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AACxC,gBAAgB;AAChB,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC","sourcesContent":["// Do not edit.\nimport { ShaderStore } from \"../Engines/shaderStore\";\n\nconst name = \"gpuUpdateParticlesVertexShader\";\nconst shader = `#version 300 es\n#define PI 3.14159\nuniform float currentCount;uniform float timeDelta;uniform float stopFactor;\n#ifndef LOCAL\nuniform mat4 emitterWM;\n#endif\nuniform vec2 lifeTime;uniform vec2 emitPower;uniform vec2 sizeRange;uniform vec4 scaleRange;\n#ifndef COLORGRADIENTS\nuniform vec4 color1;uniform vec4 color2;\n#endif\nuniform vec3 gravity;uniform sampler2D randomSampler;uniform sampler2D randomSampler2;uniform vec4 angleRange;\n#ifdef BOXEMITTER\nuniform vec3 direction1;uniform vec3 direction2;uniform vec3 minEmitBox;uniform vec3 maxEmitBox;\n#endif\n#ifdef POINTEMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#endif\n#ifdef HEMISPHERICEMITTER\nuniform float radius;uniform float radiusRange;uniform float directionRandomizer;\n#endif\n#ifdef SPHEREEMITTER\nuniform float radius;uniform float radiusRange;\n#ifdef DIRECTEDSPHEREEMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\n#ifdef CYLINDEREMITTER\nuniform float radius;uniform float height;uniform float radiusRange;\n#ifdef DIRECTEDCYLINDEREMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\n#ifdef CONEEMITTER\nuniform vec2 radius;uniform float coneAngle;uniform vec2 height;uniform float directionRandomizer;\n#endif\nin vec3 position;\n#ifdef CUSTOMEMITTER\nin vec3 initialPosition;\n#endif\nin float age;in float life;in vec4 seed;in vec3 size;\n#ifndef COLORGRADIENTS\nin vec4 color;\n#endif\nin vec3 direction;\n#ifndef BILLBOARD\nin vec3 initialDirection;\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nin float angle;\n#else\nin vec2 angle;\n#endif\n#ifdef ANIMATESHEET\nin float cellIndex;\n#ifdef ANIMATESHEETRANDOMSTART\nin float cellStartOffset;\n#endif\n#endif\n#ifdef NOISE\nin vec3 noiseCoordinates1;in vec3 noiseCoordinates2;\n#endif\nout vec3 outPosition;\n#ifdef CUSTOMEMITTER\nout vec3 outInitialPosition;\n#endif\nout float outAge;out float outLife;out vec4 outSeed;out vec3 outSize;\n#ifndef COLORGRADIENTS\nout vec4 outColor;\n#endif\nout vec3 outDirection;\n#ifndef BILLBOARD\nout vec3 outInitialDirection;\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nout float outAngle;\n#else\nout vec2 outAngle;\n#endif\n#ifdef ANIMATESHEET\nout float outCellIndex;\n#ifdef ANIMATESHEETRANDOMSTART\nout float outCellStartOffset;\n#endif\n#endif\n#ifdef NOISE\nout vec3 outNoiseCoordinates1;out vec3 outNoiseCoordinates2;\n#endif\n#ifdef SIZEGRADIENTS\nuniform sampler2D sizeGradientSampler;\n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nuniform sampler2D angularSpeedGradientSampler;\n#endif \n#ifdef VELOCITYGRADIENTS\nuniform sampler2D velocityGradientSampler;\n#endif\n#ifdef LIMITVELOCITYGRADIENTS\nuniform sampler2D limitVelocityGradientSampler;uniform float limitVelocityDamping;\n#endif\n#ifdef DRAGGRADIENTS\nuniform sampler2D dragGradientSampler;\n#endif\n#ifdef NOISE\nuniform vec3 noiseStrength;uniform sampler2D noiseSampler;\n#endif\n#ifdef ANIMATESHEET\nuniform vec4 cellInfos;\n#endif\nvec3 getRandomVec3(float offset) {return texture(randomSampler2,vec2(float(gl_VertexID)*offset/currentCount,0)).rgb;}\nvec4 getRandomVec4(float offset) {return texture(randomSampler,vec2(float(gl_VertexID)*offset/currentCount,0));}\nvoid main() {float newAge=age+timeDelta; \nif (newAge>=life && stopFactor != 0.) {vec3 newPosition;vec3 newDirection;vec4 randoms=getRandomVec4(seed.x);outLife=lifeTime.x+(lifeTime.y-lifeTime.x)*randoms.r;outAge=newAge-life;outSeed=seed;\n#ifdef SIZEGRADIENTS \noutSize.x=texture(sizeGradientSampler,vec2(0,0)).r;\n#else\noutSize.x=sizeRange.x+(sizeRange.y-sizeRange.x)*randoms.g;\n#endif\noutSize.y=scaleRange.x+(scaleRange.y-scaleRange.x)*randoms.b;outSize.z=scaleRange.z+(scaleRange.w-scaleRange.z)*randoms.a; \n#ifndef COLORGRADIENTS\noutColor=color1+(color2-color1)*randoms.b;\n#endif\n#ifndef ANGULARSPEEDGRADIENTS \noutAngle.y=angleRange.x+(angleRange.y-angleRange.x)*randoms.a;outAngle.x=angleRange.z+(angleRange.w-angleRange.z)*randoms.r;\n#else\noutAngle=angleRange.z+(angleRange.w-angleRange.z)*randoms.r;\n#endif \n#ifdef POINTEMITTER\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);newPosition=vec3(0,0,0);newDirection=direction1+(direction2-direction1)*randoms3;\n#elif defined(BOXEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);newPosition=minEmitBox+(maxEmitBox-minEmitBox)*randoms2;newDirection=direction1+(direction2-direction1)*randoms3; \n#elif defined(HEMISPHERICEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float phi=2.0*PI*randoms2.x;float theta=acos(2.0*randoms2.y-1.0);float randX=cos(phi)*sin(theta);float randY=cos(theta);float randZ=sin(phi)*sin(theta);newPosition=(radius-(radius*radiusRange*randoms2.z))*vec3(randX,abs(randY),randZ);newDirection=newPosition+directionRandomizer*randoms3; \n#elif defined(SPHEREEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float phi=2.0*PI*randoms2.x;float theta=acos(2.0*randoms2.y-1.0);float randX=cos(phi)*sin(theta);float randY=cos(theta);float randZ=sin(phi)*sin(theta);newPosition=(radius-(radius*radiusRange*randoms2.z))*vec3(randX,randY,randZ);\n#ifdef DIRECTEDSPHEREEMITTER\nnewDirection=normalize(direction1+(direction2-direction1)*randoms3);\n#else\nnewDirection=normalize(newPosition+directionRandomizer*randoms3);\n#endif\n#elif defined(CYLINDEREMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float yPos=(randoms2.x-0.5)*height;float angle=randoms2.y*PI*2.;float inverseRadiusRangeSquared=((1.-radiusRange)*(1.-radiusRange));float positionRadius=radius*sqrt(inverseRadiusRangeSquared+(randoms2.z*(1.-inverseRadiusRangeSquared)));float xPos=positionRadius*cos(angle);float zPos=positionRadius*sin(angle);newPosition=vec3(xPos,yPos,zPos);\n#ifdef DIRECTEDCYLINDEREMITTER\nnewDirection=direction1+(direction2-direction1)*randoms3;\n#else\nangle=angle+((randoms3.x-0.5)*PI)*directionRandomizer;newDirection=vec3(cos(angle),(randoms3.y-0.5)*directionRandomizer,sin(angle));newDirection=normalize(newDirection);\n#endif\n#elif defined(CONEEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);float s=2.0*PI*randoms2.x;\n#ifdef CONEEMITTERSPAWNPOINT\nfloat h=0.0001;\n#else\nfloat h=randoms2.y*height.y;h=1.-h*h; \n#endif\nfloat lRadius=radius.x-radius.x*randoms2.z*radius.y;lRadius=lRadius*h;float randX=lRadius*sin(s);float randZ=lRadius*cos(s);float randY=h *height.x;newPosition=vec3(randX,randY,randZ); \nif (abs(cos(coneAngle))==1.0) {newDirection=vec3(0.,1.0,0.);} else {vec3 randoms3=getRandomVec3(seed.z);newDirection=normalize(newPosition+directionRandomizer*randoms3); }\n#elif defined(CUSTOMEMITTER)\nnewPosition=initialPosition;outInitialPosition=initialPosition;\n#else \nnewPosition=vec3(0.,0.,0.);newDirection=2.0*(getRandomVec3(seed.w)-vec3(0.5,0.5,0.5));\n#endif\nfloat power=emitPower.x+(emitPower.y-emitPower.x)*randoms.a;\n#ifdef LOCAL\noutPosition=newPosition;\n#else\noutPosition=(emitterWM*vec4(newPosition,1.)).xyz;\n#endif\n#ifdef CUSTOMEMITTER\noutDirection=direction;\n#ifndef BILLBOARD \noutInitialDirection=direction;\n#endif\n#else\n#ifdef LOCAL\nvec3 initial=newDirection;\n#else \nvec3 initial=(emitterWM*vec4(newDirection,0.)).xyz;\n#endif\noutDirection=initial*power;\n#ifndef BILLBOARD \noutInitialDirection=initial;\n#endif\n#endif\n#ifdef ANIMATESHEET \noutCellIndex=cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\noutCellStartOffset=randoms.a*outLife;\n#endif \n#endif\n#ifdef NOISE\noutNoiseCoordinates1=noiseCoordinates1;outNoiseCoordinates2=noiseCoordinates2;\n#endif\n} else {float directionScale=timeDelta;outAge=newAge;float ageGradient=newAge/life;\n#ifdef VELOCITYGRADIENTS\ndirectionScale*=texture(velocityGradientSampler,vec2(ageGradient,0)).r;\n#endif\n#ifdef DRAGGRADIENTS\ndirectionScale*=1.0-texture(dragGradientSampler,vec2(ageGradient,0)).r;\n#endif\n#if defined(CUSTOMEMITTER)\noutPosition=position+(direction-position)*ageGradient; \noutInitialPosition=initialPosition;\n#else\noutPosition=position+direction*directionScale;\n#endif\noutLife=life;outSeed=seed;\n#ifndef COLORGRADIENTS \noutColor=color;\n#endif\n#ifdef SIZEGRADIENTS\noutSize.x=texture(sizeGradientSampler,vec2(ageGradient,0)).r;outSize.yz=size.yz;\n#else\noutSize=size;\n#endif \n#ifndef BILLBOARD \noutInitialDirection=initialDirection;\n#endif\n#ifdef CUSTOMEMITTER\noutDirection=direction;\n#else\nvec3 updatedDirection=direction+gravity*timeDelta;\n#ifdef LIMITVELOCITYGRADIENTS\nfloat limitVelocity=texture(limitVelocityGradientSampler,vec2(ageGradient,0)).r;float currentVelocity=length(updatedDirection);if (currentVelocity>limitVelocity) {updatedDirection=updatedDirection*limitVelocityDamping;}\n#endif\noutDirection=updatedDirection;\n#ifdef NOISE\nfloat fetchedR=texture(noiseSampler,vec2(noiseCoordinates1.x,noiseCoordinates1.y)*vec2(0.5)+vec2(0.5)).r;float fetchedG=texture(noiseSampler,vec2(noiseCoordinates1.z,noiseCoordinates2.x)*vec2(0.5)+vec2(0.5)).r;float fetchedB=texture(noiseSampler,vec2(noiseCoordinates2.y,noiseCoordinates2.z)*vec2(0.5)+vec2(0.5)).r;vec3 force=vec3(2.*fetchedR-1.,2.*fetchedG-1.,2.*fetchedB-1.)*noiseStrength;outDirection=outDirection+force*timeDelta;outNoiseCoordinates1=noiseCoordinates1;outNoiseCoordinates2=noiseCoordinates2;\n#endif \n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nfloat angularSpeed=texture(angularSpeedGradientSampler,vec2(ageGradient,0)).r;outAngle=angle+angularSpeed*timeDelta;\n#else\noutAngle=vec2(angle.x+angle.y*timeDelta,angle.y);\n#endif\n#ifdef ANIMATESHEET \nfloat offsetAge=outAge;float dist=cellInfos.y-cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\noutCellStartOffset=cellStartOffset;offsetAge+=cellStartOffset;\n#else\nfloat cellStartOffset=0.;\n#endif \nfloat ratio=0.;if (cellInfos.w==1.0) {ratio=clamp(mod(cellStartOffset+cellInfos.z*offsetAge,life)/life,0.,1.0);}\nelse {ratio=clamp(cellStartOffset+cellInfos.z*offsetAge/life,0.,1.0);}\noutCellIndex=float(int(cellInfos.x+ratio*dist));\n#endif\n}}`;\n// Sideeffect\nShaderStore.ShadersStore[name] = shader;\n/** @internal */\nexport const gpuUpdateParticlesVertexShader = { name, shader };\n"]}
|
|
1
|
+
{"version":3,"file":"gpuUpdateParticles.vertex.js","sourceRoot":"","sources":["../../../../dev/core/src/Shaders/gpuUpdateParticles.vertex.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,IAAI,GAAG,gCAAgC,CAAC;AAC9C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkQZ,CAAC;AACJ,aAAa;AACb,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AACxC,gBAAgB;AAChB,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC","sourcesContent":["// Do not edit.\nimport { ShaderStore } from \"../Engines/shaderStore\";\n\nconst name = \"gpuUpdateParticlesVertexShader\";\nconst shader = `#version 300 es\n#define PI 3.14159\nuniform float currentCount;uniform float timeDelta;uniform float stopFactor;\n#ifndef LOCAL\nuniform mat4 emitterWM;\n#endif\nuniform vec2 lifeTime;uniform vec2 emitPower;uniform vec2 sizeRange;uniform vec4 scaleRange;\n#ifndef COLORGRADIENTS\nuniform vec4 color1;uniform vec4 color2;\n#endif\nuniform vec3 gravity;uniform sampler2D randomSampler;uniform sampler2D randomSampler2;uniform vec4 angleRange;\n#ifdef BOXEMITTER\nuniform vec3 direction1;uniform vec3 direction2;uniform vec3 minEmitBox;uniform vec3 maxEmitBox;\n#endif\n#ifdef POINTEMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#endif\n#ifdef HEMISPHERICEMITTER\nuniform float radius;uniform float radiusRange;uniform float directionRandomizer;\n#endif\n#ifdef SPHEREEMITTER\nuniform float radius;uniform float radiusRange;\n#ifdef DIRECTEDSPHEREEMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\n#ifdef CYLINDEREMITTER\nuniform float radius;uniform float height;uniform float radiusRange;\n#ifdef DIRECTEDCYLINDEREMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\n#ifdef CONEEMITTER\nuniform vec2 radius;uniform float coneAngle;uniform vec2 height;\n#ifdef DIRECTEDCONEEMITTER\nuniform vec3 direction1;uniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\nin vec3 position;\n#ifdef CUSTOMEMITTER\nin vec3 initialPosition;\n#endif\nin float age;in float life;in vec4 seed;in vec3 size;\n#ifndef COLORGRADIENTS\nin vec4 color;\n#endif\nin vec3 direction;\n#ifndef BILLBOARD\nin vec3 initialDirection;\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nin float angle;\n#else\nin vec2 angle;\n#endif\n#ifdef ANIMATESHEET\nin float cellIndex;\n#ifdef ANIMATESHEETRANDOMSTART\nin float cellStartOffset;\n#endif\n#endif\n#ifdef NOISE\nin vec3 noiseCoordinates1;in vec3 noiseCoordinates2;\n#endif\nout vec3 outPosition;\n#ifdef CUSTOMEMITTER\nout vec3 outInitialPosition;\n#endif\nout float outAge;out float outLife;out vec4 outSeed;out vec3 outSize;\n#ifndef COLORGRADIENTS\nout vec4 outColor;\n#endif\nout vec3 outDirection;\n#ifndef BILLBOARD\nout vec3 outInitialDirection;\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nout float outAngle;\n#else\nout vec2 outAngle;\n#endif\n#ifdef ANIMATESHEET\nout float outCellIndex;\n#ifdef ANIMATESHEETRANDOMSTART\nout float outCellStartOffset;\n#endif\n#endif\n#ifdef NOISE\nout vec3 outNoiseCoordinates1;out vec3 outNoiseCoordinates2;\n#endif\n#ifdef SIZEGRADIENTS\nuniform sampler2D sizeGradientSampler;\n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nuniform sampler2D angularSpeedGradientSampler;\n#endif \n#ifdef VELOCITYGRADIENTS\nuniform sampler2D velocityGradientSampler;\n#endif\n#ifdef LIMITVELOCITYGRADIENTS\nuniform sampler2D limitVelocityGradientSampler;uniform float limitVelocityDamping;\n#endif\n#ifdef DRAGGRADIENTS\nuniform sampler2D dragGradientSampler;\n#endif\n#ifdef NOISE\nuniform vec3 noiseStrength;uniform sampler2D noiseSampler;\n#endif\n#ifdef ANIMATESHEET\nuniform vec4 cellInfos;\n#endif\nvec3 getRandomVec3(float offset) {return texture(randomSampler2,vec2(float(gl_VertexID)*offset/currentCount,0)).rgb;}\nvec4 getRandomVec4(float offset) {return texture(randomSampler,vec2(float(gl_VertexID)*offset/currentCount,0));}\nvoid main() {float newAge=age+timeDelta; \nif (newAge>=life && stopFactor != 0.) {vec3 newPosition;vec3 newDirection;vec4 randoms=getRandomVec4(seed.x);outLife=lifeTime.x+(lifeTime.y-lifeTime.x)*randoms.r;outAge=newAge-life;outSeed=seed;\n#ifdef SIZEGRADIENTS \noutSize.x=texture(sizeGradientSampler,vec2(0,0)).r;\n#else\noutSize.x=sizeRange.x+(sizeRange.y-sizeRange.x)*randoms.g;\n#endif\noutSize.y=scaleRange.x+(scaleRange.y-scaleRange.x)*randoms.b;outSize.z=scaleRange.z+(scaleRange.w-scaleRange.z)*randoms.a; \n#ifndef COLORGRADIENTS\noutColor=color1+(color2-color1)*randoms.b;\n#endif\n#ifndef ANGULARSPEEDGRADIENTS \noutAngle.y=angleRange.x+(angleRange.y-angleRange.x)*randoms.a;outAngle.x=angleRange.z+(angleRange.w-angleRange.z)*randoms.r;\n#else\noutAngle=angleRange.z+(angleRange.w-angleRange.z)*randoms.r;\n#endif \n#ifdef POINTEMITTER\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);newPosition=vec3(0,0,0);newDirection=direction1+(direction2-direction1)*randoms3;\n#elif defined(BOXEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);newPosition=minEmitBox+(maxEmitBox-minEmitBox)*randoms2;newDirection=direction1+(direction2-direction1)*randoms3; \n#elif defined(HEMISPHERICEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float phi=2.0*PI*randoms2.x;float theta=acos(2.0*randoms2.y-1.0);float randX=cos(phi)*sin(theta);float randY=cos(theta);float randZ=sin(phi)*sin(theta);newPosition=(radius-(radius*radiusRange*randoms2.z))*vec3(randX,abs(randY),randZ);newDirection=newPosition+directionRandomizer*randoms3; \n#elif defined(SPHEREEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float phi=2.0*PI*randoms2.x;float theta=acos(2.0*randoms2.y-1.0);float randX=cos(phi)*sin(theta);float randY=cos(theta);float randZ=sin(phi)*sin(theta);newPosition=(radius-(radius*radiusRange*randoms2.z))*vec3(randX,randY,randZ);\n#ifdef DIRECTEDSPHEREEMITTER\nnewDirection=normalize(direction1+(direction2-direction1)*randoms3);\n#else\nnewDirection=normalize(newPosition+directionRandomizer*randoms3);\n#endif\n#elif defined(CYLINDEREMITTER)\nvec3 randoms2=getRandomVec3(seed.y);vec3 randoms3=getRandomVec3(seed.z);float yPos=(randoms2.x-0.5)*height;float angle=randoms2.y*PI*2.;float inverseRadiusRangeSquared=((1.-radiusRange)*(1.-radiusRange));float positionRadius=radius*sqrt(inverseRadiusRangeSquared+(randoms2.z*(1.-inverseRadiusRangeSquared)));float xPos=positionRadius*cos(angle);float zPos=positionRadius*sin(angle);newPosition=vec3(xPos,yPos,zPos);\n#ifdef DIRECTEDCYLINDEREMITTER\nnewDirection=direction1+(direction2-direction1)*randoms3;\n#else\nangle=angle+((randoms3.x-0.5)*PI)*directionRandomizer;newDirection=vec3(cos(angle),(randoms3.y-0.5)*directionRandomizer,sin(angle));newDirection=normalize(newDirection);\n#endif\n#elif defined(CONEEMITTER)\nvec3 randoms2=getRandomVec3(seed.y);float s=2.0*PI*randoms2.x;\n#ifdef CONEEMITTERSPAWNPOINT\nfloat h=0.0001;\n#else\nfloat h=randoms2.y*height.y;h=1.-h*h; \n#endif\nfloat lRadius=radius.x-radius.x*randoms2.z*radius.y;lRadius=lRadius*h;float randX=lRadius*sin(s);float randZ=lRadius*cos(s);float randY=h *height.x;newPosition=vec3(randX,randY,randZ); \nvec3 randoms3=getRandomVec3(seed.z);\n#ifdef DIRECTEDCONEEMITTER\nnewDirection=direction1+(direction2-direction1)*randoms3;\n#else\nif (abs(cos(coneAngle))==1.0) {newDirection=vec3(0.,1.0,0.);} else {newDirection=normalize(newPosition+directionRandomizer*randoms3); }\n#endif\n#elif defined(CUSTOMEMITTER)\nnewPosition=initialPosition;outInitialPosition=initialPosition;\n#else \nnewPosition=vec3(0.,0.,0.);newDirection=2.0*(getRandomVec3(seed.w)-vec3(0.5,0.5,0.5));\n#endif\nfloat power=emitPower.x+(emitPower.y-emitPower.x)*randoms.a;\n#ifdef LOCAL\noutPosition=newPosition;\n#else\noutPosition=(emitterWM*vec4(newPosition,1.)).xyz;\n#endif\n#ifdef CUSTOMEMITTER\noutDirection=direction;\n#ifndef BILLBOARD \noutInitialDirection=direction;\n#endif\n#else\n#ifdef LOCAL\nvec3 initial=newDirection;\n#else \nvec3 initial=(emitterWM*vec4(newDirection,0.)).xyz;\n#endif\noutDirection=initial*power;\n#ifndef BILLBOARD \noutInitialDirection=initial;\n#endif\n#endif\n#ifdef ANIMATESHEET \noutCellIndex=cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\noutCellStartOffset=randoms.a*outLife;\n#endif \n#endif\n#ifdef NOISE\noutNoiseCoordinates1=noiseCoordinates1;outNoiseCoordinates2=noiseCoordinates2;\n#endif\n} else {float directionScale=timeDelta;outAge=newAge;float ageGradient=newAge/life;\n#ifdef VELOCITYGRADIENTS\ndirectionScale*=texture(velocityGradientSampler,vec2(ageGradient,0)).r;\n#endif\n#ifdef DRAGGRADIENTS\ndirectionScale*=1.0-texture(dragGradientSampler,vec2(ageGradient,0)).r;\n#endif\n#if defined(CUSTOMEMITTER)\noutPosition=position+(direction-position)*ageGradient; \noutInitialPosition=initialPosition;\n#else\noutPosition=position+direction*directionScale;\n#endif\noutLife=life;outSeed=seed;\n#ifndef COLORGRADIENTS \noutColor=color;\n#endif\n#ifdef SIZEGRADIENTS\noutSize.x=texture(sizeGradientSampler,vec2(ageGradient,0)).r;outSize.yz=size.yz;\n#else\noutSize=size;\n#endif \n#ifndef BILLBOARD \noutInitialDirection=initialDirection;\n#endif\n#ifdef CUSTOMEMITTER\noutDirection=direction;\n#else\nvec3 updatedDirection=direction+gravity*timeDelta;\n#ifdef LIMITVELOCITYGRADIENTS\nfloat limitVelocity=texture(limitVelocityGradientSampler,vec2(ageGradient,0)).r;float currentVelocity=length(updatedDirection);if (currentVelocity>limitVelocity) {updatedDirection=updatedDirection*limitVelocityDamping;}\n#endif\noutDirection=updatedDirection;\n#ifdef NOISE\nfloat fetchedR=texture(noiseSampler,vec2(noiseCoordinates1.x,noiseCoordinates1.y)*vec2(0.5)+vec2(0.5)).r;float fetchedG=texture(noiseSampler,vec2(noiseCoordinates1.z,noiseCoordinates2.x)*vec2(0.5)+vec2(0.5)).r;float fetchedB=texture(noiseSampler,vec2(noiseCoordinates2.y,noiseCoordinates2.z)*vec2(0.5)+vec2(0.5)).r;vec3 force=vec3(2.*fetchedR-1.,2.*fetchedG-1.,2.*fetchedB-1.)*noiseStrength;outDirection=outDirection+force*timeDelta;outNoiseCoordinates1=noiseCoordinates1;outNoiseCoordinates2=noiseCoordinates2;\n#endif \n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nfloat angularSpeed=texture(angularSpeedGradientSampler,vec2(ageGradient,0)).r;outAngle=angle+angularSpeed*timeDelta;\n#else\noutAngle=vec2(angle.x+angle.y*timeDelta,angle.y);\n#endif\n#ifdef ANIMATESHEET \nfloat offsetAge=outAge;float dist=cellInfos.y-cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\noutCellStartOffset=cellStartOffset;offsetAge+=cellStartOffset;\n#else\nfloat cellStartOffset=0.;\n#endif \nfloat ratio=0.;if (cellInfos.w==1.0) {ratio=clamp(mod(cellStartOffset+cellInfos.z*offsetAge,life)/life,0.,1.0);}\nelse {ratio=clamp(cellStartOffset+cellInfos.z*offsetAge/life,0.,1.0);}\noutCellIndex=float(int(cellInfos.x+ratio*dist));\n#endif\n}}`;\n// Sideeffect\nShaderStore.ShadersStore[name] = shader;\n/** @internal */\nexport const gpuUpdateParticlesVertexShader = { name, shader };\n"]}
|
package/Shaders/line.vertex.d.ts
CHANGED
package/Shaders/line.vertex.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Do not edit.
|
|
2
2
|
import { ShaderStore } from "../Engines/shaderStore.js";
|
|
3
|
+
import "./ShadersInclude/lineVertexDeclaration.js";
|
|
4
|
+
import "./ShadersInclude/lineUboDeclaration.js";
|
|
3
5
|
import "./ShadersInclude/instancesDeclaration.js";
|
|
4
6
|
import "./ShadersInclude/clipPlaneVertexDeclaration.js";
|
|
5
7
|
import "./ShadersInclude/logDepthDeclaration.js";
|
|
@@ -7,9 +9,10 @@ import "./ShadersInclude/instancesVertex.js";
|
|
|
7
9
|
import "./ShadersInclude/clipPlaneVertex.js";
|
|
8
10
|
import "./ShadersInclude/logDepthVertex.js";
|
|
9
11
|
const name = "lineVertexShader";
|
|
10
|
-
const shader = `#include<
|
|
12
|
+
const shader = `#include<__decl__lineVertex>
|
|
13
|
+
#include<instancesDeclaration>
|
|
11
14
|
#include<clipPlaneVertexDeclaration>
|
|
12
|
-
attribute vec3 position;attribute vec4 normal;uniform
|
|
15
|
+
attribute vec3 position;attribute vec4 normal;uniform float width;uniform float aspectRatio;
|
|
13
16
|
#include<logDepthDeclaration>
|
|
14
17
|
#define CUSTOM_VERTEX_DEFINITIONS
|
|
15
18
|
void main(void) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.vertex.js","sourceRoot":"","sources":["../../../../dev/core/src/Shaders/line.vertex.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,uCAAuC,CAAC;AAC/C,OAAO,6CAA6C,CAAC;AACrD,OAAO,sCAAsC,CAAC;AAC9C,OAAO,kCAAkC,CAAC;AAC1C,OAAO,kCAAkC,CAAC;AAC1C,OAAO,iCAAiC,CAAC;AAEzC,MAAM,IAAI,GAAG,kBAAkB,CAAC;AAChC,MAAM,MAAM,GAAG
|
|
1
|
+
{"version":3,"file":"line.vertex.js","sourceRoot":"","sources":["../../../../dev/core/src/Shaders/line.vertex.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,wCAAwC,CAAC;AAChD,OAAO,qCAAqC,CAAC;AAC7C,OAAO,uCAAuC,CAAC;AAC/C,OAAO,6CAA6C,CAAC;AACrD,OAAO,sCAAsC,CAAC;AAC9C,OAAO,kCAAkC,CAAC;AAC1C,OAAO,kCAAkC,CAAC;AAC1C,OAAO,iCAAiC,CAAC;AAEzC,MAAM,IAAI,GAAG,kBAAkB,CAAC;AAChC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;EAgBb,CAAC;AACH,aAAa;AACb,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AACxC,gBAAgB;AAChB,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC","sourcesContent":["// Do not edit.\nimport { ShaderStore } from \"../Engines/shaderStore\";\nimport \"./ShadersInclude/lineVertexDeclaration\";\nimport \"./ShadersInclude/lineUboDeclaration\";\nimport \"./ShadersInclude/instancesDeclaration\";\nimport \"./ShadersInclude/clipPlaneVertexDeclaration\";\nimport \"./ShadersInclude/logDepthDeclaration\";\nimport \"./ShadersInclude/instancesVertex\";\nimport \"./ShadersInclude/clipPlaneVertex\";\nimport \"./ShadersInclude/logDepthVertex\";\n\nconst name = \"lineVertexShader\";\nconst shader = `#include<__decl__lineVertex>\n#include<instancesDeclaration>\n#include<clipPlaneVertexDeclaration>\nattribute vec3 position;attribute vec4 normal;uniform float width;uniform float aspectRatio;\n#include<logDepthDeclaration>\n#define CUSTOM_VERTEX_DEFINITIONS\nvoid main(void) {\n#define CUSTOM_VERTEX_MAIN_BEGIN\n#include<instancesVertex>\nmat4 worldViewProjection=viewProjection*finalWorld;vec4 viewPosition=worldViewProjection*vec4(position,1.0);vec4 viewPositionNext=worldViewProjection*vec4(normal.xyz,1.0);vec2 currentScreen=viewPosition.xy/viewPosition.w;vec2 nextScreen=viewPositionNext.xy/viewPositionNext.w;currentScreen.x*=aspectRatio;nextScreen.x*=aspectRatio;vec2 dir=normalize(nextScreen-currentScreen);vec2 normalDir=vec2(-dir.y,dir.x);normalDir*=width/2.0;normalDir.x/=aspectRatio;vec4 offset=vec4(normalDir*normal.w,0.0,0.0);gl_Position=viewPosition+offset;\n#if defined(CLIPPLANE) || defined(CLIPPLANE2) || defined(CLIPPLANE3) || defined(CLIPPLANE4) || defined(CLIPPLANE5) || defined(CLIPPLANE6)\nvec4 worldPos=finalWorld*vec4(position,1.0);\n#include<clipPlaneVertex>\n#endif\n#include<logDepthVertex>\n#define CUSTOM_VERTEX_MAIN_END\n}`;\n// Sideeffect\nShaderStore.ShadersStore[name] = shader;\n/** @internal */\nexport const lineVertexShader = { name, shader };\n"]}
|
|
@@ -72,8 +72,13 @@ maxEmitBox : vec3<f32>,
|
|
|
72
72
|
radius : vec2<f32>,
|
|
73
73
|
coneAngle : f32,
|
|
74
74
|
height : vec2<f32>,
|
|
75
|
+
#ifdef DIRECTEDCONEEMITTER
|
|
76
|
+
direction1 : vec3<f32>,
|
|
77
|
+
direction2 : vec3<f32>,
|
|
78
|
+
#else
|
|
75
79
|
directionRandomizer : f32,
|
|
76
80
|
#endif
|
|
81
|
+
#endif
|
|
77
82
|
#ifdef CYLINDEREMITTER
|
|
78
83
|
radius : f32,
|
|
79
84
|
height : f32,
|
|
@@ -175,7 +180,12 @@ let h : f32=0.0001;
|
|
|
175
180
|
var h : f32=randoms2.y*params.height.y;h=1.-h*h;
|
|
176
181
|
#endif
|
|
177
182
|
var lRadius : f32=params.radius.x-params.radius.x*randoms2.z*params.radius.y;lRadius=lRadius*h;let randX : f32=lRadius*sin(s);let randZ : f32=lRadius*cos(s);let randY : f32=h *params.height.x;newPosition=vec3<f32>(randX,randY,randZ);
|
|
178
|
-
|
|
183
|
+
let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);
|
|
184
|
+
#ifdef DIRECTEDCONEEMITTER
|
|
185
|
+
newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;
|
|
186
|
+
#else
|
|
187
|
+
if (abs(cos(params.coneAngle))==1.0) {newDirection=vec3<f32>(0.,1.0,0.);} else {newDirection=normalize(newPosition+params.directionRandomizer*randoms3); }
|
|
188
|
+
#endif
|
|
179
189
|
#elif defined(CUSTOMEMITTER)
|
|
180
190
|
newPosition=particlesIn.particles[index].initialPosition;particlesOut.particles[index].initialPosition=newPosition;
|
|
181
191
|
#else
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gpuUpdateParticles.compute.js","sourceRoot":"","sources":["../../../../dev/core/src/ShadersWGSL/gpuUpdateParticles.compute.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,IAAI,GAAG,iCAAiC,CAAC;AAC/C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Qd,CAAC;AACF,aAAa;AACb,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AAC5C,gBAAgB;AAChB,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC","sourcesContent":["// Do not edit.\nimport { ShaderStore } from \"../Engines/shaderStore\";\n\nconst name = \"gpuUpdateParticlesComputeShader\";\nconst shader = `struct Particle {position : vec3<f32>,\nage : f32,\nsize : vec3<f32>,\nlife : f32,\nseed : vec4<f32>,\ndirection : vec3<f32>,\ndummy0: f32,\n#ifdef CUSTOMEMITTER\ninitialPosition : vec3<f32>,\ndummy1: f32,\n#endif\n#ifndef COLORGRADIENTS\ncolor : vec4<f32>,\n#endif\n#ifndef BILLBOARD\ninitialDirection : vec3<f32>,\ndummy2: f32,\n#endif\n#ifdef NOISE\nnoiseCoordinates1 : vec3<f32>,\ndummy3: f32,\nnoiseCoordinates2 : vec3<f32>,\ndummy4: f32,\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nangle : f32,\n#else\nangle : vec2<f32>,\n#endif\n#ifdef ANIMATESHEET\ncellIndex : f32,\n#ifdef ANIMATESHEETRANDOMSTART\ncellStartOffset : f32,\n#endif\n#endif\n};struct Particles {particles : array<Particle>,};struct SimParams {currentCount : f32,\ntimeDelta : f32,\nstopFactor : f32,\nrandomTextureSize: i32,\nlifeTime : vec2<f32>,\nemitPower : vec2<f32>,\n#ifndef COLORGRADIENTS\ncolor1 : vec4<f32>,\ncolor2 : vec4<f32>,\n#endif\nsizeRange : vec2<f32>,\nscaleRange : vec4<f32>,\nangleRange : vec4<f32>,\ngravity : vec3<f32>,\n#ifdef LIMITVELOCITYGRADIENTS\nlimitVelocityDamping : f32,\n#endif\n#ifdef ANIMATESHEET\ncellInfos : vec4<f32>,\n#endif\n#ifdef NOISE\nnoiseStrength : vec3<f32>,\n#endif\n#ifndef LOCAL\nemitterWM : mat4x4<f32>,\n#endif\n#ifdef BOXEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\nminEmitBox : vec3<f32>,\nmaxEmitBox : vec3<f32>,\n#endif\n#ifdef CONEEMITTER\nradius : vec2<f32>,\nconeAngle : f32,\nheight : vec2<f32>,\ndirectionRandomizer : f32,\n#endif\n#ifdef CYLINDEREMITTER\nradius : f32,\nheight : f32,\nradiusRange : f32,\n#ifdef DIRECTEDCYLINDEREMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#else\ndirectionRandomizer : f32,\n#endif\n#endif\n#ifdef HEMISPHERICEMITTER\nradius : f32,\nradiusRange : f32,\ndirectionRandomizer : f32,\n#endif\n#ifdef POINTEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#endif\n#ifdef SPHEREEMITTER\nradius : f32,\nradiusRange : f32,\n#ifdef DIRECTEDSPHEREEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#else\ndirectionRandomizer : f32,\n#endif\n#endif\n};@binding(0) @group(0) var<uniform> params : SimParams;@binding(1) @group(0) var<storage,read> particlesIn : Particles;@binding(2) @group(0) var<storage,read_write> particlesOut : Particles;@binding(3) @group(0) var randomTexture : texture_2d<f32>;@binding(4) @group(0) var randomTexture2 : texture_2d<f32>;\n#ifdef SIZEGRADIENTS\n@binding(0) @group(1) var sizeGradientSampler : sampler;@binding(1) @group(1) var sizeGradientTexture : texture_2d<f32>;\n#endif \n#ifdef ANGULARSPEEDGRADIENTS\n@binding(2) @group(1) var angularSpeedGradientSampler : sampler;@binding(3) @group(1) var angularSpeedGradientTexture : texture_2d<f32>;\n#endif \n#ifdef VELOCITYGRADIENTS\n@binding(4) @group(1) var velocityGradientSampler : sampler;@binding(5) @group(1) var velocityGradientTexture : texture_2d<f32>;\n#endif\n#ifdef LIMITVELOCITYGRADIENTS\n@binding(6) @group(1) var limitVelocityGradientSampler : sampler;@binding(7) @group(1) var limitVelocityGradientTexture : texture_2d<f32>;\n#endif\n#ifdef DRAGGRADIENTS\n@binding(8) @group(1) var dragGradientSampler : sampler;@binding(9) @group(1) var dragGradientTexture : texture_2d<f32>;\n#endif\n#ifdef NOISE\n@binding(10) @group(1) var noiseSampler : sampler;@binding(11) @group(1) var noiseTexture : texture_2d<f32>;\n#endif\nfn getRandomVec3(offset : f32,vertexID : f32)->vec3<f32> {return textureLoad(randomTexture2,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0).rgb;}\nfn getRandomVec4(offset : f32,vertexID : f32)->vec4<f32> {return textureLoad(randomTexture,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0);}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {let index : u32=GlobalInvocationID.x;let vertexID : f32=f32(index);if (index>=u32(params.currentCount)) {return;}\nlet PI : f32=3.14159;let timeDelta : f32=params.timeDelta;let newAge : f32=particlesIn.particles[index].age+timeDelta;let life : f32=particlesIn.particles[index].life;let seed : vec4<f32>=particlesIn.particles[index].seed;let direction : vec3<f32>=particlesIn.particles[index].direction;if (newAge>=life && params.stopFactor != 0.) {var newPosition : vec3<f32>;var newDirection : vec3<f32>;let randoms : vec4<f32>=getRandomVec4(seed.x,vertexID);let outLife : f32=params.lifeTime.x+(params.lifeTime.y-params.lifeTime.x)*randoms.r;particlesOut.particles[index].life=outLife;particlesOut.particles[index].age=newAge-life;particlesOut.particles[index].seed=seed;var sizex : f32;\n#ifdef SIZEGRADIENTS \nsizex=textureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(0.,0.),0.).r;\n#else\nsizex=params.sizeRange.x+(params.sizeRange.y-params.sizeRange.x)*randoms.g;\n#endif\nparticlesOut.particles[index].size=vec3<f32>(\nsizex,\nparams.scaleRange.x+(params.scaleRange.y-params.scaleRange.x)*randoms.b,\nparams.scaleRange.z+(params.scaleRange.w-params.scaleRange.z)*randoms.a);\n#ifndef COLORGRADIENTS\nparticlesOut.particles[index].color=params.color1+(params.color2-params.color1)*randoms.b;\n#endif\n#ifndef ANGULARSPEEDGRADIENTS \nparticlesOut.particles[index].angle=vec2<f32>(\nparams.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r,\nparams.angleRange.x+(params.angleRange.y-params.angleRange.x)*randoms.a);\n#else\nparticlesOut.particles[index].angle=params.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r;\n#endif \n#if defined(POINTEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=vec3<f32>(0.,0.,0.);newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;\n#elif defined(BOXEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=params.minEmitBox+(params.maxEmitBox-params.minEmitBox)*randoms2;newDirection=params.direction1+(params.direction2-params.direction1)*randoms3; \n#elif defined(HEMISPHERICEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,abs(randY),randZ);newDirection=normalize(newPosition+params.directionRandomizer*randoms3);\n#elif defined(SPHEREEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,randY,randZ);\n#ifdef DIRECTEDSPHEREEMITTER\nnewDirection=normalize(params.direction1+(params.direction2-params.direction1)*randoms3);\n#else\nnewDirection=normalize(newPosition+params.directionRandomizer*randoms3);\n#endif\n#elif defined(CYLINDEREMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let yPos : f32=(-0.5+randoms2.x)*params.height;var angle : f32=randoms2.y*PI*2.;let inverseRadiusRangeSquared : f32=(1.-params.radiusRange)*(1.-params.radiusRange);let positionRadius : f32=params.radius*sqrt(inverseRadiusRangeSquared+randoms2.z*(1.-inverseRadiusRangeSquared));let xPos : f32=positionRadius*cos(angle);let zPos : f32=positionRadius*sin(angle);newPosition=vec3<f32>(xPos,yPos,zPos);\n#ifdef DIRECTEDCYLINDEREMITTER\nnewDirection=params.direction1+(params.direction2-params.direction1)*randoms3;\n#else\nangle=angle+(-0.5+randoms3.x)*PI*params.directionRandomizer;newDirection=vec3<f32>(cos(angle),(-0.5+randoms3.y)*params.directionRandomizer,sin(angle));newDirection=normalize(newDirection);\n#endif\n#elif defined(CONEEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let s : f32=2.0*PI*randoms2.x;\n#ifdef CONEEMITTERSPAWNPOINT\nlet h : f32=0.0001;\n#else\nvar h : f32=randoms2.y*params.height.y;h=1.-h*h; \n#endif\nvar lRadius : f32=params.radius.x-params.radius.x*randoms2.z*params.radius.y;lRadius=lRadius*h;let randX : f32=lRadius*sin(s);let randZ : f32=lRadius*cos(s);let randY : f32=h *params.height.x;newPosition=vec3<f32>(randX,randY,randZ); \nif (abs(cos(params.coneAngle))==1.0) {newDirection=vec3<f32>(0.,1.0,0.);} else {let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newDirection=normalize(newPosition+params.directionRandomizer*randoms3); }\n#elif defined(CUSTOMEMITTER)\nnewPosition=particlesIn.particles[index].initialPosition;particlesOut.particles[index].initialPosition=newPosition;\n#else \nnewPosition=vec3<f32>(0.,0.,0.);newDirection=2.0*(getRandomVec3(seed.w,vertexID)-vec3<f32>(0.5,0.5,0.5));\n#endif\nlet power : f32=params.emitPower.x+(params.emitPower.y-params.emitPower.x)*randoms.a;\n#ifdef LOCAL\nparticlesOut.particles[index].position=newPosition;\n#else\nparticlesOut.particles[index].position=(params.emitterWM*vec4<f32>(newPosition,1.)).xyz;\n#endif\n#ifdef CUSTOMEMITTER\nparticlesOut.particles[index].direction=direction;\n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=direction;\n#endif\n#else\n#ifdef LOCAL\nlet initial : vec3<f32>=newDirection;\n#else \nlet initial : vec3<f32>=(params.emitterWM*vec4<f32>(newDirection,0.)).xyz;\n#endif\nparticlesOut.particles[index].direction=initial*power;\n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=initial;\n#endif\n#endif\n#ifdef ANIMATESHEET \nparticlesOut.particles[index].cellIndex=params.cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\nparticlesOut.particles[index].cellStartOffset=randoms.a*outLife;\n#endif \n#endif\n#ifdef NOISE\nparticlesOut.particles[index].noiseCoordinates1=particlesIn.particles[index].noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=particlesIn.particles[index].noiseCoordinates2;\n#endif\n} else {var directionScale : f32=timeDelta;particlesOut.particles[index].age=newAge;let ageGradient : f32=newAge/life;\n#ifdef VELOCITYGRADIENTS\ndirectionScale=directionScale*textureSampleLevel(velocityGradientTexture,velocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;\n#endif\n#ifdef DRAGGRADIENTS\ndirectionScale=directionScale*(1.0-textureSampleLevel(dragGradientTexture,dragGradientSampler,vec2<f32>(ageGradient,0.),0.).r);\n#endif\nlet position : vec3<f32>=particlesIn.particles[index].position;\n#if defined(CUSTOMEMITTER)\nparticlesOut.particles[index].position=position+(direction-position)*ageGradient; \nparticlesOut.particles[index].initialPosition=particlesIn.particles[index].initialPosition;\n#else\nparticlesOut.particles[index].position=position+direction*directionScale;\n#endif\nparticlesOut.particles[index].life=life;particlesOut.particles[index].seed=seed;\n#ifndef COLORGRADIENTS \nparticlesOut.particles[index].color=particlesIn.particles[index].color;\n#endif\n#ifdef SIZEGRADIENTS\nparticlesOut.particles[index].size=vec3<f32>(\ntextureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(ageGradient,0.),0.).r,\nparticlesIn.particles[index].size.yz);\n#else\nparticlesOut.particles[index].size=particlesIn.particles[index].size;\n#endif \n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=particlesIn.particles[index].initialDirection;\n#endif\n#ifdef CUSTOMEMITTER\nparticlesOut.particles[index].direction=direction;\n#else\nvar updatedDirection : vec3<f32>=direction+params.gravity*timeDelta;\n#ifdef LIMITVELOCITYGRADIENTS\nlet limitVelocity : f32=textureSampleLevel(limitVelocityGradientTexture,limitVelocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;let currentVelocity : f32=length(updatedDirection);if (currentVelocity>limitVelocity) {updatedDirection=updatedDirection*params.limitVelocityDamping;}\n#endif\nparticlesOut.particles[index].direction=updatedDirection;\n#ifdef NOISE\nlet noiseCoordinates1 : vec3<f32>=particlesIn.particles[index].noiseCoordinates1;let noiseCoordinates2 : vec3<f32>=particlesIn.particles[index].noiseCoordinates2;let fetchedR : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.x,noiseCoordinates1.y)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedG : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.z,noiseCoordinates2.x)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedB : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates2.y,noiseCoordinates2.z)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let force : vec3<f32>=vec3<f32>(-1.+2.*fetchedR,-1.+2.*fetchedG,-1.+2.*fetchedB)*params.noiseStrength;particlesOut.particles[index].direction=particlesOut.particles[index].direction+force*timeDelta;particlesOut.particles[index].noiseCoordinates1=noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=noiseCoordinates2;\n#endif \n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nlet angularSpeed : f32=textureSampleLevel(angularSpeedGradientTexture,angularSpeedGradientSampler,vec2<f32>(ageGradient,0.),0.).r;particlesOut.particles[index].angle=particlesIn.particles[index].angle+angularSpeed*timeDelta;\n#else\nlet angle : vec2<f32>=particlesIn.particles[index].angle;particlesOut.particles[index].angle=vec2<f32>(angle.x+angle.y*timeDelta,angle.y);\n#endif\n#ifdef ANIMATESHEET \nvar offsetAge : f32=particlesOut.particles[index].age;let dist : f32=params.cellInfos.y-params.cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\nlet cellStartOffset : f32=particlesIn.particles[index].cellStartOffset;particlesOut.particles[index].cellStartOffset=cellStartOffset;offsetAge=offsetAge+cellStartOffset;\n#else\nlet cellStartOffset : f32=0.;\n#endif \nvar ratio : f32;if (params.cellInfos.w==1.0) {ratio=clamp(((cellStartOffset+params.cellInfos.z*offsetAge) % life)/life,0.,1.0);}\nelse {ratio=clamp((cellStartOffset+params.cellInfos.z*offsetAge)/life,0.,1.0);}\nparticlesOut.particles[index].cellIndex=f32(i32(params.cellInfos.x+ratio*dist));\n#endif\n}}\n`;\n// Sideeffect\nShaderStore.ShadersStoreWGSL[name] = shader;\n/** @internal */\nexport const gpuUpdateParticlesComputeShader = { name, shader };\n"]}
|
|
1
|
+
{"version":3,"file":"gpuUpdateParticles.compute.js","sourceRoot":"","sources":["../../../../dev/core/src/ShadersWGSL/gpuUpdateParticles.compute.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,IAAI,GAAG,iCAAiC,CAAC;AAC/C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsRd,CAAC;AACF,aAAa;AACb,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AAC5C,gBAAgB;AAChB,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC","sourcesContent":["// Do not edit.\nimport { ShaderStore } from \"../Engines/shaderStore\";\n\nconst name = \"gpuUpdateParticlesComputeShader\";\nconst shader = `struct Particle {position : vec3<f32>,\nage : f32,\nsize : vec3<f32>,\nlife : f32,\nseed : vec4<f32>,\ndirection : vec3<f32>,\ndummy0: f32,\n#ifdef CUSTOMEMITTER\ninitialPosition : vec3<f32>,\ndummy1: f32,\n#endif\n#ifndef COLORGRADIENTS\ncolor : vec4<f32>,\n#endif\n#ifndef BILLBOARD\ninitialDirection : vec3<f32>,\ndummy2: f32,\n#endif\n#ifdef NOISE\nnoiseCoordinates1 : vec3<f32>,\ndummy3: f32,\nnoiseCoordinates2 : vec3<f32>,\ndummy4: f32,\n#endif\n#ifdef ANGULARSPEEDGRADIENTS\nangle : f32,\n#else\nangle : vec2<f32>,\n#endif\n#ifdef ANIMATESHEET\ncellIndex : f32,\n#ifdef ANIMATESHEETRANDOMSTART\ncellStartOffset : f32,\n#endif\n#endif\n};struct Particles {particles : array<Particle>,};struct SimParams {currentCount : f32,\ntimeDelta : f32,\nstopFactor : f32,\nrandomTextureSize: i32,\nlifeTime : vec2<f32>,\nemitPower : vec2<f32>,\n#ifndef COLORGRADIENTS\ncolor1 : vec4<f32>,\ncolor2 : vec4<f32>,\n#endif\nsizeRange : vec2<f32>,\nscaleRange : vec4<f32>,\nangleRange : vec4<f32>,\ngravity : vec3<f32>,\n#ifdef LIMITVELOCITYGRADIENTS\nlimitVelocityDamping : f32,\n#endif\n#ifdef ANIMATESHEET\ncellInfos : vec4<f32>,\n#endif\n#ifdef NOISE\nnoiseStrength : vec3<f32>,\n#endif\n#ifndef LOCAL\nemitterWM : mat4x4<f32>,\n#endif\n#ifdef BOXEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\nminEmitBox : vec3<f32>,\nmaxEmitBox : vec3<f32>,\n#endif\n#ifdef CONEEMITTER\nradius : vec2<f32>,\nconeAngle : f32,\nheight : vec2<f32>,\n#ifdef DIRECTEDCONEEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#else\ndirectionRandomizer : f32,\n#endif\n#endif\n#ifdef CYLINDEREMITTER\nradius : f32,\nheight : f32,\nradiusRange : f32,\n#ifdef DIRECTEDCYLINDEREMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#else\ndirectionRandomizer : f32,\n#endif\n#endif\n#ifdef HEMISPHERICEMITTER\nradius : f32,\nradiusRange : f32,\ndirectionRandomizer : f32,\n#endif\n#ifdef POINTEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#endif\n#ifdef SPHEREEMITTER\nradius : f32,\nradiusRange : f32,\n#ifdef DIRECTEDSPHEREEMITTER\ndirection1 : vec3<f32>,\ndirection2 : vec3<f32>,\n#else\ndirectionRandomizer : f32,\n#endif\n#endif\n};@binding(0) @group(0) var<uniform> params : SimParams;@binding(1) @group(0) var<storage,read> particlesIn : Particles;@binding(2) @group(0) var<storage,read_write> particlesOut : Particles;@binding(3) @group(0) var randomTexture : texture_2d<f32>;@binding(4) @group(0) var randomTexture2 : texture_2d<f32>;\n#ifdef SIZEGRADIENTS\n@binding(0) @group(1) var sizeGradientSampler : sampler;@binding(1) @group(1) var sizeGradientTexture : texture_2d<f32>;\n#endif \n#ifdef ANGULARSPEEDGRADIENTS\n@binding(2) @group(1) var angularSpeedGradientSampler : sampler;@binding(3) @group(1) var angularSpeedGradientTexture : texture_2d<f32>;\n#endif \n#ifdef VELOCITYGRADIENTS\n@binding(4) @group(1) var velocityGradientSampler : sampler;@binding(5) @group(1) var velocityGradientTexture : texture_2d<f32>;\n#endif\n#ifdef LIMITVELOCITYGRADIENTS\n@binding(6) @group(1) var limitVelocityGradientSampler : sampler;@binding(7) @group(1) var limitVelocityGradientTexture : texture_2d<f32>;\n#endif\n#ifdef DRAGGRADIENTS\n@binding(8) @group(1) var dragGradientSampler : sampler;@binding(9) @group(1) var dragGradientTexture : texture_2d<f32>;\n#endif\n#ifdef NOISE\n@binding(10) @group(1) var noiseSampler : sampler;@binding(11) @group(1) var noiseTexture : texture_2d<f32>;\n#endif\nfn getRandomVec3(offset : f32,vertexID : f32)->vec3<f32> {return textureLoad(randomTexture2,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0).rgb;}\nfn getRandomVec4(offset : f32,vertexID : f32)->vec4<f32> {return textureLoad(randomTexture,vec2<i32>(i32(vertexID*offset/params.currentCount*f32(params.randomTextureSize)) % params.randomTextureSize,0),0);}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {let index : u32=GlobalInvocationID.x;let vertexID : f32=f32(index);if (index>=u32(params.currentCount)) {return;}\nlet PI : f32=3.14159;let timeDelta : f32=params.timeDelta;let newAge : f32=particlesIn.particles[index].age+timeDelta;let life : f32=particlesIn.particles[index].life;let seed : vec4<f32>=particlesIn.particles[index].seed;let direction : vec3<f32>=particlesIn.particles[index].direction;if (newAge>=life && params.stopFactor != 0.) {var newPosition : vec3<f32>;var newDirection : vec3<f32>;let randoms : vec4<f32>=getRandomVec4(seed.x,vertexID);let outLife : f32=params.lifeTime.x+(params.lifeTime.y-params.lifeTime.x)*randoms.r;particlesOut.particles[index].life=outLife;particlesOut.particles[index].age=newAge-life;particlesOut.particles[index].seed=seed;var sizex : f32;\n#ifdef SIZEGRADIENTS \nsizex=textureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(0.,0.),0.).r;\n#else\nsizex=params.sizeRange.x+(params.sizeRange.y-params.sizeRange.x)*randoms.g;\n#endif\nparticlesOut.particles[index].size=vec3<f32>(\nsizex,\nparams.scaleRange.x+(params.scaleRange.y-params.scaleRange.x)*randoms.b,\nparams.scaleRange.z+(params.scaleRange.w-params.scaleRange.z)*randoms.a);\n#ifndef COLORGRADIENTS\nparticlesOut.particles[index].color=params.color1+(params.color2-params.color1)*randoms.b;\n#endif\n#ifndef ANGULARSPEEDGRADIENTS \nparticlesOut.particles[index].angle=vec2<f32>(\nparams.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r,\nparams.angleRange.x+(params.angleRange.y-params.angleRange.x)*randoms.a);\n#else\nparticlesOut.particles[index].angle=params.angleRange.z+(params.angleRange.w-params.angleRange.z)*randoms.r;\n#endif \n#if defined(POINTEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=vec3<f32>(0.,0.,0.);newDirection=params.direction1+(params.direction2-params.direction1)*randoms3;\n#elif defined(BOXEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);newPosition=params.minEmitBox+(params.maxEmitBox-params.minEmitBox)*randoms2;newDirection=params.direction1+(params.direction2-params.direction1)*randoms3; \n#elif defined(HEMISPHERICEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,abs(randY),randZ);newDirection=normalize(newPosition+params.directionRandomizer*randoms3);\n#elif defined(SPHEREEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let phi : f32=2.0*PI*randoms2.x;let theta : f32=acos(-1.0+2.0*randoms2.y);let randX : f32=cos(phi)*sin(theta);let randY : f32=cos(theta);let randZ : f32=sin(phi)*sin(theta);newPosition=(params.radius-(params.radius*params.radiusRange*randoms2.z))*vec3<f32>(randX,randY,randZ);\n#ifdef DIRECTEDSPHEREEMITTER\nnewDirection=normalize(params.direction1+(params.direction2-params.direction1)*randoms3);\n#else\nnewDirection=normalize(newPosition+params.directionRandomizer*randoms3);\n#endif\n#elif defined(CYLINDEREMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);let yPos : f32=(-0.5+randoms2.x)*params.height;var angle : f32=randoms2.y*PI*2.;let inverseRadiusRangeSquared : f32=(1.-params.radiusRange)*(1.-params.radiusRange);let positionRadius : f32=params.radius*sqrt(inverseRadiusRangeSquared+randoms2.z*(1.-inverseRadiusRangeSquared));let xPos : f32=positionRadius*cos(angle);let zPos : f32=positionRadius*sin(angle);newPosition=vec3<f32>(xPos,yPos,zPos);\n#ifdef DIRECTEDCYLINDEREMITTER\nnewDirection=params.direction1+(params.direction2-params.direction1)*randoms3;\n#else\nangle=angle+(-0.5+randoms3.x)*PI*params.directionRandomizer;newDirection=vec3<f32>(cos(angle),(-0.5+randoms3.y)*params.directionRandomizer,sin(angle));newDirection=normalize(newDirection);\n#endif\n#elif defined(CONEEMITTER)\nlet randoms2 : vec3<f32>=getRandomVec3(seed.y,vertexID);let s : f32=2.0*PI*randoms2.x;\n#ifdef CONEEMITTERSPAWNPOINT\nlet h : f32=0.0001;\n#else\nvar h : f32=randoms2.y*params.height.y;h=1.-h*h; \n#endif\nvar lRadius : f32=params.radius.x-params.radius.x*randoms2.z*params.radius.y;lRadius=lRadius*h;let randX : f32=lRadius*sin(s);let randZ : f32=lRadius*cos(s);let randY : f32=h *params.height.x;newPosition=vec3<f32>(randX,randY,randZ); \nlet randoms3 : vec3<f32>=getRandomVec3(seed.z,vertexID);\n#ifdef DIRECTEDCONEEMITTER\nnewDirection=params.direction1+(params.direction2-params.direction1)*randoms3;\n#else\nif (abs(cos(params.coneAngle))==1.0) {newDirection=vec3<f32>(0.,1.0,0.);} else {newDirection=normalize(newPosition+params.directionRandomizer*randoms3); }\n#endif\n#elif defined(CUSTOMEMITTER)\nnewPosition=particlesIn.particles[index].initialPosition;particlesOut.particles[index].initialPosition=newPosition;\n#else \nnewPosition=vec3<f32>(0.,0.,0.);newDirection=2.0*(getRandomVec3(seed.w,vertexID)-vec3<f32>(0.5,0.5,0.5));\n#endif\nlet power : f32=params.emitPower.x+(params.emitPower.y-params.emitPower.x)*randoms.a;\n#ifdef LOCAL\nparticlesOut.particles[index].position=newPosition;\n#else\nparticlesOut.particles[index].position=(params.emitterWM*vec4<f32>(newPosition,1.)).xyz;\n#endif\n#ifdef CUSTOMEMITTER\nparticlesOut.particles[index].direction=direction;\n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=direction;\n#endif\n#else\n#ifdef LOCAL\nlet initial : vec3<f32>=newDirection;\n#else \nlet initial : vec3<f32>=(params.emitterWM*vec4<f32>(newDirection,0.)).xyz;\n#endif\nparticlesOut.particles[index].direction=initial*power;\n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=initial;\n#endif\n#endif\n#ifdef ANIMATESHEET \nparticlesOut.particles[index].cellIndex=params.cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\nparticlesOut.particles[index].cellStartOffset=randoms.a*outLife;\n#endif \n#endif\n#ifdef NOISE\nparticlesOut.particles[index].noiseCoordinates1=particlesIn.particles[index].noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=particlesIn.particles[index].noiseCoordinates2;\n#endif\n} else {var directionScale : f32=timeDelta;particlesOut.particles[index].age=newAge;let ageGradient : f32=newAge/life;\n#ifdef VELOCITYGRADIENTS\ndirectionScale=directionScale*textureSampleLevel(velocityGradientTexture,velocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;\n#endif\n#ifdef DRAGGRADIENTS\ndirectionScale=directionScale*(1.0-textureSampleLevel(dragGradientTexture,dragGradientSampler,vec2<f32>(ageGradient,0.),0.).r);\n#endif\nlet position : vec3<f32>=particlesIn.particles[index].position;\n#if defined(CUSTOMEMITTER)\nparticlesOut.particles[index].position=position+(direction-position)*ageGradient; \nparticlesOut.particles[index].initialPosition=particlesIn.particles[index].initialPosition;\n#else\nparticlesOut.particles[index].position=position+direction*directionScale;\n#endif\nparticlesOut.particles[index].life=life;particlesOut.particles[index].seed=seed;\n#ifndef COLORGRADIENTS \nparticlesOut.particles[index].color=particlesIn.particles[index].color;\n#endif\n#ifdef SIZEGRADIENTS\nparticlesOut.particles[index].size=vec3<f32>(\ntextureSampleLevel(sizeGradientTexture,sizeGradientSampler,vec2<f32>(ageGradient,0.),0.).r,\nparticlesIn.particles[index].size.yz);\n#else\nparticlesOut.particles[index].size=particlesIn.particles[index].size;\n#endif \n#ifndef BILLBOARD \nparticlesOut.particles[index].initialDirection=particlesIn.particles[index].initialDirection;\n#endif\n#ifdef CUSTOMEMITTER\nparticlesOut.particles[index].direction=direction;\n#else\nvar updatedDirection : vec3<f32>=direction+params.gravity*timeDelta;\n#ifdef LIMITVELOCITYGRADIENTS\nlet limitVelocity : f32=textureSampleLevel(limitVelocityGradientTexture,limitVelocityGradientSampler,vec2<f32>(ageGradient,0.),0.).r;let currentVelocity : f32=length(updatedDirection);if (currentVelocity>limitVelocity) {updatedDirection=updatedDirection*params.limitVelocityDamping;}\n#endif\nparticlesOut.particles[index].direction=updatedDirection;\n#ifdef NOISE\nlet noiseCoordinates1 : vec3<f32>=particlesIn.particles[index].noiseCoordinates1;let noiseCoordinates2 : vec3<f32>=particlesIn.particles[index].noiseCoordinates2;let fetchedR : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.x,noiseCoordinates1.y)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedG : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates1.z,noiseCoordinates2.x)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let fetchedB : f32=textureSampleLevel(noiseTexture,noiseSampler,vec2<f32>(noiseCoordinates2.y,noiseCoordinates2.z)*vec2<f32>(0.5,0.5)+vec2<f32>(0.5,0.5),0.).r;let force : vec3<f32>=vec3<f32>(-1.+2.*fetchedR,-1.+2.*fetchedG,-1.+2.*fetchedB)*params.noiseStrength;particlesOut.particles[index].direction=particlesOut.particles[index].direction+force*timeDelta;particlesOut.particles[index].noiseCoordinates1=noiseCoordinates1;particlesOut.particles[index].noiseCoordinates2=noiseCoordinates2;\n#endif \n#endif \n#ifdef ANGULARSPEEDGRADIENTS\nlet angularSpeed : f32=textureSampleLevel(angularSpeedGradientTexture,angularSpeedGradientSampler,vec2<f32>(ageGradient,0.),0.).r;particlesOut.particles[index].angle=particlesIn.particles[index].angle+angularSpeed*timeDelta;\n#else\nlet angle : vec2<f32>=particlesIn.particles[index].angle;particlesOut.particles[index].angle=vec2<f32>(angle.x+angle.y*timeDelta,angle.y);\n#endif\n#ifdef ANIMATESHEET \nvar offsetAge : f32=particlesOut.particles[index].age;let dist : f32=params.cellInfos.y-params.cellInfos.x;\n#ifdef ANIMATESHEETRANDOMSTART\nlet cellStartOffset : f32=particlesIn.particles[index].cellStartOffset;particlesOut.particles[index].cellStartOffset=cellStartOffset;offsetAge=offsetAge+cellStartOffset;\n#else\nlet cellStartOffset : f32=0.;\n#endif \nvar ratio : f32;if (params.cellInfos.w==1.0) {ratio=clamp(((cellStartOffset+params.cellInfos.z*offsetAge) % life)/life,0.,1.0);}\nelse {ratio=clamp((cellStartOffset+params.cellInfos.z*offsetAge)/life,0.,1.0);}\nparticlesOut.particles[index].cellIndex=f32(i32(params.cellInfos.x+ratio*dist));\n#endif\n}}\n`;\n// Sideeffect\nShaderStore.ShadersStoreWGSL[name] = shader;\n/** @internal */\nexport const gpuUpdateParticlesComputeShader = { name, shader };\n"]}
|
|
@@ -47,6 +47,17 @@ export interface IWebXRControllerMovementOptions {
|
|
|
47
47
|
* Babylon XR Input class for controller
|
|
48
48
|
*/
|
|
49
49
|
xrInput: WebXRInput;
|
|
50
|
+
/**
|
|
51
|
+
* If movement orientation should follow controller orientation instead of viewer pose.
|
|
52
|
+
* Make sure to set movementOrientationFollowsViewerPose to false, otherwise it will be ignored.
|
|
53
|
+
*/
|
|
54
|
+
movementOrientationFollowsController: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* If orientation follows the controller, this is the preferred handedness to use for forward movement.
|
|
57
|
+
* If not set (or handedness not found), the handedness will be selected by the controller triggering the movement.
|
|
58
|
+
* Note that this only works if movementOrientationFollowsController is true.
|
|
59
|
+
*/
|
|
60
|
+
orientationPreferredHandedness?: XRHandedness;
|
|
50
61
|
}
|
|
51
62
|
/**
|
|
52
63
|
* Feature context is used in handlers and on each XR frame to control the camera movement/direction.
|
|
@@ -54,6 +65,8 @@ export interface IWebXRControllerMovementOptions {
|
|
|
54
65
|
export type WebXRControllerMovementFeatureContext = {
|
|
55
66
|
movementEnabled: boolean;
|
|
56
67
|
movementOrientationFollowsViewerPose: boolean;
|
|
68
|
+
movementOrientationFollowsController: boolean;
|
|
69
|
+
orientationPreferredHandedness?: XRHandedness;
|
|
57
70
|
movementSpeed: number;
|
|
58
71
|
movementThreshold: number;
|
|
59
72
|
rotationEnabled: boolean;
|
|
@@ -98,7 +111,7 @@ export type WebXRControllerMovementRegistrationConfiguration = {
|
|
|
98
111
|
/**
|
|
99
112
|
* Called when the button state changes.
|
|
100
113
|
*/
|
|
101
|
-
|
|
114
|
+
buttonChangedHandler: (pressed: IWebXRMotionControllerComponentChangesValues<boolean>, movementState: WebXRControllerMovementState, featureContext: WebXRControllerMovementFeatureContext, xrInput: WebXRInput) => void;
|
|
102
115
|
});
|
|
103
116
|
/**
|
|
104
117
|
* This is a movement feature to be used with WebXR-enabled motion controllers.
|
|
@@ -177,10 +177,10 @@ export class WebXRControllerMovement extends WebXRAbstractFeature {
|
|
|
177
177
|
registration.axisChangedHandler(axesData, this._movementState, this._featureContext, this._xrInput);
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
-
if ("
|
|
181
|
-
registeredComponent.onButtonChangedObserver = component.onButtonStateChangedObservable.add(() => {
|
|
180
|
+
if ("buttonChangedHandler" in registration) {
|
|
181
|
+
registeredComponent.onButtonChangedObserver = component.onButtonStateChangedObservable.add((component) => {
|
|
182
182
|
if (component.changes.pressed) {
|
|
183
|
-
registration.
|
|
183
|
+
registration.buttonChangedHandler(component.changes.pressed, this._movementState, this._featureContext, this._xrInput);
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
186
|
}
|
|
@@ -211,6 +211,8 @@ export class WebXRControllerMovement extends WebXRAbstractFeature {
|
|
|
211
211
|
this._featureContext = {
|
|
212
212
|
movementEnabled: options.movementEnabled || true,
|
|
213
213
|
movementOrientationFollowsViewerPose: options.movementOrientationFollowsViewerPose ?? true,
|
|
214
|
+
movementOrientationFollowsController: options.movementOrientationFollowsController ?? false,
|
|
215
|
+
orientationPreferredHandedness: options.orientationPreferredHandedness,
|
|
214
216
|
movementSpeed: options.movementSpeed ?? 1,
|
|
215
217
|
movementThreshold: options.movementThreshold ?? 0.25,
|
|
216
218
|
rotationEnabled: options.rotationEnabled ?? true,
|
|
@@ -264,6 +266,15 @@ export class WebXRControllerMovement extends WebXRAbstractFeature {
|
|
|
264
266
|
Quaternion.RotationYawPitchRollToRef(rotationY, 0, 0, this._tempCacheQuaternion);
|
|
265
267
|
this._xrInput.xrCamera.rotationQuaternion.multiplyToRef(this._tempCacheQuaternion, this._movementDirection);
|
|
266
268
|
}
|
|
269
|
+
else if (this._featureContext.movementOrientationFollowsController) {
|
|
270
|
+
this._xrInput.xrCamera.cameraRotation.y += rotationY;
|
|
271
|
+
// get the correct controller
|
|
272
|
+
const handedness = this._featureContext.orientationPreferredHandedness || "right";
|
|
273
|
+
const key = Object.keys(this._controllers).find((key) => this._controllers[key]?.xrController?.inputSource.handedness === handedness) || Object.keys(this._controllers)[0];
|
|
274
|
+
const controller = this._controllers[key];
|
|
275
|
+
Quaternion.RotationYawPitchRollToRef(rotationY, 0, 0, this._tempCacheQuaternion);
|
|
276
|
+
(controller?.xrController.pointer.rotationQuaternion || Quaternion.Identity()).multiplyToRef(this._tempCacheQuaternion, this._movementDirection);
|
|
277
|
+
}
|
|
267
278
|
else {
|
|
268
279
|
// movement orientation direction does not affect camera. We use rotation speed multiplier
|
|
269
280
|
// otherwise need to implement inertia and constraints for same feel as TargetCamera.
|
|
@@ -274,6 +285,13 @@ export class WebXRControllerMovement extends WebXRAbstractFeature {
|
|
|
274
285
|
else if (this._featureContext.movementOrientationFollowsViewerPose) {
|
|
275
286
|
this._movementDirection.copyFrom(this._xrInput.xrCamera.rotationQuaternion);
|
|
276
287
|
}
|
|
288
|
+
else if (this._featureContext.movementOrientationFollowsController) {
|
|
289
|
+
// get the correct controller
|
|
290
|
+
const handedness = this._featureContext.orientationPreferredHandedness || "right";
|
|
291
|
+
const key = Object.keys(this._controllers).find((key) => this._controllers[key]?.xrController.inputSource.handedness === handedness) || Object.keys(this._controllers)[0];
|
|
292
|
+
const controller = this._controllers[key];
|
|
293
|
+
this._movementDirection.copyFrom(controller?.xrController.pointer.rotationQuaternion || Quaternion.Identity());
|
|
294
|
+
}
|
|
277
295
|
if ((this._movementState.moveX || this._movementState.moveY) && this._featureContext.movementEnabled) {
|
|
278
296
|
Matrix.FromQuaternionToRef(this._movementDirection, this._tmpRotationMatrix);
|
|
279
297
|
this._tmpTranslationDirection.set(this._movementState.moveX, 0, this._movementState.moveY * (this._xrSessionManager.scene.useRightHandedSystem ? 1.0 : -1.0));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebXRControllerMovement.js","sourceRoot":"","sources":["../../../../../dev/core/src/XR/features/WebXRControllerMovement.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRFeaturesManager, WebXRFeatureName } from \"../webXRFeaturesManager\";\r\nimport type { Observer } from \"../../Misc/observable\";\r\nimport type { WebXRSessionManager } from \"../webXRSessionManager\";\r\nimport type { Nullable } from \"../../types\";\r\nimport type { WebXRInput } from \"../webXRInput\";\r\nimport type { WebXRInputSource } from \"../webXRInputSource\";\r\nimport type { IWebXRMotionControllerAxesValue, IWebXRMotionControllerComponentChangesValues } from \"../motionController/webXRControllerComponent\";\r\nimport { WebXRControllerComponent } from \"../motionController/webXRControllerComponent\";\r\nimport { Matrix, Quaternion, Vector3 } from \"../../Maths/math.vector\";\r\nimport { WebXRAbstractFeature } from \"./WebXRAbstractFeature\";\r\nimport type { MotionControllerComponentType } from \"../motionController/webXRAbstractMotionController\";\r\nimport { Tools } from \"../../Misc/tools\";\r\n\r\n/**\r\n * The options container for the controller movement module\r\n */\r\nexport interface IWebXRControllerMovementOptions {\r\n /**\r\n * Override default behaviour and provide your own movement controls\r\n */\r\n customRegistrationConfigurations?: WebXRControllerMovementRegistrationConfiguration[];\r\n /**\r\n * Is movement enabled\r\n */\r\n movementEnabled?: boolean;\r\n /**\r\n * Camera direction follows view pose and movement by default will move independently of the viewer's pose.\r\n */\r\n movementOrientationFollowsViewerPose: boolean;\r\n /**\r\n * Movement speed factor (default is 1.0)\r\n */\r\n movementSpeed?: number;\r\n /**\r\n * Minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n */\r\n movementThreshold?: number;\r\n /**\r\n * Is rotation enabled\r\n */\r\n rotationEnabled?: boolean;\r\n /**\r\n * Minimum threshold the controller's thumstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n */\r\n rotationThreshold?: number;\r\n /**\r\n * Movement speed factor (default is 1.0)\r\n */\r\n rotationSpeed?: number;\r\n /**\r\n * Babylon XR Input class for controller\r\n */\r\n xrInput: WebXRInput;\r\n}\r\n\r\n/**\r\n * Feature context is used in handlers and on each XR frame to control the camera movement/direction.\r\n */\r\nexport type WebXRControllerMovementFeatureContext = {\r\n movementEnabled: boolean;\r\n movementOrientationFollowsViewerPose: boolean;\r\n movementSpeed: number;\r\n movementThreshold: number;\r\n rotationEnabled: boolean;\r\n rotationSpeed: number;\r\n rotationThreshold: number;\r\n};\r\n\r\n/**\r\n * Current state of Movements shared across components and handlers.\r\n */\r\nexport type WebXRControllerMovementState = {\r\n moveX: number;\r\n moveY: number;\r\n rotateX: number;\r\n rotateY: number;\r\n};\r\n\r\n/**\r\n * Button of Axis Handler must be specified.\r\n */\r\nexport type WebXRControllerMovementRegistrationConfiguration = {\r\n /**\r\n * handlers are filtered to these types only\r\n */\r\n allowedComponentTypes?: MotionControllerComponentType[];\r\n /**\r\n * For registering movement to specific hand only. Useful if your app has a \"main hand\" and \"off hand\" for determining the functionality of a controller.\r\n */\r\n forceHandedness?: XRHandedness;\r\n /**\r\n * For main component only (useful for buttons and may not trigger axis changes).\r\n */\r\n mainComponentOnly?: boolean;\r\n /**\r\n * Additional predicate to apply to controllers to restrict a handler being added.\r\n */\r\n componentSelectionPredicate?: (xrController: WebXRInputSource) => Nullable<WebXRControllerComponent>;\r\n} & (\r\n | {\r\n /**\r\n * Called when axis changes occur.\r\n */\r\n axisChangedHandler: (\r\n axes: IWebXRMotionControllerAxesValue,\r\n movementState: WebXRControllerMovementState,\r\n featureContext: WebXRControllerMovementFeatureContext,\r\n xrInput: WebXRInput\r\n ) => void;\r\n }\r\n | {\r\n /**\r\n * Called when the button state changes.\r\n */\r\n buttonChangedhandler: (\r\n pressed: IWebXRMotionControllerComponentChangesValues<boolean>,\r\n movementState: WebXRControllerMovementState,\r\n featureContext: WebXRControllerMovementFeatureContext,\r\n xrInput: WebXRInput\r\n ) => void;\r\n }\r\n);\r\n\r\ntype RegisteredComponent = {\r\n registrationConfiguration: WebXRControllerMovementRegistrationConfiguration;\r\n component: WebXRControllerComponent;\r\n onAxisChangedObserver?: Nullable<Observer<IWebXRMotionControllerAxesValue>>;\r\n onButtonChangedObserver?: Nullable<Observer<WebXRControllerComponent>>;\r\n};\r\n\r\n/**\r\n * This is a movement feature to be used with WebXR-enabled motion controllers.\r\n * When enabled and attached, the feature will allow a user to move around and rotate in the scene using\r\n * the input of the attached controllers.\r\n */\r\nexport class WebXRControllerMovement extends WebXRAbstractFeature {\r\n private _controllers: {\r\n [controllerUniqueId: string]: {\r\n xrController: WebXRInputSource;\r\n registeredComponents: RegisteredComponent[];\r\n };\r\n } = {};\r\n\r\n private _currentRegistrationConfigurations: WebXRControllerMovementRegistrationConfiguration[] = [];\r\n // Feature configuration is syncronized - this is passed to all handlers (reduce GC pressure).\r\n private _featureContext: WebXRControllerMovementFeatureContext;\r\n // forward direction for movement, which may differ from viewer pose.\r\n private _movementDirection: Quaternion = new Quaternion();\r\n private _movementState: WebXRControllerMovementState;\r\n private _xrInput: WebXRInput;\r\n\r\n // unused\r\n private _tmpRotationMatrix: Matrix = Matrix.Identity();\r\n private _tmpTranslationDirection: Vector3 = new Vector3();\r\n private _tmpMovementTranslation: Vector3 = new Vector3();\r\n private _tempCacheQuaternion: Quaternion = new Quaternion();\r\n\r\n /**\r\n * The module's name\r\n */\r\n public static readonly Name = WebXRFeatureName.MOVEMENT;\r\n\r\n /**\r\n * Standard controller configurations.\r\n */\r\n public static readonly REGISTRATIONS: { [key: string]: WebXRControllerMovementRegistrationConfiguration[] } = {\r\n default: [\r\n {\r\n allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE],\r\n forceHandedness: \"left\",\r\n axisChangedHandler: (axes: IWebXRMotionControllerAxesValue, movementState: WebXRControllerMovementState, featureContext: WebXRControllerMovementFeatureContext) => {\r\n movementState.rotateX = Math.abs(axes.x) > featureContext.rotationThreshold ? axes.x : 0;\r\n movementState.rotateY = Math.abs(axes.y) > featureContext.rotationThreshold ? axes.y : 0;\r\n },\r\n },\r\n {\r\n allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE],\r\n forceHandedness: \"right\",\r\n axisChangedHandler: (axes: IWebXRMotionControllerAxesValue, movementState: WebXRControllerMovementState, featureContext: WebXRControllerMovementFeatureContext) => {\r\n movementState.moveX = Math.abs(axes.x) > featureContext.movementThreshold ? axes.x : 0;\r\n movementState.moveY = Math.abs(axes.y) > featureContext.movementThreshold ? axes.y : 0;\r\n },\r\n },\r\n ],\r\n };\r\n\r\n /**\r\n * The (Babylon) version of this module.\r\n * This is an integer representing the implementation version.\r\n * This number does not correspond to the webxr specs version\r\n */\r\n public static readonly Version = 1;\r\n\r\n /**\r\n * Current movement direction. Will be null before XR Frames have been processed.\r\n */\r\n public get movementDirection(): Quaternion {\r\n return this._movementDirection;\r\n }\r\n\r\n /**\r\n * Is movement enabled\r\n */\r\n public get movementEnabled(): boolean {\r\n return this._featureContext.movementEnabled;\r\n }\r\n\r\n /**\r\n * Sets whether movement is enabled or not\r\n * @param enabled is movement enabled\r\n */\r\n public set movementEnabled(enabled: boolean) {\r\n this._featureContext.movementEnabled = enabled;\r\n }\r\n\r\n /**\r\n * If movement follows viewer pose\r\n */\r\n public get movementOrientationFollowsViewerPose(): boolean {\r\n return this._featureContext.movementOrientationFollowsViewerPose;\r\n }\r\n\r\n /**\r\n * Sets whether movement follows viewer pose\r\n * @param followsPose is movement should follow viewer pose\r\n */\r\n public set movementOrientationFollowsViewerPose(followsPose: boolean) {\r\n this._featureContext.movementOrientationFollowsViewerPose = followsPose;\r\n }\r\n\r\n /**\r\n * Gets movement speed\r\n */\r\n public get movementSpeed(): number {\r\n return this._featureContext.movementSpeed;\r\n }\r\n\r\n /**\r\n * Sets movement speed\r\n * @param movementSpeed movement speed\r\n */\r\n public set movementSpeed(movementSpeed: number) {\r\n this._featureContext.movementSpeed = movementSpeed;\r\n }\r\n\r\n /**\r\n * Gets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n */\r\n public get movementThreshold(): number {\r\n return this._featureContext.movementThreshold;\r\n }\r\n\r\n /**\r\n * Sets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n * @param movementThreshold new threshold\r\n */\r\n public set movementThreshold(movementThreshold: number) {\r\n this._featureContext.movementThreshold = movementThreshold;\r\n }\r\n\r\n /**\r\n * Is rotation enabled\r\n */\r\n public get rotationEnabled(): boolean {\r\n return this._featureContext.rotationEnabled;\r\n }\r\n\r\n /**\r\n * Sets whether rotation is enabled or not\r\n * @param enabled is rotation enabled\r\n */\r\n public set rotationEnabled(enabled: boolean) {\r\n this._featureContext.rotationEnabled = enabled;\r\n }\r\n\r\n /**\r\n * Gets rotation speed factor\r\n */\r\n public get rotationSpeed(): number {\r\n return this._featureContext.rotationSpeed;\r\n }\r\n\r\n /**\r\n * Sets rotation speed factor (1.0 is default)\r\n * @param rotationSpeed new rotation speed factor\r\n */\r\n public set rotationSpeed(rotationSpeed: number) {\r\n this._featureContext.rotationSpeed = rotationSpeed;\r\n }\r\n\r\n /**\r\n * Gets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n */\r\n public get rotationThreshold(): number {\r\n return this._featureContext.rotationThreshold;\r\n }\r\n\r\n /**\r\n * Sets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n * @param threshold new threshold\r\n */\r\n public set rotationThreshold(threshold: number) {\r\n this._featureContext.rotationThreshold = threshold;\r\n }\r\n /**\r\n * constructs a new movement controller system\r\n * @param _xrSessionManager an instance of WebXRSessionManager\r\n * @param options configuration object for this feature\r\n */\r\n constructor(_xrSessionManager: WebXRSessionManager, options: IWebXRControllerMovementOptions) {\r\n super(_xrSessionManager);\r\n\r\n if (!options || options.xrInput === undefined) {\r\n Tools.Error('WebXRControllerMovement feature requires \"xrInput\" option.');\r\n return;\r\n }\r\n\r\n if (Array.isArray(options.customRegistrationConfigurations)) {\r\n this._currentRegistrationConfigurations = options.customRegistrationConfigurations;\r\n } else {\r\n this._currentRegistrationConfigurations = WebXRControllerMovement.REGISTRATIONS.default;\r\n }\r\n\r\n // synchronized from feature setter properties\r\n this._featureContext = {\r\n movementEnabled: options.movementEnabled || true,\r\n movementOrientationFollowsViewerPose: options.movementOrientationFollowsViewerPose ?? true,\r\n movementSpeed: options.movementSpeed ?? 1,\r\n movementThreshold: options.movementThreshold ?? 0.25,\r\n rotationEnabled: options.rotationEnabled ?? true,\r\n rotationSpeed: options.rotationSpeed ?? 1.0,\r\n rotationThreshold: options.rotationThreshold ?? 0.25,\r\n };\r\n\r\n this._movementState = {\r\n moveX: 0,\r\n moveY: 0,\r\n rotateX: 0,\r\n rotateY: 0,\r\n };\r\n\r\n this._xrInput = options.xrInput;\r\n }\r\n\r\n public override attach(): boolean {\r\n if (!super.attach()) {\r\n return false;\r\n }\r\n\r\n this._xrInput.controllers.forEach(this._attachController);\r\n this._addNewAttachObserver(this._xrInput.onControllerAddedObservable, this._attachController);\r\n this._addNewAttachObserver(this._xrInput.onControllerRemovedObservable, (controller: WebXRInputSource) => {\r\n // REMOVE the controller\r\n this._detachController(controller.uniqueId);\r\n });\r\n\r\n return true;\r\n }\r\n\r\n public override detach(): boolean {\r\n if (!super.detach()) {\r\n return false;\r\n }\r\n\r\n Object.keys(this._controllers).forEach((controllerId) => {\r\n this._detachController(controllerId);\r\n });\r\n\r\n this._controllers = {};\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Occurs on every XR frame.\r\n * @param _xrFrame\r\n */\r\n protected _onXRFrame(_xrFrame: XRFrame) {\r\n if (!this.attached) {\r\n return;\r\n }\r\n\r\n if (this._movementState.rotateX !== 0 && this._featureContext.rotationEnabled) {\r\n // smooth rotation\r\n const deltaMillis = this._xrSessionManager.scene.getEngine().getDeltaTime();\r\n const rotationY = deltaMillis * 0.001 * this._featureContext.rotationSpeed * this._movementState.rotateX * (this._xrSessionManager.scene.useRightHandedSystem ? -1 : 1);\r\n\r\n if (this._featureContext.movementOrientationFollowsViewerPose) {\r\n this._xrInput.xrCamera.cameraRotation.y += rotationY;\r\n Quaternion.RotationYawPitchRollToRef(rotationY, 0, 0, this._tempCacheQuaternion);\r\n this._xrInput.xrCamera.rotationQuaternion.multiplyToRef(this._tempCacheQuaternion, this._movementDirection);\r\n } else {\r\n // movement orientation direction does not affect camera. We use rotation speed multiplier\r\n // otherwise need to implement inertia and constraints for same feel as TargetCamera.\r\n\r\n Quaternion.RotationYawPitchRollToRef(rotationY * 3.0, 0, 0, this._tempCacheQuaternion);\r\n this._movementDirection.multiplyInPlace(this._tempCacheQuaternion);\r\n }\r\n } else if (this._featureContext.movementOrientationFollowsViewerPose) {\r\n this._movementDirection.copyFrom(this._xrInput.xrCamera.rotationQuaternion);\r\n }\r\n\r\n if ((this._movementState.moveX || this._movementState.moveY) && this._featureContext.movementEnabled) {\r\n Matrix.FromQuaternionToRef(this._movementDirection, this._tmpRotationMatrix);\r\n this._tmpTranslationDirection.set(this._movementState.moveX, 0, this._movementState.moveY * (this._xrSessionManager.scene.useRightHandedSystem ? 1.0 : -1.0));\r\n // move according to forward direction based on camera speed\r\n Vector3.TransformCoordinatesToRef(this._tmpTranslationDirection, this._tmpRotationMatrix, this._tmpMovementTranslation);\r\n this._tmpMovementTranslation.scaleInPlace(this._xrInput.xrCamera._computeLocalCameraSpeed() * this._featureContext.movementSpeed);\r\n\r\n this._xrInput.xrCamera.cameraDirection.addInPlace(this._tmpMovementTranslation);\r\n }\r\n }\r\n\r\n private _attachController = (xrController: WebXRInputSource) => {\r\n if (this._controllers[xrController.uniqueId]) {\r\n // already attached\r\n return;\r\n }\r\n\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n registeredComponents: [],\r\n };\r\n const controllerData = this._controllers[xrController.uniqueId];\r\n\r\n // movement controller only available to gamepad-enabled input sources.\r\n if (controllerData.xrController.inputSource.targetRayMode === \"tracked-pointer\" && controllerData.xrController.inputSource.gamepad) {\r\n // motion controller support\r\n const initController = () => {\r\n if (xrController.motionController) {\r\n for (const registration of this._currentRegistrationConfigurations) {\r\n let component: Nullable<WebXRControllerComponent> = null;\r\n\r\n if (registration.allowedComponentTypes) {\r\n for (const componentType of registration.allowedComponentTypes) {\r\n const componentOfType = xrController.motionController.getComponentOfType(componentType);\r\n if (componentOfType !== null) {\r\n component = componentOfType;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (registration.mainComponentOnly) {\r\n const mainComponent = xrController.motionController.getMainComponent();\r\n if (mainComponent === null) {\r\n continue;\r\n }\r\n component = mainComponent;\r\n }\r\n\r\n if (typeof registration.componentSelectionPredicate === \"function\") {\r\n // if does not match we do want to ignore a previously found component\r\n component = registration.componentSelectionPredicate(xrController);\r\n }\r\n\r\n if (component && registration.forceHandedness) {\r\n if (xrController.inputSource.handedness !== registration.forceHandedness) {\r\n continue; // do not register\r\n }\r\n }\r\n\r\n if (component === null) {\r\n continue; // do not register\r\n }\r\n\r\n const registeredComponent: RegisteredComponent = {\r\n registrationConfiguration: registration,\r\n component,\r\n };\r\n controllerData.registeredComponents.push(registeredComponent);\r\n\r\n if (\"axisChangedHandler\" in registration) {\r\n registeredComponent.onAxisChangedObserver = component.onAxisValueChangedObservable.add((axesData) => {\r\n registration.axisChangedHandler(axesData, this._movementState, this._featureContext, this._xrInput);\r\n });\r\n }\r\n\r\n if (\"buttonChangedhandler\" in registration) {\r\n registeredComponent.onButtonChangedObserver = component.onButtonStateChangedObservable.add(() => {\r\n if (component!.changes.pressed) {\r\n registration.buttonChangedhandler(component!.changes.pressed, this._movementState, this._featureContext, this._xrInput);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n };\r\n\r\n if (xrController.motionController) {\r\n initController();\r\n } else {\r\n xrController.onMotionControllerInitObservable.addOnce(() => {\r\n initController();\r\n });\r\n }\r\n }\r\n };\r\n\r\n private _detachController(xrControllerUniqueId: string) {\r\n const controllerData = this._controllers[xrControllerUniqueId];\r\n if (!controllerData) {\r\n return;\r\n }\r\n\r\n for (const registeredComponent of controllerData.registeredComponents) {\r\n if (registeredComponent.onAxisChangedObserver) {\r\n registeredComponent.component.onAxisValueChangedObservable.remove(registeredComponent.onAxisChangedObserver);\r\n }\r\n if (registeredComponent.onButtonChangedObserver) {\r\n registeredComponent.component.onButtonStateChangedObservable.remove(registeredComponent.onButtonChangedObserver);\r\n }\r\n }\r\n\r\n // remove from the map\r\n delete this._controllers[xrControllerUniqueId];\r\n }\r\n}\r\n\r\nWebXRFeaturesManager.AddWebXRFeature(\r\n WebXRControllerMovement.Name,\r\n (xrSessionManager, options) => {\r\n return () => new WebXRControllerMovement(xrSessionManager, options);\r\n },\r\n WebXRControllerMovement.Version,\r\n true\r\n);\r\n"]}
|
|
1
|
+
{"version":3,"file":"WebXRControllerMovement.js","sourceRoot":"","sources":["../../../../../dev/core/src/XR/features/WebXRControllerMovement.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRFeaturesManager, WebXRFeatureName } from \"../webXRFeaturesManager\";\r\nimport type { Observer } from \"../../Misc/observable\";\r\nimport type { WebXRSessionManager } from \"../webXRSessionManager\";\r\nimport type { Nullable } from \"../../types\";\r\nimport type { WebXRInput } from \"../webXRInput\";\r\nimport type { WebXRInputSource } from \"../webXRInputSource\";\r\nimport type { IWebXRMotionControllerAxesValue, IWebXRMotionControllerComponentChangesValues } from \"../motionController/webXRControllerComponent\";\r\nimport { WebXRControllerComponent } from \"../motionController/webXRControllerComponent\";\r\nimport { Matrix, Quaternion, Vector3 } from \"../../Maths/math.vector\";\r\nimport { WebXRAbstractFeature } from \"./WebXRAbstractFeature\";\r\nimport type { MotionControllerComponentType } from \"../motionController/webXRAbstractMotionController\";\r\nimport { Tools } from \"../../Misc/tools\";\r\n\r\n/**\r\n * The options container for the controller movement module\r\n */\r\nexport interface IWebXRControllerMovementOptions {\r\n /**\r\n * Override default behaviour and provide your own movement controls\r\n */\r\n customRegistrationConfigurations?: WebXRControllerMovementRegistrationConfiguration[];\r\n /**\r\n * Is movement enabled\r\n */\r\n movementEnabled?: boolean;\r\n /**\r\n * Camera direction follows view pose and movement by default will move independently of the viewer's pose.\r\n */\r\n movementOrientationFollowsViewerPose: boolean;\r\n /**\r\n * Movement speed factor (default is 1.0)\r\n */\r\n movementSpeed?: number;\r\n /**\r\n * Minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n */\r\n movementThreshold?: number;\r\n /**\r\n * Is rotation enabled\r\n */\r\n rotationEnabled?: boolean;\r\n /**\r\n * Minimum threshold the controller's thumstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n */\r\n rotationThreshold?: number;\r\n /**\r\n * Movement speed factor (default is 1.0)\r\n */\r\n rotationSpeed?: number;\r\n /**\r\n * Babylon XR Input class for controller\r\n */\r\n xrInput: WebXRInput;\r\n\r\n /**\r\n * If movement orientation should follow controller orientation instead of viewer pose.\r\n * Make sure to set movementOrientationFollowsViewerPose to false, otherwise it will be ignored.\r\n */\r\n movementOrientationFollowsController: boolean;\r\n\r\n /**\r\n * If orientation follows the controller, this is the preferred handedness to use for forward movement.\r\n * If not set (or handedness not found), the handedness will be selected by the controller triggering the movement.\r\n * Note that this only works if movementOrientationFollowsController is true.\r\n */\r\n orientationPreferredHandedness?: XRHandedness;\r\n}\r\n\r\n/**\r\n * Feature context is used in handlers and on each XR frame to control the camera movement/direction.\r\n */\r\nexport type WebXRControllerMovementFeatureContext = {\r\n movementEnabled: boolean;\r\n movementOrientationFollowsViewerPose: boolean;\r\n movementOrientationFollowsController: boolean;\r\n orientationPreferredHandedness?: XRHandedness;\r\n movementSpeed: number;\r\n movementThreshold: number;\r\n rotationEnabled: boolean;\r\n rotationSpeed: number;\r\n rotationThreshold: number;\r\n};\r\n\r\n/**\r\n * Current state of Movements shared across components and handlers.\r\n */\r\nexport type WebXRControllerMovementState = {\r\n moveX: number;\r\n moveY: number;\r\n rotateX: number;\r\n rotateY: number;\r\n};\r\n\r\n/**\r\n * Button of Axis Handler must be specified.\r\n */\r\nexport type WebXRControllerMovementRegistrationConfiguration = {\r\n /**\r\n * handlers are filtered to these types only\r\n */\r\n allowedComponentTypes?: MotionControllerComponentType[];\r\n /**\r\n * For registering movement to specific hand only. Useful if your app has a \"main hand\" and \"off hand\" for determining the functionality of a controller.\r\n */\r\n forceHandedness?: XRHandedness;\r\n /**\r\n * For main component only (useful for buttons and may not trigger axis changes).\r\n */\r\n mainComponentOnly?: boolean;\r\n /**\r\n * Additional predicate to apply to controllers to restrict a handler being added.\r\n */\r\n componentSelectionPredicate?: (xrController: WebXRInputSource) => Nullable<WebXRControllerComponent>;\r\n} & (\r\n | {\r\n /**\r\n * Called when axis changes occur.\r\n */\r\n axisChangedHandler: (\r\n axes: IWebXRMotionControllerAxesValue,\r\n movementState: WebXRControllerMovementState,\r\n featureContext: WebXRControllerMovementFeatureContext,\r\n xrInput: WebXRInput\r\n ) => void;\r\n }\r\n | {\r\n /**\r\n * Called when the button state changes.\r\n */\r\n buttonChangedHandler: (\r\n pressed: IWebXRMotionControllerComponentChangesValues<boolean>,\r\n movementState: WebXRControllerMovementState,\r\n featureContext: WebXRControllerMovementFeatureContext,\r\n xrInput: WebXRInput\r\n ) => void;\r\n }\r\n);\r\n\r\ntype RegisteredComponent = {\r\n registrationConfiguration: WebXRControllerMovementRegistrationConfiguration;\r\n component: WebXRControllerComponent;\r\n onAxisChangedObserver?: Nullable<Observer<IWebXRMotionControllerAxesValue>>;\r\n onButtonChangedObserver?: Nullable<Observer<WebXRControllerComponent>>;\r\n};\r\n\r\n/**\r\n * This is a movement feature to be used with WebXR-enabled motion controllers.\r\n * When enabled and attached, the feature will allow a user to move around and rotate in the scene using\r\n * the input of the attached controllers.\r\n */\r\nexport class WebXRControllerMovement extends WebXRAbstractFeature {\r\n private _controllers: {\r\n [controllerUniqueId: string]: {\r\n xrController: WebXRInputSource;\r\n registeredComponents: RegisteredComponent[];\r\n };\r\n } = {};\r\n\r\n private _currentRegistrationConfigurations: WebXRControllerMovementRegistrationConfiguration[] = [];\r\n // Feature configuration is synchronized - this is passed to all handlers (reduce GC pressure).\r\n private _featureContext: WebXRControllerMovementFeatureContext;\r\n // forward direction for movement, which may differ from viewer pose.\r\n private _movementDirection: Quaternion = new Quaternion();\r\n private _movementState: WebXRControllerMovementState;\r\n private _xrInput: WebXRInput;\r\n\r\n // unused\r\n private _tmpRotationMatrix: Matrix = Matrix.Identity();\r\n private _tmpTranslationDirection: Vector3 = new Vector3();\r\n private _tmpMovementTranslation: Vector3 = new Vector3();\r\n private _tempCacheQuaternion: Quaternion = new Quaternion();\r\n\r\n /**\r\n * The module's name\r\n */\r\n public static readonly Name = WebXRFeatureName.MOVEMENT;\r\n\r\n /**\r\n * Standard controller configurations.\r\n */\r\n public static readonly REGISTRATIONS: { [key: string]: WebXRControllerMovementRegistrationConfiguration[] } = {\r\n default: [\r\n {\r\n allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE],\r\n forceHandedness: \"left\",\r\n axisChangedHandler: (axes: IWebXRMotionControllerAxesValue, movementState: WebXRControllerMovementState, featureContext: WebXRControllerMovementFeatureContext) => {\r\n movementState.rotateX = Math.abs(axes.x) > featureContext.rotationThreshold ? axes.x : 0;\r\n movementState.rotateY = Math.abs(axes.y) > featureContext.rotationThreshold ? axes.y : 0;\r\n },\r\n },\r\n {\r\n allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE],\r\n forceHandedness: \"right\",\r\n axisChangedHandler: (axes: IWebXRMotionControllerAxesValue, movementState: WebXRControllerMovementState, featureContext: WebXRControllerMovementFeatureContext) => {\r\n movementState.moveX = Math.abs(axes.x) > featureContext.movementThreshold ? axes.x : 0;\r\n movementState.moveY = Math.abs(axes.y) > featureContext.movementThreshold ? axes.y : 0;\r\n },\r\n },\r\n ],\r\n };\r\n\r\n /**\r\n * The (Babylon) version of this module.\r\n * This is an integer representing the implementation version.\r\n * This number does not correspond to the webxr specs version\r\n */\r\n public static readonly Version = 1;\r\n\r\n /**\r\n * Current movement direction. Will be null before XR Frames have been processed.\r\n */\r\n public get movementDirection(): Quaternion {\r\n return this._movementDirection;\r\n }\r\n\r\n /**\r\n * Is movement enabled\r\n */\r\n public get movementEnabled(): boolean {\r\n return this._featureContext.movementEnabled;\r\n }\r\n\r\n /**\r\n * Sets whether movement is enabled or not\r\n * @param enabled is movement enabled\r\n */\r\n public set movementEnabled(enabled: boolean) {\r\n this._featureContext.movementEnabled = enabled;\r\n }\r\n\r\n /**\r\n * If movement follows viewer pose\r\n */\r\n public get movementOrientationFollowsViewerPose(): boolean {\r\n return this._featureContext.movementOrientationFollowsViewerPose;\r\n }\r\n\r\n /**\r\n * Sets whether movement follows viewer pose\r\n * @param followsPose is movement should follow viewer pose\r\n */\r\n public set movementOrientationFollowsViewerPose(followsPose: boolean) {\r\n this._featureContext.movementOrientationFollowsViewerPose = followsPose;\r\n }\r\n\r\n /**\r\n * Gets movement speed\r\n */\r\n public get movementSpeed(): number {\r\n return this._featureContext.movementSpeed;\r\n }\r\n\r\n /**\r\n * Sets movement speed\r\n * @param movementSpeed movement speed\r\n */\r\n public set movementSpeed(movementSpeed: number) {\r\n this._featureContext.movementSpeed = movementSpeed;\r\n }\r\n\r\n /**\r\n * Gets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n */\r\n public get movementThreshold(): number {\r\n return this._featureContext.movementThreshold;\r\n }\r\n\r\n /**\r\n * Sets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for movement (avoids jitter/unintentional movement)\r\n * @param movementThreshold new threshold\r\n */\r\n public set movementThreshold(movementThreshold: number) {\r\n this._featureContext.movementThreshold = movementThreshold;\r\n }\r\n\r\n /**\r\n * Is rotation enabled\r\n */\r\n public get rotationEnabled(): boolean {\r\n return this._featureContext.rotationEnabled;\r\n }\r\n\r\n /**\r\n * Sets whether rotation is enabled or not\r\n * @param enabled is rotation enabled\r\n */\r\n public set rotationEnabled(enabled: boolean) {\r\n this._featureContext.rotationEnabled = enabled;\r\n }\r\n\r\n /**\r\n * Gets rotation speed factor\r\n */\r\n public get rotationSpeed(): number {\r\n return this._featureContext.rotationSpeed;\r\n }\r\n\r\n /**\r\n * Sets rotation speed factor (1.0 is default)\r\n * @param rotationSpeed new rotation speed factor\r\n */\r\n public set rotationSpeed(rotationSpeed: number) {\r\n this._featureContext.rotationSpeed = rotationSpeed;\r\n }\r\n\r\n /**\r\n * Gets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n */\r\n public get rotationThreshold(): number {\r\n return this._featureContext.rotationThreshold;\r\n }\r\n\r\n /**\r\n * Sets minimum threshold the controller's thumbstick/touchpad must pass before being recognized for rotation (avoids jitter/unintentional rotation)\r\n * @param threshold new threshold\r\n */\r\n public set rotationThreshold(threshold: number) {\r\n this._featureContext.rotationThreshold = threshold;\r\n }\r\n /**\r\n * constructs a new movement controller system\r\n * @param _xrSessionManager an instance of WebXRSessionManager\r\n * @param options configuration object for this feature\r\n */\r\n constructor(_xrSessionManager: WebXRSessionManager, options: IWebXRControllerMovementOptions) {\r\n super(_xrSessionManager);\r\n\r\n if (!options || options.xrInput === undefined) {\r\n Tools.Error('WebXRControllerMovement feature requires \"xrInput\" option.');\r\n return;\r\n }\r\n\r\n if (Array.isArray(options.customRegistrationConfigurations)) {\r\n this._currentRegistrationConfigurations = options.customRegistrationConfigurations;\r\n } else {\r\n this._currentRegistrationConfigurations = WebXRControllerMovement.REGISTRATIONS.default;\r\n }\r\n\r\n // synchronized from feature setter properties\r\n this._featureContext = {\r\n movementEnabled: options.movementEnabled || true,\r\n movementOrientationFollowsViewerPose: options.movementOrientationFollowsViewerPose ?? true,\r\n movementOrientationFollowsController: options.movementOrientationFollowsController ?? false,\r\n orientationPreferredHandedness: options.orientationPreferredHandedness,\r\n movementSpeed: options.movementSpeed ?? 1,\r\n movementThreshold: options.movementThreshold ?? 0.25,\r\n rotationEnabled: options.rotationEnabled ?? true,\r\n rotationSpeed: options.rotationSpeed ?? 1.0,\r\n rotationThreshold: options.rotationThreshold ?? 0.25,\r\n };\r\n\r\n this._movementState = {\r\n moveX: 0,\r\n moveY: 0,\r\n rotateX: 0,\r\n rotateY: 0,\r\n };\r\n\r\n this._xrInput = options.xrInput;\r\n }\r\n\r\n public override attach(): boolean {\r\n if (!super.attach()) {\r\n return false;\r\n }\r\n\r\n this._xrInput.controllers.forEach(this._attachController);\r\n this._addNewAttachObserver(this._xrInput.onControllerAddedObservable, this._attachController);\r\n this._addNewAttachObserver(this._xrInput.onControllerRemovedObservable, (controller: WebXRInputSource) => {\r\n // REMOVE the controller\r\n this._detachController(controller.uniqueId);\r\n });\r\n\r\n return true;\r\n }\r\n\r\n public override detach(): boolean {\r\n if (!super.detach()) {\r\n return false;\r\n }\r\n\r\n Object.keys(this._controllers).forEach((controllerId) => {\r\n this._detachController(controllerId);\r\n });\r\n\r\n this._controllers = {};\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Occurs on every XR frame.\r\n * @param _xrFrame\r\n */\r\n protected _onXRFrame(_xrFrame: XRFrame) {\r\n if (!this.attached) {\r\n return;\r\n }\r\n\r\n if (this._movementState.rotateX !== 0 && this._featureContext.rotationEnabled) {\r\n // smooth rotation\r\n const deltaMillis = this._xrSessionManager.scene.getEngine().getDeltaTime();\r\n const rotationY = deltaMillis * 0.001 * this._featureContext.rotationSpeed * this._movementState.rotateX * (this._xrSessionManager.scene.useRightHandedSystem ? -1 : 1);\r\n\r\n if (this._featureContext.movementOrientationFollowsViewerPose) {\r\n this._xrInput.xrCamera.cameraRotation.y += rotationY;\r\n Quaternion.RotationYawPitchRollToRef(rotationY, 0, 0, this._tempCacheQuaternion);\r\n this._xrInput.xrCamera.rotationQuaternion.multiplyToRef(this._tempCacheQuaternion, this._movementDirection);\r\n } else if (this._featureContext.movementOrientationFollowsController) {\r\n this._xrInput.xrCamera.cameraRotation.y += rotationY;\r\n // get the correct controller\r\n const handedness = this._featureContext.orientationPreferredHandedness || \"right\";\r\n const key =\r\n Object.keys(this._controllers).find((key) => this._controllers[key]?.xrController?.inputSource.handedness === handedness) || Object.keys(this._controllers)[0];\r\n const controller = this._controllers[key];\r\n Quaternion.RotationYawPitchRollToRef(rotationY, 0, 0, this._tempCacheQuaternion);\r\n (controller?.xrController.pointer.rotationQuaternion || Quaternion.Identity()).multiplyToRef(this._tempCacheQuaternion, this._movementDirection);\r\n } else {\r\n // movement orientation direction does not affect camera. We use rotation speed multiplier\r\n // otherwise need to implement inertia and constraints for same feel as TargetCamera.\r\n\r\n Quaternion.RotationYawPitchRollToRef(rotationY * 3.0, 0, 0, this._tempCacheQuaternion);\r\n this._movementDirection.multiplyInPlace(this._tempCacheQuaternion);\r\n }\r\n } else if (this._featureContext.movementOrientationFollowsViewerPose) {\r\n this._movementDirection.copyFrom(this._xrInput.xrCamera.rotationQuaternion);\r\n } else if (this._featureContext.movementOrientationFollowsController) {\r\n // get the correct controller\r\n const handedness = this._featureContext.orientationPreferredHandedness || \"right\";\r\n const key =\r\n Object.keys(this._controllers).find((key) => this._controllers[key]?.xrController.inputSource.handedness === handedness) || Object.keys(this._controllers)[0];\r\n const controller = this._controllers[key];\r\n this._movementDirection.copyFrom(controller?.xrController.pointer.rotationQuaternion || Quaternion.Identity());\r\n }\r\n\r\n if ((this._movementState.moveX || this._movementState.moveY) && this._featureContext.movementEnabled) {\r\n Matrix.FromQuaternionToRef(this._movementDirection, this._tmpRotationMatrix);\r\n this._tmpTranslationDirection.set(this._movementState.moveX, 0, this._movementState.moveY * (this._xrSessionManager.scene.useRightHandedSystem ? 1.0 : -1.0));\r\n // move according to forward direction based on camera speed\r\n Vector3.TransformCoordinatesToRef(this._tmpTranslationDirection, this._tmpRotationMatrix, this._tmpMovementTranslation);\r\n this._tmpMovementTranslation.scaleInPlace(this._xrInput.xrCamera._computeLocalCameraSpeed() * this._featureContext.movementSpeed);\r\n\r\n this._xrInput.xrCamera.cameraDirection.addInPlace(this._tmpMovementTranslation);\r\n }\r\n }\r\n\r\n private _attachController = (xrController: WebXRInputSource) => {\r\n if (this._controllers[xrController.uniqueId]) {\r\n // already attached\r\n return;\r\n }\r\n\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n registeredComponents: [],\r\n };\r\n const controllerData = this._controllers[xrController.uniqueId];\r\n\r\n // movement controller only available to gamepad-enabled input sources.\r\n if (controllerData.xrController.inputSource.targetRayMode === \"tracked-pointer\" && controllerData.xrController.inputSource.gamepad) {\r\n // motion controller support\r\n const initController = () => {\r\n if (xrController.motionController) {\r\n for (const registration of this._currentRegistrationConfigurations) {\r\n let component: Nullable<WebXRControllerComponent> = null;\r\n\r\n if (registration.allowedComponentTypes) {\r\n for (const componentType of registration.allowedComponentTypes) {\r\n const componentOfType = xrController.motionController.getComponentOfType(componentType);\r\n if (componentOfType !== null) {\r\n component = componentOfType;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (registration.mainComponentOnly) {\r\n const mainComponent = xrController.motionController.getMainComponent();\r\n if (mainComponent === null) {\r\n continue;\r\n }\r\n component = mainComponent;\r\n }\r\n\r\n if (typeof registration.componentSelectionPredicate === \"function\") {\r\n // if does not match we do want to ignore a previously found component\r\n component = registration.componentSelectionPredicate(xrController);\r\n }\r\n\r\n if (component && registration.forceHandedness) {\r\n if (xrController.inputSource.handedness !== registration.forceHandedness) {\r\n continue; // do not register\r\n }\r\n }\r\n\r\n if (component === null) {\r\n continue; // do not register\r\n }\r\n\r\n const registeredComponent: RegisteredComponent = {\r\n registrationConfiguration: registration,\r\n component,\r\n };\r\n controllerData.registeredComponents.push(registeredComponent);\r\n\r\n if (\"axisChangedHandler\" in registration) {\r\n registeredComponent.onAxisChangedObserver = component.onAxisValueChangedObservable.add((axesData) => {\r\n registration.axisChangedHandler(axesData, this._movementState, this._featureContext, this._xrInput);\r\n });\r\n }\r\n\r\n if (\"buttonChangedHandler\" in registration) {\r\n registeredComponent.onButtonChangedObserver = component.onButtonStateChangedObservable.add((component) => {\r\n if (component.changes.pressed) {\r\n registration.buttonChangedHandler(component.changes.pressed, this._movementState, this._featureContext, this._xrInput);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n };\r\n\r\n if (xrController.motionController) {\r\n initController();\r\n } else {\r\n xrController.onMotionControllerInitObservable.addOnce(() => {\r\n initController();\r\n });\r\n }\r\n }\r\n };\r\n\r\n private _detachController(xrControllerUniqueId: string) {\r\n const controllerData = this._controllers[xrControllerUniqueId];\r\n if (!controllerData) {\r\n return;\r\n }\r\n\r\n for (const registeredComponent of controllerData.registeredComponents) {\r\n if (registeredComponent.onAxisChangedObserver) {\r\n registeredComponent.component.onAxisValueChangedObservable.remove(registeredComponent.onAxisChangedObserver);\r\n }\r\n if (registeredComponent.onButtonChangedObserver) {\r\n registeredComponent.component.onButtonStateChangedObservable.remove(registeredComponent.onButtonChangedObserver);\r\n }\r\n }\r\n\r\n // remove from the map\r\n delete this._controllers[xrControllerUniqueId];\r\n }\r\n}\r\n\r\nWebXRFeaturesManager.AddWebXRFeature(\r\n WebXRControllerMovement.Name,\r\n (xrSessionManager, options) => {\r\n return () => new WebXRControllerMovement(xrSessionManager, options);\r\n },\r\n WebXRControllerMovement.Version,\r\n true\r\n);\r\n"]}
|
package/XR/webXRInputSource.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Observable } from "../Misc/observable";
|
|
2
|
-
import { AbstractMesh } from "../Meshes/abstractMesh";
|
|
2
|
+
import type { AbstractMesh } from "../Meshes/abstractMesh";
|
|
3
3
|
import type { Ray } from "../Culling/ray";
|
|
4
4
|
import type { Scene } from "../scene";
|
|
5
5
|
import type { WebXRAbstractMotionController } from "./motionController/webXRAbstractMotionController";
|
package/XR/webXRInputSource.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Observable } from "../Misc/observable.js";
|
|
2
|
-
import { AbstractMesh } from "../Meshes/abstractMesh.js";
|
|
3
2
|
import { Quaternion, Vector3 } from "../Maths/math.vector.js";
|
|
4
3
|
import { WebXRMotionControllerManager } from "./motionController/webXRMotionControllerManager.js";
|
|
5
4
|
import { Tools } from "../Misc/tools.js";
|
|
5
|
+
import { Mesh } from "../Meshes/mesh.js";
|
|
6
6
|
let idCount = 0;
|
|
7
7
|
/**
|
|
8
8
|
* Represents an XR controller
|
|
@@ -40,10 +40,10 @@ export class WebXRInputSource {
|
|
|
40
40
|
*/
|
|
41
41
|
this.onMotionControllerInitObservable = new Observable();
|
|
42
42
|
this._uniqueId = `controller-${idCount++}-${inputSource.targetRayMode}-${inputSource.handedness}`;
|
|
43
|
-
this.pointer = new
|
|
43
|
+
this.pointer = new Mesh(`${this._uniqueId}-pointer`, _scene);
|
|
44
44
|
this.pointer.rotationQuaternion = new Quaternion();
|
|
45
45
|
if (this.inputSource.gripSpace) {
|
|
46
|
-
this.grip = new
|
|
46
|
+
this.grip = new Mesh(`${this._uniqueId}-grip`, this._scene);
|
|
47
47
|
this.grip.rotationQuaternion = new Quaternion();
|
|
48
48
|
}
|
|
49
49
|
this._tmpVector.set(0, 0, this._scene.useRightHandedSystem ? -1.0 : 1.0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webXRInputSource.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRInputSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable } from \"../Misc/observable\";\r\nimport { AbstractMesh } from \"../Meshes/abstractMesh\";\r\nimport { Quaternion, Vector3 } from \"../Maths/math.vector\";\r\nimport type { Ray } from \"../Culling/ray\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { WebXRAbstractMotionController } from \"./motionController/webXRAbstractMotionController\";\r\nimport { WebXRMotionControllerManager } from \"./motionController/webXRMotionControllerManager\";\r\nimport { Tools } from \"../Misc/tools\";\r\nimport type { WebXRCamera } from \"./webXRCamera\";\r\nimport type { WebXRSessionManager } from \"./webXRSessionManager\";\r\n\r\nlet idCount = 0;\r\n\r\n/**\r\n * Configuration options for the WebXR controller creation\r\n */\r\nexport interface IWebXRControllerOptions {\r\n /**\r\n * Should the controller mesh be animated when a user interacts with it\r\n * The pressed buttons / thumbstick and touchpad animations will be disabled\r\n */\r\n disableMotionControllerAnimation?: boolean;\r\n /**\r\n * Do not load the controller mesh, in case a different mesh needs to be loaded.\r\n */\r\n doNotLoadControllerMesh?: boolean;\r\n /**\r\n * Force a specific controller type for this controller.\r\n * This can be used when creating your own profile or when testing different controllers\r\n */\r\n forceControllerProfile?: string;\r\n /**\r\n * Defines a rendering group ID for meshes that will be loaded.\r\n * This is for the default controllers only.\r\n */\r\n renderingGroupId?: number;\r\n}\r\n\r\n/**\r\n * Represents an XR controller\r\n */\r\nexport class WebXRInputSource {\r\n private _tmpVector = new Vector3();\r\n private _uniqueId: string;\r\n private _disposed = false;\r\n\r\n /**\r\n * Represents the part of the controller that is held. This may not exist if the controller is the head mounted display itself, if that's the case only the pointer from the head will be available\r\n */\r\n public grip?: AbstractMesh;\r\n /**\r\n * If available, this is the gamepad object related to this controller.\r\n * Using this object it is possible to get click events and trackpad changes of the\r\n * webxr controller that is currently being used.\r\n */\r\n public motionController?: WebXRAbstractMotionController;\r\n /**\r\n * Event that fires when the controller is removed/disposed.\r\n * The object provided as event data is this controller, after associated assets were disposed.\r\n * uniqueId is still available.\r\n */\r\n public onDisposeObservable = new Observable<WebXRInputSource>();\r\n /**\r\n * Will be triggered when the mesh associated with the motion controller is done loading.\r\n * It is also possible that this will never trigger (!) if no mesh was loaded, or if the developer decides to load a different mesh\r\n * A shortened version of controller -> motion controller -> on mesh loaded.\r\n */\r\n public onMeshLoadedObservable = new Observable<AbstractMesh>();\r\n /**\r\n * Observers registered here will trigger when a motion controller profile was assigned to this xr controller\r\n */\r\n public onMotionControllerInitObservable = new Observable<WebXRAbstractMotionController>();\r\n /**\r\n * Pointer which can be used to select objects or attach a visible laser to\r\n */\r\n public pointer: AbstractMesh;\r\n\r\n /**\r\n * The last XRPose the was calculated on the current XRFrame\r\n * @internal\r\n */\r\n public _lastXRPose?: XRPose;\r\n\r\n /**\r\n * Creates the input source object\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRInputControllerSupport\r\n * @param _scene the scene which the controller should be associated to\r\n * @param inputSource the underlying input source for the controller\r\n * @param _options options for this controller creation\r\n */\r\n constructor(\r\n private _scene: Scene,\r\n /** The underlying input source for the controller */\r\n public inputSource: XRInputSource,\r\n private _options: IWebXRControllerOptions = {}\r\n ) {\r\n this._uniqueId = `controller-${idCount++}-${inputSource.targetRayMode}-${inputSource.handedness}`;\r\n\r\n this.pointer = new AbstractMesh(`${this._uniqueId}-pointer`, _scene);\r\n this.pointer.rotationQuaternion = new Quaternion();\r\n\r\n if (this.inputSource.gripSpace) {\r\n this.grip = new AbstractMesh(`${this._uniqueId}-grip`, this._scene);\r\n this.grip.rotationQuaternion = new Quaternion();\r\n }\r\n\r\n this._tmpVector.set(0, 0, this._scene.useRightHandedSystem ? -1.0 : 1.0);\r\n\r\n // for now only load motion controllers if gamepad object available\r\n if (this.inputSource.gamepad && this.inputSource.targetRayMode === \"tracked-pointer\") {\r\n WebXRMotionControllerManager.GetMotionControllerWithXRInput(inputSource, _scene, this._options.forceControllerProfile).then(\r\n (motionController) => {\r\n this.motionController = motionController;\r\n this.onMotionControllerInitObservable.notifyObservers(motionController);\r\n // should the model be loaded?\r\n if (!this._options.doNotLoadControllerMesh && !this.motionController._doNotLoadControllerMesh) {\r\n this.motionController.loadModel().then((success) => {\r\n if (success && this.motionController && this.motionController.rootMesh) {\r\n if (this._options.renderingGroupId) {\r\n // anything other than 0?\r\n this.motionController.rootMesh.renderingGroupId = this._options.renderingGroupId;\r\n this.motionController.rootMesh.getChildMeshes(false).forEach((mesh) => (mesh.renderingGroupId = this._options.renderingGroupId!));\r\n }\r\n this.onMeshLoadedObservable.notifyObservers(this.motionController.rootMesh);\r\n this.motionController.rootMesh.parent = this.grip || this.pointer;\r\n this.motionController.disableAnimation = !!this._options.disableMotionControllerAnimation;\r\n }\r\n // make sure to dispose is the controller is already disposed\r\n if (this._disposed) {\r\n this.motionController?.dispose();\r\n }\r\n });\r\n }\r\n },\r\n () => {\r\n Tools.Warn(`Could not find a matching motion controller for the registered input source`);\r\n }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get this controllers unique id\r\n */\r\n public get uniqueId() {\r\n return this._uniqueId;\r\n }\r\n\r\n /**\r\n * Disposes of the object\r\n */\r\n public dispose() {\r\n if (this.grip) {\r\n this.grip.dispose(true);\r\n }\r\n if (this.motionController) {\r\n this.motionController.dispose();\r\n }\r\n this.pointer.dispose(true);\r\n this.onMotionControllerInitObservable.clear();\r\n this.onMeshLoadedObservable.clear();\r\n this.onDisposeObservable.notifyObservers(this);\r\n this.onDisposeObservable.clear();\r\n this._disposed = true;\r\n }\r\n\r\n /**\r\n * Gets a world space ray coming from the pointer or grip\r\n * @param result the resulting ray\r\n * @param gripIfAvailable use the grip mesh instead of the pointer, if available\r\n */\r\n public getWorldPointerRayToRef(result: Ray, gripIfAvailable: boolean = false) {\r\n const object = gripIfAvailable && this.grip ? this.grip : this.pointer;\r\n Vector3.TransformNormalToRef(this._tmpVector, object.getWorldMatrix(), result.direction);\r\n result.direction.normalize();\r\n result.origin.copyFrom(object.absolutePosition);\r\n result.length = 1000;\r\n }\r\n\r\n /**\r\n * Updates the controller pose based on the given XRFrame\r\n * @param xrFrame xr frame to update the pose with\r\n * @param referenceSpace reference space to use\r\n * @param xrCamera the xr camera, used for parenting\r\n * @param xrSessionManager the session manager used to get the world reference system\r\n */\r\n public updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace, xrCamera: WebXRCamera, xrSessionManager: WebXRSessionManager) {\r\n const pose = xrFrame.getPose(this.inputSource.targetRaySpace, referenceSpace);\r\n this._lastXRPose = pose;\r\n\r\n // Update the pointer mesh\r\n if (pose) {\r\n const pos = pose.transform.position;\r\n this.pointer.position.set(pos.x, pos.y, pos.z).scaleInPlace(xrSessionManager.worldScalingFactor);\r\n const orientation = pose.transform.orientation;\r\n this.pointer.rotationQuaternion!.set(orientation.x, orientation.y, orientation.z, orientation.w);\r\n if (!this._scene.useRightHandedSystem) {\r\n this.pointer.position.z *= -1;\r\n this.pointer.rotationQuaternion!.z *= -1;\r\n this.pointer.rotationQuaternion!.w *= -1;\r\n }\r\n this.pointer.parent = xrCamera.parent;\r\n this.pointer.scaling.setAll(xrSessionManager.worldScalingFactor);\r\n }\r\n\r\n // Update the grip mesh if it exists\r\n if (this.inputSource.gripSpace && this.grip) {\r\n const pose = xrFrame.getPose(this.inputSource.gripSpace, referenceSpace);\r\n if (pose) {\r\n const pos = pose.transform.position;\r\n const orientation = pose.transform.orientation;\r\n this.grip.position.set(pos.x, pos.y, pos.z).scaleInPlace(xrSessionManager.worldScalingFactor);\r\n this.grip.rotationQuaternion!.set(orientation.x, orientation.y, orientation.z, orientation.w);\r\n if (!this._scene.useRightHandedSystem) {\r\n this.grip.position.z *= -1;\r\n this.grip.rotationQuaternion!.z *= -1;\r\n this.grip.rotationQuaternion!.w *= -1;\r\n }\r\n }\r\n this.grip.parent = xrCamera.parent;\r\n this.grip.scaling.setAll(xrSessionManager.worldScalingFactor);\r\n }\r\n if (this.motionController) {\r\n // either update buttons only or also position, if in gamepad mode\r\n this.motionController.updateFromXRFrame(xrFrame);\r\n }\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"webXRInputSource.js","sourceRoot":"","sources":["../../../../dev/core/src/XR/webXRInputSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { Observable } from \"../Misc/observable\";\r\nimport type { AbstractMesh } from \"../Meshes/abstractMesh\";\r\nimport { Quaternion, Vector3 } from \"../Maths/math.vector\";\r\nimport type { Ray } from \"../Culling/ray\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { WebXRAbstractMotionController } from \"./motionController/webXRAbstractMotionController\";\r\nimport { WebXRMotionControllerManager } from \"./motionController/webXRMotionControllerManager\";\r\nimport { Tools } from \"../Misc/tools\";\r\nimport type { WebXRCamera } from \"./webXRCamera\";\r\nimport type { WebXRSessionManager } from \"./webXRSessionManager\";\r\nimport { Mesh } from \"../Meshes/mesh\";\r\n\r\nlet idCount = 0;\r\n\r\n/**\r\n * Configuration options for the WebXR controller creation\r\n */\r\nexport interface IWebXRControllerOptions {\r\n /**\r\n * Should the controller mesh be animated when a user interacts with it\r\n * The pressed buttons / thumbstick and touchpad animations will be disabled\r\n */\r\n disableMotionControllerAnimation?: boolean;\r\n /**\r\n * Do not load the controller mesh, in case a different mesh needs to be loaded.\r\n */\r\n doNotLoadControllerMesh?: boolean;\r\n /**\r\n * Force a specific controller type for this controller.\r\n * This can be used when creating your own profile or when testing different controllers\r\n */\r\n forceControllerProfile?: string;\r\n /**\r\n * Defines a rendering group ID for meshes that will be loaded.\r\n * This is for the default controllers only.\r\n */\r\n renderingGroupId?: number;\r\n}\r\n\r\n/**\r\n * Represents an XR controller\r\n */\r\nexport class WebXRInputSource {\r\n private _tmpVector = new Vector3();\r\n private _uniqueId: string;\r\n private _disposed = false;\r\n\r\n /**\r\n * Represents the part of the controller that is held. This may not exist if the controller is the head mounted display itself, if that's the case only the pointer from the head will be available\r\n */\r\n public grip?: AbstractMesh;\r\n /**\r\n * If available, this is the gamepad object related to this controller.\r\n * Using this object it is possible to get click events and trackpad changes of the\r\n * webxr controller that is currently being used.\r\n */\r\n public motionController?: WebXRAbstractMotionController;\r\n /**\r\n * Event that fires when the controller is removed/disposed.\r\n * The object provided as event data is this controller, after associated assets were disposed.\r\n * uniqueId is still available.\r\n */\r\n public onDisposeObservable = new Observable<WebXRInputSource>();\r\n /**\r\n * Will be triggered when the mesh associated with the motion controller is done loading.\r\n * It is also possible that this will never trigger (!) if no mesh was loaded, or if the developer decides to load a different mesh\r\n * A shortened version of controller -> motion controller -> on mesh loaded.\r\n */\r\n public onMeshLoadedObservable = new Observable<AbstractMesh>();\r\n /**\r\n * Observers registered here will trigger when a motion controller profile was assigned to this xr controller\r\n */\r\n public onMotionControllerInitObservable = new Observable<WebXRAbstractMotionController>();\r\n /**\r\n * Pointer which can be used to select objects or attach a visible laser to\r\n */\r\n public pointer: AbstractMesh;\r\n\r\n /**\r\n * The last XRPose the was calculated on the current XRFrame\r\n * @internal\r\n */\r\n public _lastXRPose?: XRPose;\r\n\r\n /**\r\n * Creates the input source object\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRInputControllerSupport\r\n * @param _scene the scene which the controller should be associated to\r\n * @param inputSource the underlying input source for the controller\r\n * @param _options options for this controller creation\r\n */\r\n constructor(\r\n private _scene: Scene,\r\n /** The underlying input source for the controller */\r\n public inputSource: XRInputSource,\r\n private _options: IWebXRControllerOptions = {}\r\n ) {\r\n this._uniqueId = `controller-${idCount++}-${inputSource.targetRayMode}-${inputSource.handedness}`;\r\n\r\n this.pointer = new Mesh(`${this._uniqueId}-pointer`, _scene);\r\n this.pointer.rotationQuaternion = new Quaternion();\r\n\r\n if (this.inputSource.gripSpace) {\r\n this.grip = new Mesh(`${this._uniqueId}-grip`, this._scene);\r\n this.grip.rotationQuaternion = new Quaternion();\r\n }\r\n\r\n this._tmpVector.set(0, 0, this._scene.useRightHandedSystem ? -1.0 : 1.0);\r\n\r\n // for now only load motion controllers if gamepad object available\r\n if (this.inputSource.gamepad && this.inputSource.targetRayMode === \"tracked-pointer\") {\r\n WebXRMotionControllerManager.GetMotionControllerWithXRInput(inputSource, _scene, this._options.forceControllerProfile).then(\r\n (motionController) => {\r\n this.motionController = motionController;\r\n this.onMotionControllerInitObservable.notifyObservers(motionController);\r\n // should the model be loaded?\r\n if (!this._options.doNotLoadControllerMesh && !this.motionController._doNotLoadControllerMesh) {\r\n this.motionController.loadModel().then((success) => {\r\n if (success && this.motionController && this.motionController.rootMesh) {\r\n if (this._options.renderingGroupId) {\r\n // anything other than 0?\r\n this.motionController.rootMesh.renderingGroupId = this._options.renderingGroupId;\r\n this.motionController.rootMesh.getChildMeshes(false).forEach((mesh) => (mesh.renderingGroupId = this._options.renderingGroupId!));\r\n }\r\n this.onMeshLoadedObservable.notifyObservers(this.motionController.rootMesh);\r\n this.motionController.rootMesh.parent = this.grip || this.pointer;\r\n this.motionController.disableAnimation = !!this._options.disableMotionControllerAnimation;\r\n }\r\n // make sure to dispose is the controller is already disposed\r\n if (this._disposed) {\r\n this.motionController?.dispose();\r\n }\r\n });\r\n }\r\n },\r\n () => {\r\n Tools.Warn(`Could not find a matching motion controller for the registered input source`);\r\n }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Get this controllers unique id\r\n */\r\n public get uniqueId() {\r\n return this._uniqueId;\r\n }\r\n\r\n /**\r\n * Disposes of the object\r\n */\r\n public dispose() {\r\n if (this.grip) {\r\n this.grip.dispose(true);\r\n }\r\n if (this.motionController) {\r\n this.motionController.dispose();\r\n }\r\n this.pointer.dispose(true);\r\n this.onMotionControllerInitObservable.clear();\r\n this.onMeshLoadedObservable.clear();\r\n this.onDisposeObservable.notifyObservers(this);\r\n this.onDisposeObservable.clear();\r\n this._disposed = true;\r\n }\r\n\r\n /**\r\n * Gets a world space ray coming from the pointer or grip\r\n * @param result the resulting ray\r\n * @param gripIfAvailable use the grip mesh instead of the pointer, if available\r\n */\r\n public getWorldPointerRayToRef(result: Ray, gripIfAvailable: boolean = false) {\r\n const object = gripIfAvailable && this.grip ? this.grip : this.pointer;\r\n Vector3.TransformNormalToRef(this._tmpVector, object.getWorldMatrix(), result.direction);\r\n result.direction.normalize();\r\n result.origin.copyFrom(object.absolutePosition);\r\n result.length = 1000;\r\n }\r\n\r\n /**\r\n * Updates the controller pose based on the given XRFrame\r\n * @param xrFrame xr frame to update the pose with\r\n * @param referenceSpace reference space to use\r\n * @param xrCamera the xr camera, used for parenting\r\n * @param xrSessionManager the session manager used to get the world reference system\r\n */\r\n public updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace, xrCamera: WebXRCamera, xrSessionManager: WebXRSessionManager) {\r\n const pose = xrFrame.getPose(this.inputSource.targetRaySpace, referenceSpace);\r\n this._lastXRPose = pose;\r\n\r\n // Update the pointer mesh\r\n if (pose) {\r\n const pos = pose.transform.position;\r\n this.pointer.position.set(pos.x, pos.y, pos.z).scaleInPlace(xrSessionManager.worldScalingFactor);\r\n const orientation = pose.transform.orientation;\r\n this.pointer.rotationQuaternion!.set(orientation.x, orientation.y, orientation.z, orientation.w);\r\n if (!this._scene.useRightHandedSystem) {\r\n this.pointer.position.z *= -1;\r\n this.pointer.rotationQuaternion!.z *= -1;\r\n this.pointer.rotationQuaternion!.w *= -1;\r\n }\r\n this.pointer.parent = xrCamera.parent;\r\n this.pointer.scaling.setAll(xrSessionManager.worldScalingFactor);\r\n }\r\n\r\n // Update the grip mesh if it exists\r\n if (this.inputSource.gripSpace && this.grip) {\r\n const pose = xrFrame.getPose(this.inputSource.gripSpace, referenceSpace);\r\n if (pose) {\r\n const pos = pose.transform.position;\r\n const orientation = pose.transform.orientation;\r\n this.grip.position.set(pos.x, pos.y, pos.z).scaleInPlace(xrSessionManager.worldScalingFactor);\r\n this.grip.rotationQuaternion!.set(orientation.x, orientation.y, orientation.z, orientation.w);\r\n if (!this._scene.useRightHandedSystem) {\r\n this.grip.position.z *= -1;\r\n this.grip.rotationQuaternion!.z *= -1;\r\n this.grip.rotationQuaternion!.w *= -1;\r\n }\r\n }\r\n this.grip.parent = xrCamera.parent;\r\n this.grip.scaling.setAll(xrSessionManager.worldScalingFactor);\r\n }\r\n if (this.motionController) {\r\n // either update buttons only or also position, if in gamepad mode\r\n this.motionController.updateFromXRFrame(xrFrame);\r\n }\r\n }\r\n}\r\n"]}
|