@soonspacejs/plugin-heat-cloud 2.13.5 → 2.13.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1 +1,3360 @@
1
- import{TextureLoader as t,Texture as e,Matrix3 as n,Vector3 as i,Vector4 as a,Vector2 as o,AlphaFormat as r,RedFormat as s,RedIntegerFormat as l,RGFormat as c,RGIntegerFormat as u,RGBAFormat as d,RGBAIntegerFormat as m,LuminanceFormat as p,LuminanceAlphaFormat as f,DepthFormat as h,DepthStencilFormat as v,ShaderMaterial as g,GLSL3 as x,Matrix4 as _,DoubleSide as y,Mesh as w,BoxGeometry as M,Data3DTexture as z,FloatType as D,LinearFilter as S,UnsignedByteType as b,Color as C,FrontSide as N,UniformsUtils as U,ShaderLib as A,Points as P,PlaneGeometry as O,Box3 as I,Line3 as T,Quaternion as F,BackSide as R,RawShaderMaterial as V,BufferGeometry as E,Float32BufferAttribute as G,Uint8ClampedBufferAttribute as j}from"three";import L from"soonspacejs";var B,k=(t=>(t[t.x=0]="x",t[t.y=1]="y",t[t.z=2]="z",t))(k||{});(B=k||(k={})).toKey=function(t){return B[t]},B.toIndex=function(t){return B[t]},B.getCrossAxiss=function(t){return[(t+1)%3,(t+2)%3]};var H=(t=>(t[t.x=0]="x",t[t.y=1]="y",t[t.z=2]="z",t[t.w=3]="w",t))(H||{});(t=>{t.toKey=function(e){return t[e]},t.toIndex=function(e){return t[e]},t.getCrossAxiss=function(t){return[(t+1)%4,(t+2)%4]}})(H||(H={}));var q=Object.defineProperty,K=(t,e,n)=>(((t,e,n)=>{e in t?q(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n})(t,"symbol"!=typeof e?e+"":e,n),n);function W(t,e,n,i="srgb"){const a=new OffscreenCanvas(e,n).getContext("2d"),o=a.createLinearGradient(0,0,256,1);for(const[e,n]of t)o.addColorStop(Number(e),n);return a.fillStyle=o,a.fillRect(0,0,e,n),a.getImageData(0,0,e,n,{colorSpace:i})}function Y(t,e){let{area:n,width:i,height:a,colorSpace:o}=e||{};o=o??"srgb",n=n||{};const r=n.x??0,s=n.y??0,l=X(t),c=n.width??l.width,u=n.height??l.height;i=i??c,a=a??u;const d=new OffscreenCanvas(i,a).getContext("2d");return d.drawImage(t,r,s,c,u,0,0,i,a),d.getImageData(0,0,i,a,{colorSpace:o})}function X(t){let e=0,n=0;return t instanceof HTMLImageElement?(e=t.naturalWidth,n=t.naturalHeight):t instanceof HTMLVideoElement?(e=t.videoWidth,n=t.videoHeight):(e=t.width,n=t.height),{width:e,height:n}}function Z(t){const{data:e,width:n,height:i,colorSpace:a}=t,o=e.length,r=new Uint8ClampedArray(o);for(let t=0;t<i;t++){const i=t*n,a=-(i+n),o=a+n,s=e.slice(4*a,4*o);r.set(s,4*i)}return new ImageData(r,n,i,{colorSpace:a})}function J(t,e){const{data:n,width:i}=t,a=e*i,o=a+i;return n.slice(4*a,4*o)}function Q(t,e,n){const{data:i,width:a}=t,o=4*(e*a+n);return i.slice(o,o+4)}function $(t){const e=document.createElement("canvas"),n=e.getContext("2d");return e.width=t.width,e.height=t.height,n.putImageData(t,0,0),e}function tt(t){return $(t).toDataURL()}function et(t){return t&&null!=t.data&&null!=t.width&&null!=t.height}function nt(t){return et(t)&&null!=t.depth}function it(t,e){for(const[n,i]of Object.entries(t))if(0<=i&&i<=e[n])return!0;return!1}function at(t,e){const{x:n,y:i}=e;return t.z*i*n+t.y*n+t.x}function ot(t,e){const{x:n,y:i}=e,a=Math.trunc(t/n),o=t-a*n,r=Math.trunc(a/i);return{x:o,y:a-r*i,z:r}}function rt(t,e,n=1){let{x:i,y:a,z:o}=e;const r=t.size;return i=Math.max(0,Math.min(r.x-1,i)),a=Math.max(0,Math.min(r.y-1,a)),o=Math.max(0,Math.min(r.z-1,o)),st(t,{x:i,y:a,z:o},n)}function st(t,e,n=1){const{data:i,size:a}=t,o=at(e,a);let r=[];if(n>0){const t=o*n;for(let e=0;e<n;e++)r.push(i[t+e])}return{index:o,value:r}}function lt(t,e){let{x:n,y:i,z:a}=e;const o=t.size;return n=Math.max(0,Math.min(o.x-1,n)),i=Math.max(0,Math.min(o.y-1,i)),a=Math.max(0,Math.min(o.z-1,a)),ct(t,{x:n,y:i,z:a})}function ct(t,e){const{data:n,size:i}=t,a=at(e,i);return{index:a,value:n[a]}}function ut(t,e){const{voidValue:n,valuesAccumulate:i,verifyVoid:a=(()=>!1)}=e;let{x:o,y:r,z:s}=t[0].size;const l=t.length;for(let e=1;e<l;e++){const n=t[e].size;o=Math.max(o,n.x),r=Math.max(r,n.y),s=Math.max(s,n.z)}const c=new Array(o*r*s),u=o*r;for(let e=0;e<s;e++){const s=e*u;for(let l=0;l<r;l++){const r=s+l*o;for(let s=0;s<o;s++){const o=r+s,u={x:s,y:l,z:e},d=[];for(const n of t){const t=n.size;if(s<t.x&&l<t.y&&e<t.z)continue;const{index:i,value:o}=ct(n,u);a(o,n,i)||d.push({value:o,index:i,data3D:n,coord:u})}const m=d.length;let p=n;m>1?p=i(d):1===m&&(p=d[0].value),c[o]=p}}}return{data:c,size:{x:o,y:r,z:s}}}function dt(t,e,n,i=1){const{size:a}=t,o=k.toKey(e),[r,s]=k.getCrossAxiss(e),l=k.toKey(r),c=k.toKey(s),u=a[l],d=a[c],m=[],p=a[o];n=Math.trunc(n),n=Math.max(0,Math.min(p-1,n));let f={x:0,y:0,z:0};f[o]=n;for(let e=0;e<d;e++){f[c]=e;for(let e=0;e<u;e++){f[l]=e;const{value:n}=st(t,f,i);m.push(...n)}}return{data:m,size:{x:u,y:d}}}function mt(t,e,n){e=Math.trunc(e);const{data:i,width:a,height:o,colorSpace:r}=n?Z(t):t,s=i.length,l=new Uint8ClampedArray(s*e);for(let t=0;t<e;t++)l.set(i,t*s);return{data:l,width:a,height:o,depth:e,colorSpace:r}}function pt(t,e,n){const i=n||{},a=i.reverseY,o=i.axis??"z",r=et(t)?t:Y(t,i);return"z"===o?mt(r,e,a):ft(r,o,e,a)}function ft(t,e,n,i){n=Math.trunc(n);const{data:a,width:o,height:r,colorSpace:s}=i?Z(t):t,l=k.toKey(e),c=(e+1)%3,u=(e+2)%3,d=k.toKey(c),m=k.toKey(u),p={[d]:o,[m]:r,[l]:n},f=new Uint8ClampedArray(a.length*n),h={x:0,y:0,z:0};for(let t=0;t<n;t++){h[l]=t;for(let t=0;t<r;t++){h[m]=t;for(let e=0;e<o;e++){h[d]=e;const n=4*(t*o+e),i=n+4,r=a.subarray(n,i),s=4*at(h,p);f.set(r,s)}}}return{data:f,width:p.x,height:p.y,depth:p.z,colorSpace:s}}function ht(t,e){return t.y*e.x+t.x}function vt(t,e){const{x:n}=e,i=Math.trunc(t/n);return{x:t-i*n,y:i}}function gt(t,e,n=1){let{x:i,y:a}=e;const o=t.size;return i=Math.max(0,Math.min(o.x-1,i)),a=Math.max(0,Math.min(o.y-1,a)),xt(t,{x:i,y:a},n)}function xt(t,e,n=1){const{data:i,size:a}=t,o=ht(e,a);let r=[];if(n>0){const t=o*n;for(let e=0;e<n;e++)r.push(i[t+e])}return{index:o,value:r}}function _t(t,e){let{x:n,y:i}=e;const a=t.size;return n=Math.max(0,Math.min(a.x-1,n)),i=Math.max(0,Math.min(a.y-1,i)),yt(t,{x:n,y:i})}function yt(t,e){const{data:n,size:i}=t,a=ht(e,i);return{index:a,value:n[a]}}function wt(t,e,n=1){const{data:i,size:a}=t,o=a.x,r=e*o,s=r+o;return("function"==typeof i.slice?i:Array.from(i)).slice(r*n,s*n)}class Mt{constructor(t){K(this,"isImageData3DSlice",!0),K(this,"_image3D"),K(this,"_canvas"),K(this,"_context"),K(this,"_axis",k.z),K(this,"_depth",0),K(this,"_sliceSize",null),K(this,"_slice"),this.image3D=t}get image3D(){return this._image3D}set image3D(t){this._image3D=t,this.updateSize()}get canvas(){let t=this._canvas;return t||(t=this._canvas=document.createElement("canvas"),t.width=this.sliceSize.x,t.height=this.sliceSize.y),t}get context(){return this._context??(this._context=this.canvas.getContext("2d"))}get axis(){return this._axis}set axis(t){this._axis=t,this.updateSize()}get depth(){return this._depth}set depth(t){this._depth=t,this.updateSlice()}get sliceSize(){let t=this._sliceSize;if(!t){const{axis:e,image3D:n}=this,{width:i,height:a,depth:o}=n,[r,s]=k.getCrossAxiss(e),l=[i,a,o];this._sliceSize=t={x:l[r],y:l[s]}}return t}get slice(){return this._slice??(this._slice=this.getSlice(this.axis,this.depth))}getSlice(t,e){const{data:n,width:i,height:a,depth:o,colorSpace:r}=this.image3D,{data:s,size:l}=dt({data:n,size:{x:i,y:a,z:o}},t,e,4),c=s instanceof Uint8ClampedArray?s:Uint8ClampedArray.from(s);return new ImageData(c,l.x,l.y,{colorSpace:r})}getDataURL(){return this.canvas.toDataURL()}getColor(t){const{x:e,y:n}=t;return Q(this.slice,n,e)}updateSize(){this._sliceSize=null;const t=this.canvas;t.width=this.sliceSize.x,t.height=this.sliceSize.y,this.updateSlice()}updateSlice(){this._slice=null,this.context.putImageData(this.slice,0,0)}}var zt=Object.defineProperty,Dt=(t,e,n)=>(((t,e,n)=>{e in t?zt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n})(t,"symbol"!=typeof e?e+"":e,n),n);function St(t){const e=t.length,n=[];if(0===e)return n;const[r,s]=function(t){return void 0!==t.w?[a,4]:void 0!==t.z?[i,3]:[o,2]}(t[0]);for(let i=0;i<e;i++){const a=t[i],o=(new r).copy(a),s=a.radius,l=n[i]??(n[i]=[]);for(let a=i+1;a<e;a++){const e=t[a];o.distanceToSquared(e)<=(e.radius+s)**2&&(l.push(a),(n[a]=[]).push(i))}}return n}let bt;function Ct(n){if("string"==typeof n)return(bt||(bt=new t)).load(n);if(n.isTexture)return n;const i=Array.isArray(n)?W(n,256,1):n,a=new e(i);return"srgb"===i.colorSpace&&(a.colorSpace="srgb"),a.needsUpdate=!0,a}function Nt(t,e,n){let i=function(t,e){const n=Math.sqrt(t.lengthSq()*e.lengthSq());if(0===n)return 0;let i=t.dot(e)/n;return i=Math.max(-1,Math.min(1,i)),Math.acos(i)}(t,e);return 0===i?i:t.clone().cross(e).dot(n)<0?-i:i}const Ut=180/Math.PI,At={yaw:[{name:"前",range:[-15,15]},{name:"左",range:[15,165]},{name:"右",range:[-165,-15]},{name:"后",range:[-180.1,-165]},{name:"后",range:[165,180.1]}],pitch:[{name:"前",range:[-15,15]},{name:"上",range:[15,165]},{name:"下",range:[-165,-15]},{name:"后",range:[-180.1,-165]},{name:"后",range:[165,180.1]}],roll:[{name:"上",range:[-15,15]},{name:"左",range:[15,165]},{name:"右",range:[-165,-15]},{name:"下",range:[-180.1,-165]},{name:"下",range:[165,180.1]}]};const Pt={degrees:!0,map:At,front:{x:0,y:0,z:1},up:{x:0,y:1,z:0}};let Ot=class{constructor(t){Dt(this,"_options"),Dt(this,"_listMap"),Dt(this,"_front"),Dt(this,"_up"),t&&(this.options=t)}static get options(){return this._options??(this.options=Pt)}static set options(t){this._options=Object.assign({},structuredClone(At),t)}get defaultOptions(){return this.constructor.options}get options(){return this._options??(this.options=this.defaultOptions)}set options(t){this._options=Object.assign({},structuredClone(this.defaultOptions),t),this._listMap=null,this._front=null,this._up=null}get degrees(){return this.options.degrees??(this.options.degrees=this.defaultOptions.degrees??!0)}set degrees(t){this.options.degrees=t}get map(){return this.options.map||(this.map=this.defaultOptions.map),this.options.map}set map(t){const e=structuredClone(this.defaultOptions.map),n=structuredClone(At);t=t?{yaw:t.yaw??e.yaw??n.yaw,pitch:t.pitch??e.pitch??n.pitch,roll:t.roll??e.roll??n.roll}:e,this.options.map=t,this._listMap=null}get listMap(){return this._listMap??(this._listMap=function(t){const e={};for(const[n,i]of Object.entries(t))e[n]=Array.isArray(i)?i:Object.entries(i).map((([t,e])=>({name:t,range:e})));return e}(this.map??{}))}get front(){return this._front||(this.front=this.options.front??this.defaultOptions.front??Pt.front),this._front}set front(t){this._front=(new i).copy(t)}get up(){return this._up||(this.up=this.options.up??this.defaultOptions.up??Pt.up),this._up}set up(t){this._up=(new i).copy(t)}computeAzimuth(t,e,n){const a=(new i).copy(t),o=(new i).copy(e??this.front),r=(new i).copy(n??this.up);let{yaw:s,pitch:l,roll:c}=function(t,e,n){const i=e.clone().negate(),a=n.clone().projectOnPlane(e),o=Nt(e,t.clone().projectOnPlane(a),a),r=e.clone().cross(a);return{yaw:o,pitch:Nt(e,t.clone().projectOnPlane(r),r),roll:Nt(a,t.clone().projectOnPlane(i),i)}}(a,o,r);return this.degrees&&(s*=Ut,l*=Ut,c*=Ut),{yaw:{angle:s,name:this.findAzimuthNames("yaw",s)},pitch:{angle:l,name:this.findAzimuthNames("pitch",l)},roll:{angle:c,name:this.findAzimuthNames("roll",c)}}}findAzimuthNames(t,e){const n=[],i=this.listMap[t];if(!i)return n;for(const{name:t,range:[a,o]}of i)(e>=a&&e<o||e<=a&&e>o)&&n.push(t);return n}};Dt(Ot,"_options"),new Ot;const It={[r]:1,[s]:1,[l]:1,[c]:3,[u]:2,[d]:4,[m]:4,[p]:1,[f]:2,[h]:1,[v]:2};function Tt(t){return It[t]}new n;var Ft=Object.defineProperty,Rt=(t,e,n)=>(((t,e,n)=>{e in t?Ft(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n})(t,"symbol"!=typeof e?e+"":e,n),n);var Vt=(t=>(t[t.Fill=0]="Fill",t[t.Align=1]="Align",t[t.Raw=2]="Raw",t))(Vt||{});class Et extends g{constructor(t){const{map:e,opacity:n,accFactor:a,steps:r,alphaRange:s,fit:l,atomize:c,side:u,containerMin:d,containerMax:m,uniforms:p,...f}=t??{},h=n??1,v=a??1,g=r??100,_=(new o).copy(s??{x:0,y:.95}),y=l??0,w=c??!0,M=u??N,z=(new i).copy(d??{x:0,y:0,z:0}),D=new i;if(m)D.copy(m);else if(e){const{width:t,height:n,depth:a}=e.image,o=new i(t-1,n-1,a-1);D.addVectors(z,o)}const S={map:{value:e},containerMin:{value:z},containerMax:{value:D},fit:{value:y},opacity:{value:h},alphaRange:{value:_},accFactor:{value:v},steps:{value:g},isDoubleSide:{value:!1},atomize:{value:w},...p};super({glslVersion:x,uniforms:S,transparent:!0,vertexShader:"precision highp sampler3D;\n\nuniform sampler3D map;\nuniform vec3 containerMin;\nuniform vec3 containerMax;\n\n// 0: 充满;1: 对齐;2: 原始\nuniform int fit;\n\n\nout vec3 cameraPos;\nout vec3 lookDir;\nout vec3 displayMin;\nout vec3 displayMax;\n\n\n\nvoid main() {\n cameraPos = vec3( inverse( modelMatrix ) * vec4( cameraPosition, 1.0 ) ).xyz;\n lookDir = position - cameraPos;\n\n vec3 containerSize = containerMax - containerMin;\n vec3 origin = containerMin;\n vec3 textSize = vec3(textureSize(map,0));\n displayMin = containerMin;\n displayMax = containerMax;\n\n switch (fit) {\n case 1:\n displayMax = displayMin + textSize;\n break;\n case 2:\n origin = vec3(0.0);\n break;\n default:\n textSize = containerSize;\n }\n\n vec3 scale = 1.0/textSize;\n cameraPos = (cameraPos - origin)*scale;\n lookDir *= scale;\n\n displayMin = max((displayMin - origin)*scale,vec3(0.0));\n displayMax = min((displayMax - origin)*scale,vec3(1.0));\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",...f}),Rt(this,"isVolumeMaterial",!0),Rt(this,"_side",N),this.opacity=h,this.side=M}get map(){return this.uniforms.map.value}set map(t){this.uniforms.map.value=t,this.uniformsNeedUpdate=!0}get containerMin(){return this.uniforms.containerMin.value}set containerMin(t){this.uniforms.containerMin.value.copy(t),this.uniformsNeedUpdate=!0}get containerMax(){return this.uniforms.containerMax.value}set containerMax(t){this.uniforms.containerMax.value.copy(t),this.uniformsNeedUpdate=!0}get containerSize(){return this.containerMax.clone().sub(this.containerMin)}get fit(){return this.uniforms.fit.value}set fit(t){this.uniforms.fit.value=t,this.uniformsNeedUpdate=!0}getFitTranslate(){return 2===this.fit?new i:this.containerMin.clone()}getFitScale(){var t;const e=new i(1,1,1),n=null==(t=this.map)?void 0:t.image,a=this.fit;if(!n||2===a||1===a)return e;const o=new i(n.width,n.height,n.depth);return e.copy(this.containerSize).divide(o),e}getFitMatrix(){var t;const e=new _,n=null==(t=this.map)?void 0:t.image,a=this.fit;if(!n||2===a)return e;if(0===a){const t=new i(n.width,n.height,n.depth),a=this.containerSize.divide(t);e.makeScale(a.x,a.y,a.z)}return e.setPosition(this.containerMin),e}getFitMatrixInvert(){return this.getFitMatrix().invert()}get side(){return this._side}set side(t){this._side=t,this.uniforms&&(this.uniforms.isDoubleSide.value=t===y,this.uniformsNeedUpdate=!0)}get opacity(){return this.uniforms.opacity.value}set opacity(t){this.uniforms&&(this.uniforms.opacity.value=t),this.uniformsNeedUpdate=!0}get alphaRange(){return this.uniforms.alphaRange.value}set alphaRange(t){this.uniforms.alphaRange.value.copy(t),this.uniformsNeedUpdate=!0}get atomize(){return this.uniforms.atomize.value}set atomize(t){this.uniforms.atomize.value=t,this.uniformsNeedUpdate=!0}get steps(){return this.uniforms.steps.value}set steps(t){this.uniforms.steps.value=t,this.uniformsNeedUpdate=!0}get accFactor(){return this.uniforms.accFactor.value}set accFactor(t){this.uniforms&&(this.uniforms.accFactor.value=t),this.uniformsNeedUpdate=!0}toMapPosition(t){const e=new i(t.x,t.y,t.z).applyMatrix4(this.getFitMatrixInvert());return e.set(Math.trunc(e.x),Math.trunc(e.y),Math.trunc(e.z)),e}toMapDepth(t,e){const a=k.toKey(t),o=new i;o[a]=1;const r=(new n).setFromMatrix4(this.getFitMatrix());return o.applyMatrix3(r),e/=o.length(),Math.trunc(e)}getData3DSlice(t,e){const n=this.map;return null!=n&&n.image?function(t,e,n){const{data:i,width:a,height:o,depth:r}=t.image;return dt({data:i,size:{x:a,y:o,z:r}},e,n,Tt(t.format))}(n,t,e=this.toMapDepth(t,e)):null}getItem(t){const e=this.map;return null!=e&&e.image?function(t,e){const{data:n,width:i,height:a,depth:o}=t.image;return rt({data:n,size:{x:i,y:a,z:o}},e,Tt(t.format))}(e,this.toMapPosition(t)).value:null}}function Gt(t){t.boundingBox||t.computeBoundingBox();const{x:e,y:n,z:i}=t.boundingBox.min;return t.translate(-e,-n,-i),t}class jt extends w{constructor(t){var e;const{width:n,height:i,depth:a}=(null==(e=t.map)?void 0:e.image)||{},o=new M(n,i,a);Gt(o),super(o,t),Rt(this,"isVolumeMesh",!0),Rt(this,"_geometry"),Rt(this,"autoUpdateMaterial",!0),Rt(this,"_material"),Rt(this,"autoUpdateGeometry",!0),Rt(this,"autoNormalize",!1),Object.defineProperties(this,{geometry:{get:()=>this._geometry,set:t=>{this._geometry=t,this.autoNormalize?this.normalize():this.autoUpdateMaterial&&this.updateMaterial()}},material:{get:()=>this._material,set:t=>{this._material=t,this.autoUpdateGeometry&&this.updateGeometry()}}}),this.geometry=o,this.material=t}updateMaterial(){const{geometry:t,material:e}=this;if(!e||!t)return!1;t.boundingBox||t.computeBoundingBox();const{min:n,max:i}=t.boundingBox;e.containerMin=n,e.containerMax=i}updateGeometry(){var t;const{geometry:e,material:n,autoUpdateMaterial:a}=this,o=null==(t=n.map)?void 0:t.image;if(!o)return!1;e.boundingBox||e.computeBoundingBox();const{width:r,height:s,depth:l}=o,c=e.boundingBox.getSize(new i);e.scale(r/c.x,s/c.y,l/c.z),a&&this.updateMaterial()}normalize(){const{geometry:t,autoUpdateMaterial:e}=this;t.boundingBox||t.computeBoundingBox();const{x:n,y:i,z:a}=t.boundingBox.min;t.translate(-n,-i,-a),e&&this.updateMaterial()}toMapPosition(t){const e=this.worldToLocal(new i(t.x,t.y,t.z));return this.material.toMapPosition(e)}toMaterialDepth(t,e){const a=k.toKey(t),o=new i;o[a]=1;const r=(new n).setFromMatrix4(this.matrixWorld);return o.applyMatrix3(r),e/=o.length()}toMapDepth(t,e){return e=this.toMaterialDepth(t,e),this.material.toMapDepth(t,e)}getData3DSlice(t,e){return e=this.toMaterialDepth(t,e),this.material.getData3DSlice(t,e)}getItem(t){const e=this.worldToLocal(new i(t.x,t.y,t.z));return this.material.getItem(e)}}class Lt extends Et{constructor(t){const{gradient:e,range:n,discardOut:i,voidRange:a,...r}=t??{},s=(new o).copy(n??{x:0,y:100}),l=i??!0,c=(new o).copy(a??{x:-100,y:-1});super({...r,fragmentShader:"precision highp float;\nprecision highp sampler3D;\n\nuniform sampler3D map;\nuniform sampler2D gradient;\n\nuniform bool atomize;\nuniform float steps;\n// 颜色累积系数\nuniform float accFactor;\nuniform vec2 range;\n// 是否丢弃超出范围的像素\nuniform bool discardOut;\n// 空值范围\nuniform vec2 voidRange;\nuniform float opacity;\nuniform vec2 alphaRange;\nuniform bool isDoubleSide;\n\nin vec3 cameraPos;\nin vec3 lookDir;\nin vec3 displayMin;\nin vec3 displayMax;\nout vec4 fragColor;\n\nvec4 colorBlend(vec4 near,vec4 far){\n float nA = near.a;\n if (nA >= 1.0){\n return near;\n }\n if (nA <= 0.0){\n return far;\n }\n \n float fA = far.a;\n float a = fA + nA - fA*nA;\n vec3 color = (far.rgb * fA * (1.0 - nA) + near.rgb*nA)/a;\n return vec4(color,a);\n}\n\n\n\n\nvec2 intersectBox( vec3 orig, vec3 dir ) {\n vec3 inv_dir = 1.0 / dir;\n vec3 tmin_tmp = (displayMin - orig ) * inv_dir;\n vec3 tmax_tmp = (displayMax - orig ) * inv_dir;\n vec3 tmin = min( tmin_tmp, tmax_tmp );\n vec3 tmax = max( tmin_tmp, tmax_tmp );\n float t0 = max( tmin.x, max( tmin.y, tmin.z ) );\n float t1 = min( tmax.x, min( tmax.y, tmax.z ) );\n return vec2( t0, t1 );\n}\n\nfloat getValue( vec3 point ) {\n return texture( map, point ).r;\n}\n\n// 获取梯度颜色\nvec4 getGradientColor(float val) {\n val = clamp( val, 0.0,1.0);\n return texture2D(gradient, vec2(val, 0.5));\n}\n\n\n\n\nvoid main(){\n vec3 rayDir = normalize( lookDir );\n\n vec2 times = intersectBox( cameraPos, rayDir );\n float tMin = times.x;\n float tMax = times.y;\n if ( tMin > tMax || tMax < 0.0 ) discard;\n tMin = max( tMin, 0.0 );\n\n vec3 point = cameraPos + tMin * rayDir;\n \n float step = 1.0/steps;\n float opacityFactor = atomize ? step * accFactor : 1.0;\n\n\n float invRangeLen = 1.0/(range.y - range.x);\n vec3 stepDir = rayDir * step;\n\n vec4 finalColor = vec4( 0,0,0,0);\n float alphaMax = alphaRange.y;\n\n for ( float t = tMin; t <= tMax; t += step,point += stepDir ) {\n float val = getValue( point);\n if (voidRange.x <= val && val <= voidRange.y ) continue;\n val = (val - range.x) * invRangeLen;\n if (discardOut && (val < 0.0 || val > 1.0)) continue;\n\n vec4 gradientColor = getGradientColor(val);\n gradientColor.a *= opacityFactor;\n finalColor = colorBlend(finalColor,gradientColor);\n if ( finalColor.a >= alphaMax ) break;\n }\n\n finalColor.a *= opacity;\n if ( finalColor.a <= alphaRange.x ) discard;\n if (isDoubleSide){\n finalColor.a = 1.0 - sqrt(1.0 - finalColor.a);\n }\n fragColor = finalColor;\n\n}",uniforms:{gradient:{value:null==e?e:Ct(e)},range:{value:s},discardOut:{value:l},voidRange:{value:c}}}),Rt(this,"isGradientVolumeMaterial",!0)}get gradient(){return this.uniforms.gradient.value}set gradient(t){this.uniforms.gradient.value=t,this.uniformsNeedUpdate=!0}get range(){return this.uniforms.range.value}set range(t){this.uniforms.range.value.copy(t),this.uniformsNeedUpdate=!0}get discardOut(){return this.uniforms.discardOut.value}set discardOut(t){this.uniforms.discardOut.value=t,this.uniformsNeedUpdate=!0}get voidRange(){return this.uniforms.voidRange.value}set voidRange(t){this.uniforms.voidRange.value.copy(t),this.uniformsNeedUpdate=!0}}class Bt extends z{constructor(t,e,n,i,a){super(t,e,n,i),Rt(this,"isGradientData3DTexture",!0),this.format=s,this.type=a??D,this.minFilter=this.magFilter=S,this.unpackAlignment=1,this.needsUpdate=!0}getData3DSlice(t,e){const{data:n,width:i,height:a,depth:o}=this.image;return dt({data:n,size:{x:i,y:a,z:o}},t,e,1)}getItem(t){const{data:e,width:n,height:i,depth:a}=this.image;return rt({data:e,size:{x:n,y:i,z:a}},t).value}getValue(t){const{data:e,width:n,height:i,depth:a}=this.image;return lt({data:e,size:{x:n,y:i,z:a}},t).value}}function kt(t,e){const{data:n,size:i}=t,{x:a,y:o,z:r}=i,s=a*o*r,{voidValue:l=0,uint8:c}=e??{};let u;if(c){u=new Uint8Array(s);for(let t=0;t<s;t++){const e=n[t]??l;u[t]=Math.trunc(e)}}else{u=new Float32Array(s);for(let t=0;t<s;t++){const e=n[t]??l;u[t]=e}}return new Bt(u,a,o,r,c?b:D)}class Ht extends Et{constructor(t){super({...t,fragmentShader:"precision highp float;\nprecision highp sampler3D;\n\nuniform sampler3D map;\n\n\n\n// 颜色累积系数\nuniform float accFactor;\nuniform bool isDoubleSide;\nuniform bool atomize;\n\n\nuniform float opacity;\nuniform vec2 alphaRange;\nuniform float steps;\n\nin vec3 cameraPos;\nin vec3 lookDir;\nin vec3 displayMin;\nin vec3 displayMax;\nout vec4 fragColor;\n\n// 混合颜色\nvec4 colorBlend(vec4 near,vec4 far){\n float nA = near.a;\n if (nA >= 1.0){\n return near;\n }\n if (nA <= 0.0){\n return far;\n }\n \n float fA = far.a;\n float a = fA + nA - fA*nA;\n vec3 color = (far.rgb * fA * (1.0 - nA) + near.rgb*nA)/a;\n return vec4(color,a);\n}\n\n\n\n\n// 包围盒求交\nvec2 intersectBox( vec3 orig, vec3 dir ) {\n vec3 inv_dir = 1.0 / dir;\n vec3 tmin_tmp = (displayMin - orig ) * inv_dir;\n vec3 tmax_tmp = (displayMax - orig ) * inv_dir;\n vec3 tmin = min( tmin_tmp, tmax_tmp );\n vec3 tmax = max( tmin_tmp, tmax_tmp );\n float t0 = max( tmin.x, max( tmin.y, tmin.z ) );\n float t1 = min( tmax.x, min( tmax.y, tmax.z ) );\n return vec2( t0, t1 );\n}\n\n\n\nvoid main(){\n vec3 rayDir = normalize( lookDir );\n\n vec2 times = intersectBox( cameraPos, rayDir );\n float tMin = times.x;\n float tMax = times.y;\n if ( tMin > tMax || tMax < 0.0 ) discard;\n tMin = max( tMin, 0.0 );\n\n vec3 point = cameraPos + tMin * rayDir;\n \n float step = 1.0/steps;\n float opacityFactor = atomize ? step * accFactor : 1.0;\n\n vec3 stepDir = rayDir * step;\n\n vec4 finalColor = vec4( 0,0,0,0);\n float alphaMax = alphaRange.y;\n\n for ( float t = tMin; t <= tMax; t += step,point += stepDir ) {\n vec4 textureColor = texture( map, point );\n textureColor.a *= opacityFactor;\n finalColor = colorBlend(finalColor,textureColor);\n if ( finalColor.a >= alphaMax ) break;\n }\n\n finalColor.a *= opacity;\n if ( finalColor.a <= alphaRange.x ) discard;\n if (isDoubleSide){\n finalColor.a = 1.0 - sqrt(1.0 - finalColor.a);\n }\n fragColor = finalColor;\n\n}"}),Rt(this,"isImageVolumeMaterial",!0)}}function qt(t,e,n){const i=n??{},{x:a,y:o}=i.range??{x:0,y:100},r=i.discardOut??!0,{x:s,y:l}=i.voidRange??{x:-100,y:-1},c=i.voidColor??[0,0,0,0],{width:u,height:d}=e,m=Math.trunc(d/2),p=u-1;function f(t){const n=Math.trunc(p*t);return Q(e,m,n)}const h=1/(o-a),{data:v,size:g}=t,x=v.length,_=[];for(let t=0;t<x;t++){let e=c,n=v[t];(n<=s||l<=n)&&(n=(n-a)*h,r&&(n<0||n>1)||(n=Math.min(Math.max(n,0),1),e=f(n))),_.push(...e)}return{data:_,size:g}}class Kt extends z{constructor(t,e,n,i){super(t,e,n,i),Rt(this,"isImageData3DTexture",!0),this.format=d,this.type=b,this.minFilter=this.magFilter=S,this.unpackAlignment=1,this.needsUpdate=!0}getData3DSlice(t,e){const{data:n,width:i,height:a,depth:o}=this.image;return dt({data:n,size:{x:i,y:a,z:o}},t,e,4)}getItem(t){return this.getColor(t)}getColor(t){const{data:e,width:n,height:i,depth:a}=this.image;return rt({data:e,size:{x:n,y:i,z:a}},t,4).value}}function Wt(t,e,n){const i=(null==n?void 0:n.reverseY)??!0,{data:a,width:o,height:r,depth:s,colorSpace:l}=pt(t,e,{...n,reverseY:i}),c=new Kt(a,o,r,s);return"srgb"===l&&(c.colorSpace="srgb"),c}function Yt(t,e){const n=e.gradient,i=Array.isArray(n)?W(n,256,1):et(n)?n:Y(n);let a=t;nt(t)&&(a={data:t.data,size:{x:t.width,y:t.height,z:t.depth}});const{data:o,size:r}=qt(a,i,e),s=Uint8ClampedArray.from(o);return new Kt(s,r.x,r.y,r.z)}class Xt extends g{constructor(t){const e=t??{},n=e.color??new C(1,1,1),i=e.solid??0,a=e.exp??1,o=e.opacity??1,r=e.side??N;super({glslVersion:x,uniforms:{color:{value:n},solid:{value:i},exp:{value:a},opacity:{value:o},isDoubleSide:{value:!1}},vertexShader:"out vec3 lookDir;\nout vec3 normalDir;\n\n#if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )\n out vec4 verColor;\n#endif\n\nvoid main() {\n vec3 cameraPos = vec3( inverse( modelMatrix ) * vec4( cameraPosition, 1.0 ) ).xyz;\n lookDir = position - cameraPos;\n normalDir = normal;\n\n #if defined( USE_COLOR_ALPHA )\n verColor = color;\n #elif defined( USE_INSTANCING_COLOR )\n overColor = vec3(instanceColor,1.0);\n #elif defined( USE_COLOR )\n overColor = vec3(color,1.0);\n #endif\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform vec3 color;\nuniform float solid;\nuniform float exp;\n\nuniform float opacity;\nuniform bool isDoubleSide;\n\nin vec3 lookDir;\nin vec3 normalDir;\n\n#if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )\n in vec4 verColor;\n#endif\n\nout vec4 fragColor;\n\n\nvoid main(){\n #if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )\n fragColor = verColor;\n #else\n fragColor = vec4(color,1.0);\n #endif\n\n vec3 dir = normalize(lookDir);\n vec3 nor = normalize(normalDir);\n float depth = abs(dot(nor,dir));\n float dist = sqrt(1.0 - pow(depth,2.0));\n\n float finalAlpha = fragColor.a * depth;\n if (dist > solid) {\n float distAlpha = 1.0 - (dist - solid)/(1.0 - solid);\n finalAlpha *= pow(distAlpha,exp);\n }\n \n finalAlpha *= opacity;\n if ( finalAlpha == 0.0 ) discard;\n if (isDoubleSide){\n finalAlpha = 1.0 - sqrt(1.0 - finalAlpha);\n }\n fragColor.a = finalAlpha;\n}",side:N,transparent:!0}),Rt(this,"isSphereFogMaterial",!0),Rt(this,"_side",N),this.opacity=o,this.side=r}get side(){return this._side}set side(t){this._side=t,this.uniforms&&(this.uniforms.isDoubleSide.value=t===y,this.uniformsNeedUpdate=!0)}get color(){return this.uniforms.color.value}set color(t){this.uniforms.color.value.copy(t),this.uniformsNeedUpdate=!0}get opacity(){return this.uniforms.opacity.value}set opacity(t){this.uniforms&&(this.uniforms.opacity.value=t),this.uniformsNeedUpdate=!0}get solid(){return this.uniforms.solid.value}set solid(t){this.uniforms&&(this.uniforms.solid.value=t),this.uniformsNeedUpdate=!0}get exp(){return this.uniforms.exp.value}set exp(t){this.uniforms&&(this.uniforms.exp.value=t),this.uniformsNeedUpdate=!0}}class Zt extends g{constructor(t,e){const{solid:n=0,exp:i=1,useRadius:a=!0,sizeAttenuation:o=!0,star:r=!1,...s}=t??{},{uniforms:l,...c}=e||{},u={star:{value:r},solid:{value:n},exp:{value:i}};super({uniforms:U.merge([A.points.uniforms,u,l]),transparent:!0,depthTest:!1,defines:{useRadius:a},...c}),Rt(this,"isFogPointsMaterial",!0),Rt(this,"sizeAttenuation",!0),Object.assign(this,{...s,solid:n,exp:i,sizeAttenuation:o})}get map(){return this.uniforms.map.value}set map(t){this.uniforms.map.value=t,this.uniformsNeedUpdate=!0}get star(){return this.uniforms.star.value}set star(t){this.uniforms.star.value=t,this.uniformsNeedUpdate=!0}get size(){return this.uniforms.size.value}set size(t){this.uniforms.size.value=t,this.uniformsNeedUpdate=!0}get opacity(){return this.uniforms.opacity.value}set opacity(t){this.uniforms&&(this.uniforms.opacity.value=t),this.uniformsNeedUpdate=!0}get solid(){return this.uniforms.solid.value}set solid(t){this.uniforms&&(this.uniforms.solid.value=t),this.uniformsNeedUpdate=!0}get exp(){return this.uniforms.exp.value}set exp(t){this.uniforms&&(this.uniforms.exp.value=t),this.uniformsNeedUpdate=!0}get scale(){return this.uniforms.scale.value}set scale(t){this.uniforms&&(this.uniforms.scale.value=t),this.uniformsNeedUpdate=!0}get fogDensity(){return this.uniforms.fogDensity.value}set fogDensity(t){this.uniforms&&(this.uniforms.fogDensity.value=t),this.uniformsNeedUpdate=!0}get fogNear(){return this.uniforms.fogNear.value}set fogNear(t){this.uniforms&&(this.uniforms.fogNear.value=t),this.uniformsNeedUpdate=!0}get fogFar(){return this.uniforms.fogFar.value}set fogFar(t){this.uniforms&&(this.uniforms.fogFar.value=t),this.uniformsNeedUpdate=!0}get fogColor(){return this.uniforms.fogColor.value}set fogColor(t){this.uniforms.fogColor.value.copy(t),this.uniformsNeedUpdate=!0}}class Jt extends Zt{constructor(t){super(t,{vertexShader:"#ifdef useRadius\n\tattribute float radius;\n#endif\n\nuniform float size;\nuniform float scale;\n\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\n#ifdef USE_POINTS_UV\n\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n\n#endif\n\nvoid main() {\n\n\t#ifdef USE_POINTS_UV\n\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n\t#endif\n\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\n\t#ifdef useRadius\n\t\tgl_PointSize = radius;\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\n\t#ifdef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\n\t#endif\n\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n\n}",fragmentShader:"uniform float solid;\nuniform float exp;\nuniform bool star;\n\nuniform vec3 diffuse;\nuniform float opacity;\n\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\n\nvec4 getColor(vec4 originColor){\n\tfloat finalAlpha = originColor.a;\n\tfloat dist = 0.0;\n\tif (star){\n\t\tvec2 coord = abs(gl_PointCoord - vec2(0.5));\n\t\tdist = max(coord.x,coord.y);\n\t}else{\n\t\tdist = distance(gl_PointCoord,vec2(0.5));\n\t\tif (dist>0.5) discard;\n\t}\n\tdist /= 0.5;\n\tfloat depth = sqrt(1.0 - pow(dist,2.0));\n\tfinalAlpha *= depth;\n if (dist > solid) {\n float distAlpha = 1.0 - (dist - solid)/(1.0 - solid);\n finalAlpha *= pow(distAlpha,exp);\n }\n\toriginColor.a = finalAlpha;\n\treturn originColor;\n}\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\n\tdiffuseColor = getColor(diffuseColor);\n\toutgoingLight = diffuseColor.rgb;\n\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\n}"}),Rt(this,"isColorFogPointsMaterial",!0)}get color(){return this.uniforms.diffuse.value}set color(t){this.uniforms.diffuse.value.copy(t),this.uniformsNeedUpdate=!0}get alphaMap(){return this.uniforms.alphaMap.value}set alphaMap(t){this.uniforms&&(this.uniforms.alphaMap.value=t),this.uniformsNeedUpdate=!0}get uvTransform(){return this.uniforms.uvTransform.value}set uvTransform(t){this.uniforms&&this.uniforms.uvTransform.value.copy(t),this.uniformsNeedUpdate=!0}}function Qt(t){const e=new Jt(t),n=function(t){const{points:e,radius:n=10,color:i=[0,0,0,0]}=t,a=[],o=[],r=[];for(const{x:t,y:s,z:l,radius:c,color:u}of e){a.push(t,s,l),o.push(c??n);const e=u??i,d=e[3];e[3]=Math.trunc(255*d),r.push(...e)}const s=new E;return s.setAttribute("position",new G(a,3)),s.setAttribute("radius",new G(o,1)),s.setAttribute("color",new j(r,4,!0)),s}(t);return new P(n,e)}class $t extends Zt{constructor(t){const{range:e,...n}=t||{};super(n,{vertexShader:"attribute float value;\nuniform vec2 range;\nvarying float vValue;\n#ifdef useRadius\n\tattribute float radius;\n#endif\n\n\nuniform float size;\nuniform float scale;\n\n#include <common>\n// #include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\n#ifdef USE_POINTS_UV\n\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n\n#endif\n\nvoid main() {\n\tvValue = (value - range.x)/(range.y - range.x);\n\n\t#ifdef USE_POINTS_UV\n\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n\t#endif\n\n\t// #include <color_vertex>\n\t// #include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\n\t#ifdef useRadius\n\t\tgl_PointSize = radius;\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\n\t#ifdef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\n\t#endif\n\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n\n}",fragmentShader:"varying float vValue;\nuniform sampler2D map;\n\n\nuniform float solid;\nuniform float exp;\nuniform bool star;\n\n// uniform vec3 diffuse;\nuniform float opacity;\n\n#include <common>\n// #include <color_pars_fragment>\n// #include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\n\n// 获取梯度颜色\nvec4 getGradientColor(float val) {\n\tval = clamp( val, 0.0,1.0);\n return texture2D(map, vec2(val, 0.5));\n}\n\n\nvec4 getColor(){\n\tfloat val = vValue;\n\tfloat dist = 0.0;\n\tif (star){\n\t\tvec2 coord = abs(gl_PointCoord - vec2(0.5));\n\t\tdist = max(coord.x,coord.y);\n\t}else{\n\t\tdist = distance(gl_PointCoord,vec2(0.5));\n\t\tif (dist>0.5) discard;\n\t}\n\tdist /= 0.5;\n\tfloat depth = sqrt(1.0 - pow(dist,2.0));\n if (dist > solid) {\n float solidDist = 1.0 - (dist - solid)/(1.0 - solid);\n val *= pow(solidDist,exp);\n }\n\tvec4 valColor = getGradientColor(val);\n\tvalColor.a *= depth * opacity;\n\treturn valColor;\n}\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = getColor();\n\n\t#include <logdepthbuf_fragment>\n\t// #include <map_particle_fragment>\n\t// #include <color_fragment>\n\t#include <alphatest_fragment>\n\n\toutgoingLight = diffuseColor.rgb;\n\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\n}",uniforms:{range:{value:(new o).copy(e??{x:0,y:100})}}}),Rt(this,"isColorFogPointsMaterial",!0)}get range(){return this.uniforms.range.value}set range(t){this.uniforms.range.value.copy(t),this.uniformsNeedUpdate=!0}}function te(t){const e=t.gradient,n=null==e?e:Ct(e),i=new $t({...t,map:n}),a=function(t){const{points:e,radius:n=10,value:i=100}=t,a=[],o=[],r=[];for(const{x:t,y:s,z:l,radius:c,value:u}of e)a.push(t,s,l),o.push(c??n),r.push(u??i);const s=new E;return s.setAttribute("position",new G(a,3)),s.setAttribute("radius",new G(o,1)),s.setAttribute("value",new G(r,1)),s}(t);return new P(a,i)}class ee extends g{constructor(t){const e=t??{};let{map:n,opacity:i,axis:a,depth:o,side:r,...s}=e;i=i??1,a=a??k.z,o=o??0,r=r??y,super({...s,glslVersion:x,uniforms:{map:{value:n},opacity:{value:i},axis:{value:a},depth:{value:o}},transparent:!0,vertexShader:"\tout vec2 vUv;\n \n\tvoid main() {\n\t\tvUv = uv;\n\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t}",fragmentShader:"precision highp float;\nprecision highp sampler3D;\n\nuniform sampler3D map;\n\nuniform float opacity;\nuniform int axis;\nuniform float depth;\n\nin vec2 vUv;\nout vec4 fragColor;\n\nvoid main(){\n vec3 uv3 = vec3(0.0);\n int depthSize = textureSize(map,0)[axis];\n uv3[axis] = depth/float(depthSize);\n int xIndex = (axis + 1)%3;\n int yIndex = (axis + 2)%3;\n uv3[xIndex] = vUv.x;\n uv3[yIndex] = vUv.y;\n\n fragColor = texture(map, uv3);\n fragColor.a *= opacity;\n}",side:r}),Rt(this,"isSliceMaterial",!0),Rt(this,"_sliceSize",null),this.opacity=i}get map(){return this.uniforms.map.value}set map(t){this.uniforms.map.value=t,this._sliceSize=null,this.uniformsNeedUpdate=!0}get opacity(){return this.uniforms.opacity.value}set opacity(t){this.uniforms&&(this.uniforms.opacity.value=t),this.uniformsNeedUpdate=!0}get axis(){return this.uniforms.axis.value}set axis(t){this.uniforms.axis.value=t,this._sliceSize=null,this.uniformsNeedUpdate=!0}get depth(){return this.uniforms.depth.value}set depth(t){this.uniforms.depth.value=t,this.uniformsNeedUpdate=!0}get sliceSize(){let t=this._sliceSize;if(!t){this._sliceSize=t=new o(1,1);const{axis:e,map:n}=this;if(n){const{width:i,height:a,depth:o}=n.image,[r,s]=k.getCrossAxiss(e),l=[i,a,o];t.set(l[r],l[s])}}return t}}class ne extends w{constructor(t){const e=new ee(t),n=new O;super(n,e),Rt(this,"isSliceMesh",!0),Rt(this,"_geometry"),Rt(this,"_material"),Rt(this,"autoUpdateGeometry",!0),Object.defineProperties(this,{geometry:{get:()=>this._geometry,set:t=>{this._geometry=t,this.autoUpdateGeometry&&this.updateGeometry()}},material:{get:()=>this._material,set:t=>{this._material=t,this.autoUpdateGeometry&&this.updateGeometry()}}}),this.geometry=n,this.material=e}updateGeometry(){var t;const{geometry:e,material:n}=this;if(!n||!(null==(t=n.map)?void 0:t.image))return!1;e.boundingBox||e.computeBoundingBox();const a=n.sliceSize,o=e.boundingBox.getSize(new i);e.scale(a.x/o.x,a.y/o.y,1)}get map(){return this.material.map}set map(t){this.material.map=t,this.material=this.material}get axis(){return this.material.axis}set axis(t){this.material.axis=t,this.material=this.material}get depth(){return this.material.depth}set depth(t){this.material.depth=t}get sliceSize(){return this.material.sliceSize}}class ie extends Mt{constructor(t){super(nt(t)?t:t.image),Rt(this,"isImageData3DTextureSlice",!0)}set texture(t){this.image3D=nt(t)?t:t.image}}function ae({ratio:t,value:e}){return e-e*t}function oe(t,e){const{x:n,y:i}=e;let a=0;for(const{value:e,clim:{x:n,y:i}}of t)a+=(e-n)/(i-n);return a*(i-n)+n}function re(t,e,n){const{size:a,data3D:o,tags:r}=e,{clim:s,radius:l,value:c,hollow:u,valueGradient:d,valuesAccumulate:m}=t,p=(new i).copy(t),f=[],h=[],v={particles:f,values:h},g=l*u,x=p.clone().subScalar(l),_=p.clone().addScalar(l);x.max(new i(0,0,0));const y=(new i).copy(a).subScalar(1);_.min(y);let{x:w,y:M,z:z}=x;w=Math.trunc(w),M=Math.trunc(M),z=Math.trunc(z);let{x:D,y:S,z:b}=_;if(D=Math.trunc(D),S=Math.trunc(S),b=Math.trunc(b),w>D||M>S||z>b)return v;const{x:C,y:N}=a,U=C*N;for(let e=z;e<=b;e++){const a=e*U;for(let v=M;v<=S;v++){const x=a+v*C;t:for(let a=w;a<=D;a++){const _=x+a;if(r[_])continue;const y=new i(a,v,e),w=y.distanceTo(p);if(w>l||w<g)continue;r[_]=!0;const M=[],z={...{radius:l,hollow:u,hollowRadius:g,distance:w,clim:s,value:c},ratio:w/l,distance:w,point:y},D=d(z);M.push({...t,...z,value:D});for(const t of n){const e=y.distanceTo(t),{hollow:n,radius:i}=t;if(e<=i){const a=i*n;if(e<a)continue t;const o={...t,ratio:e/i,distance:e,hollowRadius:a,point:y},r=d(o);M.push({...o,value:r})}}const S=m(M,s);o[_]=S,f.push(y),h.push(S)}}}return v}function se(t){const{points:e,clim:n={x:0,y:100},radius:i=10,value:a=100,hollow:o=0,valueGradient:r=ae,valuesAccumulate:s=oe,size:l}=t,c={clim:n,radius:i,value:a,hollow:o,valueGradient:r,valuesAccumulate:s},u=e.map((t=>({...c,...t})));let d=l;l||(d=(new I).setFromPoints(u).max.addScalar(1));const m=St(u);let{x:p,y:f,z:h}=d;p=d.x=Math.trunc(p),f=d.y=Math.trunc(f),h=d.z=Math.trunc(h);const v=new Array(p*f*h),g={size:d,data3D:v,tags:new Array(p*f*h)},x=u.length;for(let t=0;t<x;t++){re(u[t],g,m[t].map((t=>u[t])))}return{data:v,size:d}}function le({startRadius:t,addedRadius:e,ratio:n}){return e*n+t}function ce({startHollow:t,addedHollow:e,ratio:n}){return e*n+t}function ue({startValue:t,addedValue:e,ratio:n}){return e*n+t}function de(t,e){const{x:n,y:i}=e;return t.reduce(((t,e)=>t+e-n),0)}function me(t){const{points:e,size:n,clim:a={x:0,y:100},radius:o=10,value:r=100,hollow:s=0,valueGradient:l=ae,radiusGradient:c=le,hollowGradient:u=ce,lineValueGradient:d=ue,valuesAccumulate:m=de}=t,p={radius:o,value:r,hollow:s},f=e.map((function(t){return Object.assign(new i,p,t)})),h=n?(new i).copy(n).subScalar(1):(new I).setFromPoints(f).max;h.x=Math.trunc(h.x),h.y=Math.trunc(h.y),h.z=Math.trunc(h.z);const v=h.clone().addScalar(1),{x:g,y:x,z:y}=v,w=g*x,M=new Array(w*y),z=[],D=[],S={particles:z,values:D,size:v,data:M},b=new i(0,0,0),C=e.length,N=Math.trunc(C/2);for(let t=0;t<N;t++){const e=2*t,n=f[e],p=f[e+1],v=new T(n,p),x=v.distance(),y=v.delta(new i).normalize(),C=new F;C.setFromUnitVectors(new i(0,1,0),y);const N=(new _).makeRotationFromQuaternion(C);N.setPosition(n);const{radius:U,value:A,hollow:P}=n,{radius:O,value:R,hollow:V}=p,E={length:x,startRadius:U,endRadius:O,addedRadius:O-U,defaultRadius:o,radius:o,startValue:A,endValue:R,addedValue:R-A,defaultValue:r,startHollow:P,endHollow:V,addedHollow:V-P,defaultHollow:s,clim:a},G=Math.max(U,O),j=new i(-G,0,-G),L=new i(G,x,G),B=new I(j,L);B.applyMatrix4(N);const{min:k,max:H}=B;k.max(b),H.min(h);let{x:q,y:K,z:W}=k;q=Math.trunc(q),K=Math.trunc(K),W=Math.trunc(W);let{x:Y,y:X,z:Z}=H;if(Y=Math.trunc(Y),X=Math.trunc(X),Z=Math.trunc(Z),q>Y||K>X||W>Z)return S;N.invert();for(let t=W;t<=Z;t++){const e=t*w;for(let n=K;n<=X;n++){const o=e+n*g;for(let e=q;e<=Y;e++){const r=o+e,s=new i(e,n,t),p=s.clone();p.applyMatrix4(N);const{x:f,y:h,z:v}=p;if(h<0||h>x)continue;const g=Math.hypot(f,v),_={...E,ratio:h/x,point:s},y=c(_);_.radius=y;const w=u(_),S=y*w;if(g>y||g<S)continue;const b=d(_);let C=l({...E,value:b,ratio:g/y,radius:y,hollow:w,hollowRadius:S,distance:g,point:s});const U=D[r];void 0!==U&&(C=m([U,C],a)),M[r]=C,z.push(s),D.push(C)}}}}return S}function pe(t,e){const a=(new i).setFromMatrixScale(e),o=Math.sqrt(a.lengthSq()/3),r=(new n).setFromMatrix4(e);let{points:s,size:l,radius:c,...u}=t;if(l&&(l=(new i).copy(l).applyMatrix3(r)),c&&(c*=o),s){const t=[];for(let{x:n,y:a,z:r,radius:l,...c}of s){l&&(l*=o);const s=new i(n,a,r).applyMatrix4(e);Object.assign(s,c,{radius:l}),t.push(s)}s=t}return{points:s,size:l,radius:c,...u}}function fe(t,e,n=1){let{points:a,size:o,radius:r,...s}=t;if(r&&(r*=n),a){const t=[];for(let{x:o,y:r,z:s,radius:l,...c}of a){l&&(l*=n);const a=new i(o,r,s).add(e).multiplyScalar(n);Object.assign(a,c,{radius:l}),t.push(a)}a=t}return o&&(o=(new i).copy(o).add(e).multiplyScalar(n)),{points:a,size:o,radius:r,...s}}function he(t,e){const{points:n,radius:a}=t;if(!n)return{options:t,position:new i,scale:1};const o=new I;for(const t of n){const e=(new i).copy(t),n=t.radius??a;n?(o.expandByPoint(e.clone().subScalar(n)),o.expandByPoint(e.addScalar(n))):o.expandByPoint(e)}const r=(new i).max(o.min),s=o.max.clone().sub(r).addScalar(1);t.size&&s.min(t.size);let{scale:l,maxSize:c}=e||{};l||(c=c??100,l=c/Math.max(s.x,s.y,s.z)),s.multiplyScalar(l);const u=fe(t,r.clone().negate(),l);return u.size=s,{options:u,position:r,scale:1/l}}const ve={uniforms:{u_size:{value:new i(1,1,1)},u_renderstyle:{value:0},u_renderthreshold:{value:.5},u_clim:{value:new o(1,1)},u_data:{value:null},u_cmdata:{value:null}},vertexShader:'\n\n\t\tvarying vec4 v_nearpos;\n\t\tvarying vec4 v_farpos;\n\t\tvarying vec3 v_position;\n\n\t\tvoid main() {\n\t\t\t\t// Prepare transforms to map to "camera view". See also:\n\t\t\t\t// https://threejs.org/docs/#api/renderers/webgl/WebGLProgram\n\t\t\t\tmat4 viewtransformf = modelViewMatrix;\n\t\t\t\tmat4 viewtransformi = inverse(modelViewMatrix);\n\n\t\t\t\t// Project local vertex coordinate to camera position. Then do a step\n\t\t\t\t// backward (in cam coords) to the near clipping plane, and project back. Do\n\t\t\t\t// the same for the far clipping plane. This gives us all the information we\n\t\t\t\t// need to calculate the ray and truncate it to the viewing cone.\n\t\t\t\tvec4 position4 = vec4(position, 1.0);\n\t\t\t\tvec4 pos_in_cam = viewtransformf * position4;\n\n\t\t\t\t// Intersection of ray and near clipping plane (z = -1 in clip coords)\n\t\t\t\tpos_in_cam.z = -pos_in_cam.w;\n\t\t\t\tv_nearpos = viewtransformi * pos_in_cam;\n\n\t\t\t\t// Intersection of ray and far clipping plane (z = +1 in clip coords)\n\t\t\t\tpos_in_cam.z = pos_in_cam.w;\n\t\t\t\tv_farpos = viewtransformi * pos_in_cam;\n\n\t\t\t\t// Set varyings and output pos\n\t\t\t\tv_position = position;\n\t\t\t\tgl_Position = projectionMatrix * viewMatrix * modelMatrix * position4;\n\t\t}',fragmentShader:"\n\n\t\t\t\tprecision highp float;\n\t\t\t\tprecision mediump sampler3D;\n\n\t\t\t\tuniform vec3 u_size;\n\t\t\t\tuniform int u_renderstyle;\n\t\t\t\tuniform float u_renderthreshold;\n\t\t\t\tuniform vec2 u_clim;\n\n\t\t\t\tuniform sampler3D u_data;\n\t\t\t\tuniform sampler2D u_cmdata;\n\n\t\t\t\tvarying vec3 v_position;\n\t\t\t\tvarying vec4 v_nearpos;\n\t\t\t\tvarying vec4 v_farpos;\n\n\t\t\t\t// The maximum distance through our rendering volume is sqrt(3).\n\t\t\t\tconst int MAX_STEPS = 887;\t// 887 for 512^3, 1774 for 1024^3\n\t\t\t\tconst int REFINEMENT_STEPS = 4;\n\t\t\t\tconst float relative_step_size = 1.0;\n\t\t\t\tconst vec4 ambient_color = vec4(0.2, 0.4, 0.2, 1.0);\n\t\t\t\tconst vec4 diffuse_color = vec4(0.8, 0.2, 0.2, 1.0);\n\t\t\t\tconst vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);\n\t\t\t\tconst float shininess = 40.0;\n\n\t\t\t\tvoid cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);\n\t\t\t\tvoid cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);\n\n\t\t\t\tfloat sample1(vec3 texcoords);\n\t\t\t\tvec4 apply_colormap(float val);\n\t\t\t\tvec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray);\n\n\n\t\t\t\tvoid main() {\n\t\t\t\t\t\t// Normalize clipping plane info\n\t\t\t\t\t\tvec3 farpos = v_farpos.xyz / v_farpos.w;\n\t\t\t\t\t\tvec3 nearpos = v_nearpos.xyz / v_nearpos.w;\n\n\t\t\t\t\t\t// Calculate unit vector pointing in the view direction through this fragment.\n\t\t\t\t\t\tvec3 view_ray = normalize(nearpos.xyz - farpos.xyz);\n\n\t\t\t\t\t\t// Compute the (negative) distance to the front surface or near clipping plane.\n\t\t\t\t\t\t// v_position is the back face of the cuboid, so the initial distance calculated in the dot\n\t\t\t\t\t\t// product below is the distance from near clip plane to the back of the cuboid\n\t\t\t\t\t\tfloat distance = dot(nearpos - v_position, view_ray);\n\t\t\t\t\t\tdistance = max(distance, min((-0.5 - v_position.x) / view_ray.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(u_size.x - 0.5 - v_position.x) / view_ray.x));\n\t\t\t\t\t\tdistance = max(distance, min((-0.5 - v_position.y) / view_ray.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(u_size.y - 0.5 - v_position.y) / view_ray.y));\n\t\t\t\t\t\tdistance = max(distance, min((-0.5 - v_position.z) / view_ray.z,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(u_size.z - 0.5 - v_position.z) / view_ray.z));\n\n\t\t\t\t\t\t// Now we have the starting position on the front surface\n\t\t\t\t\t\tvec3 front = v_position + view_ray * distance;\n\n\t\t\t\t\t\t// Decide how many steps to take\n\t\t\t\t\t\tint nsteps = int(-distance / relative_step_size + 0.5);\n\t\t\t\t\t\tif ( nsteps < 1 )\n\t\t\t\t\t\t\t\tdiscard;\n\n\t\t\t\t\t\t// Get starting location and step vector in texture coordinates\n\t\t\t\t\t\tvec3 step = ((v_position - front) / u_size) / float(nsteps);\n\t\t\t\t\t\tvec3 start_loc = front / u_size;\n\n\t\t\t\t\t\t// For testing: show the number of steps. This helps to establish\n\t\t\t\t\t\t// whether the rays are correctly oriented\n\t\t\t\t\t\t//'gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0);\n\t\t\t\t\t\t//'return;\n\n\t\t\t\t\t\tif (u_renderstyle == 0)\n\t\t\t\t\t\t\t\tcast_mip(start_loc, step, nsteps, view_ray);\n\t\t\t\t\t\telse if (u_renderstyle == 1)\n\t\t\t\t\t\t\t\tcast_iso(start_loc, step, nsteps, view_ray);\n\n\t\t\t\t\t\tif (gl_FragColor.a < 0.05)\n\t\t\t\t\t\t\t\tdiscard;\n\t\t\t\t}\n\n\n\t\t\t\tfloat sample1(vec3 texcoords) {\n\t\t\t\t\t\t/* Sample float value from a 3D texture. Assumes intensity data. */\n\t\t\t\t\t\treturn texture(u_data, texcoords.xyz).r;\n\t\t\t\t}\n\n\n\t\t\t\tvec4 apply_colormap(float val) {\n\t\t\t\t\t\tval = (val - u_clim[0]) / (u_clim[1] - u_clim[0]);\n\t\t\t\t\t\treturn texture2D(u_cmdata, vec2(val, 0.5));\n\t\t\t\t}\n\n\n\t\t\t\tvoid cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {\n\n\t\t\t\t\t\tfloat max_val = -1e6;\n\t\t\t\t\t\tint max_i = 100;\n\t\t\t\t\t\tvec3 loc = start_loc;\n\n\t\t\t\t\t\t// Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with\n\t\t\t\t\t\t// non-constant expression. So we use a hard-coded max, and an additional condition\n\t\t\t\t\t\t// inside the loop.\n\t\t\t\t\t\tfor (int iter=0; iter<MAX_STEPS; iter++) {\n\t\t\t\t\t\t\t\tif (iter >= nsteps)\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t// Sample from the 3D texture\n\t\t\t\t\t\t\t\tfloat val = sample1(loc);\n\t\t\t\t\t\t\t\t// Apply MIP operation\n\t\t\t\t\t\t\t\tif (val > max_val) {\n\t\t\t\t\t\t\t\t\t\tmax_val = val;\n\t\t\t\t\t\t\t\t\t\tmax_i = iter;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Advance location deeper into the volume\n\t\t\t\t\t\t\t\tloc += step;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Refine location, gives crispier images\n\t\t\t\t\t\tvec3 iloc = start_loc + step * (float(max_i) - 0.5);\n\t\t\t\t\t\tvec3 istep = step / float(REFINEMENT_STEPS);\n\t\t\t\t\t\tfor (int i=0; i<REFINEMENT_STEPS; i++) {\n\t\t\t\t\t\t\t\tmax_val = max(max_val, sample1(iloc));\n\t\t\t\t\t\t\t\tiloc += istep;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Resolve final color\n\t\t\t\t\t\tgl_FragColor = apply_colormap(max_val);\n\t\t\t\t}\n\n\n\t\t\t\tvoid cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {\n\n\t\t\t\t\t\tgl_FragColor = vec4(0.0);\t// init transparent\n\t\t\t\t\t\tvec4 color3 = vec4(0.0);\t// final color\n\t\t\t\t\t\tvec3 dstep = 1.5 / u_size;\t// step to sample derivative\n\t\t\t\t\t\tvec3 loc = start_loc;\n\n\t\t\t\t\t\tfloat low_threshold = u_renderthreshold - 0.02 * (u_clim[1] - u_clim[0]);\n\n\t\t\t\t\t\t// Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with\n\t\t\t\t\t\t// non-constant expression. So we use a hard-coded max, and an additional condition\n\t\t\t\t\t\t// inside the loop.\n\t\t\t\t\t\tfor (int iter=0; iter<MAX_STEPS; iter++) {\n\t\t\t\t\t\t\t\tif (iter >= nsteps)\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t// Sample from the 3D texture\n\t\t\t\t\t\t\t\tfloat val = sample1(loc);\n\n\t\t\t\t\t\t\t\tif (val > low_threshold) {\n\t\t\t\t\t\t\t\t\t\t// Take the last interval in smaller steps\n\t\t\t\t\t\t\t\t\t\tvec3 iloc = loc - 0.5 * step;\n\t\t\t\t\t\t\t\t\t\tvec3 istep = step / float(REFINEMENT_STEPS);\n\t\t\t\t\t\t\t\t\t\tfor (int i=0; i<REFINEMENT_STEPS; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\tval = sample1(iloc);\n\t\t\t\t\t\t\t\t\t\t\t\tif (val > u_renderthreshold) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tgl_FragColor = add_lighting(val, iloc, dstep, view_ray);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tiloc += istep;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Advance location deeper into the volume\n\t\t\t\t\t\t\t\tloc += step;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tvec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray)\n\t\t\t\t{\n\t\t\t\t\t// Calculate color by incorporating lighting\n\n\t\t\t\t\t\t// View direction\n\t\t\t\t\t\tvec3 V = normalize(view_ray);\n\n\t\t\t\t\t\t// calculate normal vector from gradient\n\t\t\t\t\t\tvec3 N;\n\t\t\t\t\t\tfloat val1, val2;\n\t\t\t\t\t\tval1 = sample1(loc + vec3(-step[0], 0.0, 0.0));\n\t\t\t\t\t\tval2 = sample1(loc + vec3(+step[0], 0.0, 0.0));\n\t\t\t\t\t\tN[0] = val1 - val2;\n\t\t\t\t\t\tval = max(max(val1, val2), val);\n\t\t\t\t\t\tval1 = sample1(loc + vec3(0.0, -step[1], 0.0));\n\t\t\t\t\t\tval2 = sample1(loc + vec3(0.0, +step[1], 0.0));\n\t\t\t\t\t\tN[1] = val1 - val2;\n\t\t\t\t\t\tval = max(max(val1, val2), val);\n\t\t\t\t\t\tval1 = sample1(loc + vec3(0.0, 0.0, -step[2]));\n\t\t\t\t\t\tval2 = sample1(loc + vec3(0.0, 0.0, +step[2]));\n\t\t\t\t\t\tN[2] = val1 - val2;\n\t\t\t\t\t\tval = max(max(val1, val2), val);\n\n\t\t\t\t\t\tfloat gm = length(N); // gradient magnitude\n\t\t\t\t\t\tN = normalize(N);\n\n\t\t\t\t\t\t// Flip normal so it points towards viewer\n\t\t\t\t\t\tfloat Nselect = float(dot(N, V) > 0.0);\n\t\t\t\t\t\tN = (2.0 * Nselect - 1.0) * N;\t// ==\tNselect * N - (1.0-Nselect)*N;\n\n\t\t\t\t\t\t// Init colors\n\t\t\t\t\t\tvec4 ambient_color = vec4(0.0, 0.0, 0.0, 0.0);\n\t\t\t\t\t\tvec4 diffuse_color = vec4(0.0, 0.0, 0.0, 0.0);\n\t\t\t\t\t\tvec4 specular_color = vec4(0.0, 0.0, 0.0, 0.0);\n\n\t\t\t\t\t\t// note: could allow multiple lights\n\t\t\t\t\t\tfor (int i=0; i<1; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t // Get light direction (make sure to prevent zero devision)\n\t\t\t\t\t\t\t\tvec3 L = normalize(view_ray);\t//lightDirs[i];\n\t\t\t\t\t\t\t\tfloat lightEnabled = float( length(L) > 0.0 );\n\t\t\t\t\t\t\t\tL = normalize(L + (1.0 - lightEnabled));\n\n\t\t\t\t\t\t\t\t// Calculate lighting properties\n\t\t\t\t\t\t\t\tfloat lambertTerm = clamp(dot(N, L), 0.0, 1.0);\n\t\t\t\t\t\t\t\tvec3 H = normalize(L+V); // Halfway vector\n\t\t\t\t\t\t\t\tfloat specularTerm = pow(max(dot(H, N), 0.0), shininess);\n\n\t\t\t\t\t\t\t\t// Calculate mask\n\t\t\t\t\t\t\t\tfloat mask1 = lightEnabled;\n\n\t\t\t\t\t\t\t\t// Calculate colors\n\t\t\t\t\t\t\t\tambient_color +=\tmask1 * ambient_color;\t// * gl_LightSource[i].ambient;\n\t\t\t\t\t\t\t\tdiffuse_color +=\tmask1 * lambertTerm;\n\t\t\t\t\t\t\t\tspecular_color += mask1 * specularTerm * specular_color;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Calculate final color by componing different components\n\t\t\t\t\t\tvec4 final_color;\n\t\t\t\t\t\tvec4 color = apply_colormap(val);\n\t\t\t\t\t\tfinal_color = color * (ambient_color + diffuse_color) + specular_color;\n\t\t\t\t\t\tfinal_color.a = color.a;\n\t\t\t\t\t\treturn final_color;\n\t\t\t\t}"};var ge=(t=>(t[t.MIP=0]="MIP",t[t.ISO=1]="ISO",t))(ge||{});class xe extends g{constructor(t){const{style:e,threshold:n,clim:a,map:r,gradient:s}=t??{},l=new i(1,1,1);if(r){const{width:t,height:e,depth:n}=r.image;l.set(t,e,n)}const c=null==s?s:Ct(s),u=U.clone(ve.uniforms);u.u_size.value.copy(l),u.u_clim.value.copy(a??new o(1,1)),u.u_renderstyle.value=e??1,u.u_renderthreshold.value=n??.5,u.u_data.value=r??null,u.u_cmdata.value=c??null,super({...ve,uniforms:u,side:R}),Rt(this,"isExampleVolumeMaterial_1",!0),Rt(this,"_gradient")}get map(){return this.uniforms.u_data.value}set map(t){this.uniforms.u_data.value=t,this.uniformsNeedUpdate=!0}get gradientMap(){return this.uniforms.u_cmdata.value}get gradient(){return this._gradient}set gradient(t){this._gradient=t;const e=null==t?t:Ct(t);this.uniforms.u_cmdata.value=e??null,this.uniformsNeedUpdate=!0}get size(){return this.uniforms.u_size.value}set size(t){this.uniforms.u_size.value.copy(t),this.uniformsNeedUpdate=!0}get style(){return this.uniforms.u_renderstyle.value}set style(t){this.uniforms.u_renderstyle.value=t,this.uniformsNeedUpdate=!0}get clim(){return this.uniforms.u_clim.value}set clim(t){this.uniforms.u_clim.value=t,this.uniformsNeedUpdate=!0}get threshold(){return this.uniforms.u_renderthreshold.value}set threshold(t){this.uniforms.u_renderthreshold.value=t,this.uniformsNeedUpdate=!0}}const _e="in vec3 position;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform vec3 cameraPos;\n\nout vec3 vOrigin;\nout vec3 vDirection;\n\nvoid main() {\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n vOrigin = vec3( inverse( modelMatrix ) * vec4( cameraPos, 1.0 ) ).xyz;\n vDirection = position - vOrigin;\n gl_Position = projectionMatrix * mvPosition;\n}";class ye extends V{constructor(t){let{color:e,threshold:n,map:a,opacity:o,range:r,steps:s,frame:l,cameraPos:c}=t??{};e=e??new C(1,1,1),n=n??.25,o=o??.25,r=r??.1,s=s??100,l=l??100,c=c??new i,super({glslVersion:x,uniforms:{base:{value:e},map:{value:a},cameraPos:{value:c},threshold:{value:n},opacity:{value:o},range:{value:r},steps:{value:s},frame:{value:l}},vertexShader:_e,fragmentShader:"precision highp float;\nprecision highp sampler3D;\n\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\n\nin vec3 vOrigin;\nin vec3 vDirection;\n\nout vec4 color;\n\nuniform vec3 base;\nuniform sampler3D map;\n\nuniform float threshold;\nuniform float range;\nuniform float opacity;\nuniform float steps;\nuniform float frame;\n\nuint wang_hash(uint seed)\n{\n seed = (seed ^ 61u) ^ (seed >> 16u);\n seed *= 9u;\n seed = seed ^ (seed >> 4u);\n seed *= 0x27d4eb2du;\n seed = seed ^ (seed >> 15u);\n return seed;\n}\n\nfloat randomFloat(inout uint seed)\n{\n return float(wang_hash(seed)) / 4294967296.;\n}\n\nvec2 hitBox( vec3 orig, vec3 dir ) {\n const vec3 box_min = vec3( - 0.5 );\n const vec3 box_max = vec3( 0.5 );\n vec3 inv_dir = 1.0 / dir;\n vec3 tmin_tmp = ( box_min - orig ) * inv_dir;\n vec3 tmax_tmp = ( box_max - orig ) * inv_dir;\n vec3 tmin = min( tmin_tmp, tmax_tmp );\n vec3 tmax = max( tmin_tmp, tmax_tmp );\n float t0 = max( tmin.x, max( tmin.y, tmin.z ) );\n float t1 = min( tmax.x, min( tmax.y, tmax.z ) );\n return vec2( t0, t1 );\n}\n\nfloat sample1( vec3 p ) {\n return texture( map, p ).r;\n}\n\nfloat shading( vec3 coord ) {\n float step = 0.01;\n return sample1( coord + vec3( - step ) ) - sample1( coord + vec3( step ) );\n}\n\nvoid main(){\n vec3 rayDir = normalize( vDirection );\n vec2 bounds = hitBox( vOrigin, rayDir );\n\n if ( bounds.x > bounds.y ) discard;\n\n bounds.x = max( bounds.x, 0.0 );\n\n vec3 p = vOrigin + bounds.x * rayDir;\n vec3 inc = 1.0 / abs( rayDir );\n float delta = min( inc.x, min( inc.y, inc.z ) );\n delta /= steps;\n\n // Jitter\n\n // Nice little seed from\n // https://blog.demofox.org/2020/05/25/casual-shadertoy-path-tracing-1-basic-camera-diffuse-emissive/\n uint seed = uint( gl_FragCoord.x ) * uint( 1973 ) + uint( gl_FragCoord.y ) * uint( 9277 ) + uint( frame ) * uint( 26699 );\n vec3 size = vec3( textureSize( map, 0 ) );\n float randNum = randomFloat( seed ) * 2.0 - 1.0;\n p += rayDir * randNum * ( 1.0 / size );\n\n //\n\n vec4 ac = vec4( base, 0.0 );\n\n for ( float t = bounds.x; t < bounds.y; t += delta ) {\n\n float d = sample1( p + 0.5 );\n\n d = smoothstep( threshold - range, threshold + range, d ) * opacity;\n\n float col = shading( p + 0.5 ) * 3.0 + ( ( p.x + p.y ) * 0.25 ) + 0.2;\n\n ac.rgb += ( 1.0 - ac.a ) * d * col;\n\n ac.a += ( 1.0 - ac.a ) * d;\n\n if ( ac.a >= 0.95 ) break;\n\n p += rayDir * delta;\n\n }\n\n color = ac;\n\n if ( color.a == 0.0 ) discard;\n\n}",side:R,transparent:!0}),Rt(this,"isExampleVolumeMaterial_Cloud",!0),this.opacity=o}get map(){return this.uniforms.map.value}set map(t){this.uniforms.map.value=t,this.uniformsNeedUpdate=!0}get color(){return this.uniforms.base.value}set color(t){this.uniforms.base.value=t,this.uniformsNeedUpdate=!0}get opacity(){return this.uniforms.opacity.value}set opacity(t){this.uniforms&&(this.uniforms.opacity.value=t),this.uniformsNeedUpdate=!0}get threshold(){return this.uniforms.threshold.value}set threshold(t){this.uniforms.threshold.value=t,this.uniformsNeedUpdate=!0}get range(){return this.uniforms.range.value}set range(t){this.uniforms.range.value=t,this.uniformsNeedUpdate=!0}get steps(){return this.uniforms.steps.value}set steps(t){this.uniforms.steps.value=t,this.uniformsNeedUpdate=!0}get frame(){return this.uniforms.frame.value}set frame(t){this.uniforms.frame.value=t,this.uniformsNeedUpdate=!0}get cameraPos(){return this.uniforms.cameraPos.value}set cameraPos(t){this.uniforms.cameraPos.value.copy(t),this.uniformsNeedUpdate=!0}}class we extends V{constructor(t){let{threshold:e,map:n,steps:a,cameraPos:o}=t??{};e=e??.25,a=a??100,o=o??new i,super({glslVersion:x,uniforms:{map:{value:n},cameraPos:{value:o},threshold:{value:e},steps:{value:a}},vertexShader:_e,fragmentShader:"precision highp float;\nprecision highp sampler3D;\n\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\n\nin vec3 vOrigin;\nin vec3 vDirection;\n\nout vec4 color;\n\nuniform sampler3D map;\n\nuniform float threshold;\nuniform float steps;\n\nvec2 hitBox( vec3 orig, vec3 dir ) {\n const vec3 box_min = vec3( - 0.5 );\n const vec3 box_max = vec3( 0.5 );\n vec3 inv_dir = 1.0 / dir;\n vec3 tmin_tmp = ( box_min - orig ) * inv_dir;\n vec3 tmax_tmp = ( box_max - orig ) * inv_dir;\n vec3 tmin = min( tmin_tmp, tmax_tmp );\n vec3 tmax = max( tmin_tmp, tmax_tmp );\n float t0 = max( tmin.x, max( tmin.y, tmin.z ) );\n float t1 = min( tmax.x, min( tmax.y, tmax.z ) );\n return vec2( t0, t1 );\n}\n\nfloat sample1( vec3 p ) {\n return texture( map, p ).r;\n}\n\n#define epsilon .0001\n\nvec3 normal( vec3 coord ) {\n if ( coord.x < epsilon ) return vec3( 1.0, 0.0, 0.0 );\n if ( coord.y < epsilon ) return vec3( 0.0, 1.0, 0.0 );\n if ( coord.z < epsilon ) return vec3( 0.0, 0.0, 1.0 );\n if ( coord.x > 1.0 - epsilon ) return vec3( - 1.0, 0.0, 0.0 );\n if ( coord.y > 1.0 - epsilon ) return vec3( 0.0, - 1.0, 0.0 );\n if ( coord.z > 1.0 - epsilon ) return vec3( 0.0, 0.0, - 1.0 );\n\n float step = 0.01;\n float x = sample1( coord + vec3( - step, 0.0, 0.0 ) ) - sample1( coord + vec3( step, 0.0, 0.0 ) );\n float y = sample1( coord + vec3( 0.0, - step, 0.0 ) ) - sample1( coord + vec3( 0.0, step, 0.0 ) );\n float z = sample1( coord + vec3( 0.0, 0.0, - step ) ) - sample1( coord + vec3( 0.0, 0.0, step ) );\n\n return normalize( vec3( x, y, z ) );\n}\n\nvoid main(){\n\n vec3 rayDir = normalize( vDirection );\n vec2 bounds = hitBox( vOrigin, rayDir );\n\n if ( bounds.x > bounds.y ) discard;\n\n bounds.x = max( bounds.x, 0.0 );\n\n vec3 p = vOrigin + bounds.x * rayDir;\n vec3 inc = 1.0 / abs( rayDir );\n float delta = min( inc.x, min( inc.y, inc.z ) );\n delta /= steps;\n\n for ( float t = bounds.x; t < bounds.y; t += delta ) {\n\n float d = sample1( p + 0.5 );\n\n if ( d > threshold ) {\n\n color.rgb = normal( p + 0.5 ) * 0.5 + ( p * 1.5 + 0.25 );\n color.a = 1.;\n break;\n\n }\n\n p += rayDir * delta;\n\n }\n\n if ( color.a == 0.0 ) discard;\n\n}",side:R,transparent:!0}),Rt(this,"isExampleVolumeMaterial_Perlin",!0)}get map(){return this.uniforms.map.value}set map(t){this.uniforms.map.value=t,this.uniformsNeedUpdate=!0}get threshold(){return this.uniforms.threshold.value}set threshold(t){this.uniforms.threshold.value=t,this.uniformsNeedUpdate=!0}get steps(){return this.uniforms.steps.value}set steps(t){this.uniforms.steps.value=t,this.uniformsNeedUpdate=!0}get cameraPos(){return this.uniforms.cameraPos.value}set cameraPos(t){this.uniforms.cameraPos.value.copy(t),this.uniformsNeedUpdate=!0}}class Me{constructor(t){this.ssp=t,this.defaultColorGradient=[[0,"rgba(0,255,0,0)"],[.5,"rgba(64,255,255,0.5)"],[1,"rgba(255,64,255,1)"]],this.defaultGradientVolumeMaterialOptions={fit:Vt.Raw,accFactor:2,depthTest:!1,side:R,discardOut:!1,gradient:Ct(this.defaultColorGradient)}}_createTexture(t,e,n=!1){const i=he(Object.assign({points:t},e),Object.assign({maxSize:60},e)),{options:a,position:o,scale:r}=i,s=kt(n?me(a):se(a),Object.assign({},e)),l=new Lt(Object.assign(Object.assign(Object.assign({},this.defaultGradientVolumeMaterialOptions),{map:s}),e)),c=new jt(l);return c.position.copy(o),c.scale.set(r,r,r),this.ssp.addObject(c),c}createHeatCloud(t,e){return this._createTexture(t,e)}createLineHeat(t,e){return this._createTexture(t,e,!0)}async createImageExtrusion(t,e){var n;const i=new Ht(Object.assign({side:R,depthTest:!1},e)),a=Wt(await L.utils.imageLoader.loadAsync(t),null!==(n=null==e?void 0:e.depth)&&void 0!==n?n:200,e);i.map=a;const o=new jt(i);return this.ssp.addObject(o),o}createSliceMesh(t,e){let n=t.map;if(!n)return;if(t instanceof Lt){const{gradient:i,range:a,discardOut:o,voidRange:r}=t;n=Yt(n.image,Object.assign({gradient:null==i?void 0:i.image,range:a,discardOut:o,voidRange:r},e))}const i=new ne(Object.assign({map:n},e));return this.ssp.addObject(i),i}createImageSlice(t,e){const n=t.map;if(!n)return;let i=null;if(t instanceof Lt){const{gradient:a,range:o,discardOut:r,voidRange:s}=t;i=Yt(n.image,Object.assign({gradient:null==a?void 0:a.image,range:o,discardOut:r,voidRange:s},e))}if(t instanceof Ht&&(i=n),!i)return;return new ie(i)}}export{Jt as ColorFogPointsMaterial,xe as ExampleVolumeMaterial_1,ye as ExampleVolumeMaterial_Cloud,we as ExampleVolumeMaterial_Perlin,Zt as FogPointsMaterial,Bt as GradientData3DTexture,$t as GradientFogPointsMaterial,Lt as GradientVolumeMaterial,Me as HeatMapPlugin,Mt as ImageData3DSlice,Kt as ImageData3DTexture,ie as ImageData3DTextureSlice,Ht as ImageVolumeMaterial,ee as SliceMaterial,ne as SliceMesh,Xt as SphereFogMaterial,Vt as VolumeFit,Et as VolumeMaterial,jt as VolumeMesh,ge as VolumeRenderStyle,re as computeHeatData3DForPoint,Qt as createColorFogPoints,kt as createGradientData3DTexture,te as createGradientFogPoints,se as createHeatData3D,Wt as createImageData3DTextureByExtrudeImage,Yt as createImageData3DTextureFromGradient,me as createLineData3D,W as createLinearGradientImageData,Ct as createLinearGradientTexture,ht as data2DCoordToIndex,vt as data2DIndexToCoord,at as data3DCoordToIndex,ot as data3DIndexToCoord,Me as default,pt as extrudeImage,mt as extrudeImageData,ft as extrudeImageDataOnAxis,xt as getData2DItem,gt as getData2DItemSafe,wt as getData2DRow,yt as getData2DValue,_t as getData2DValueSafe,st as getData3DItem,rt as getData3DItemSafe,dt as getData3DSlice,ct as getData3DValue,lt as getData3DValueSafe,Q as getImageDateColor,Y as getImageDateOfImage,J as getImageDateRow,X as getNaturalSizeOfImageSource,qt as gradientData3DToImageData3D,ce as hollowGradient_Default,$ as imageDataToCanvas,tt as imageDataToUrl,et as isIImageData2,nt as isIImageData3,it as isOutOfSize,ue as lineValueGradient_Default,Gt as makeOriginOnBoundingBoxMinOfGeometry,ut as mergeData3Ds,de as numberValuesAccumulate_Default,he as optimizeGradientOptions,le as radiusGradient_Default,Z as reverseImageDateY,pe as transformGradientOptions,fe as translateScaleGradientOptions,ae as valueGradient_Default,oe as valuesAccumulate_Default};
1
+ import { TextureLoader, Texture, Matrix3, Vector3, Vector4, Vector2, AlphaFormat, RedFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAFormat, RGBAIntegerFormat, LuminanceFormat, LuminanceAlphaFormat, DepthFormat, DepthStencilFormat, ShaderMaterial, GLSL3, Matrix4, DoubleSide, Mesh, BoxGeometry, Data3DTexture, FloatType, LinearFilter, UnsignedByteType, Color, FrontSide, UniformsUtils, ShaderLib, Points, PlaneGeometry, Box3, Line3, Quaternion, BackSide, RawShaderMaterial, BufferGeometry, Float32BufferAttribute, Uint8ClampedBufferAttribute } from 'three';
2
+ import SoonSpace from 'soonspacejs';
3
+
4
+ var f$1 = /* @__PURE__ */ ((n) => (n[n.x = 0] = "x", n[n.y = 1] = "y", n[n.z = 2] = "z", n))(f$1 || {});
5
+ ((n) => {
6
+ function t(r) {
7
+ return n[r];
8
+ }
9
+ n.toKey = t;
10
+ function e(r) {
11
+ return n[r];
12
+ }
13
+ n.toIndex = e;
14
+ function o(r) {
15
+ const c = (r + 1) % 3, i = (r + 2) % 3;
16
+ return [c, i];
17
+ }
18
+ n.getCrossAxiss = o;
19
+ })(f$1 || (f$1 = {}));
20
+ var s$1 = /* @__PURE__ */ ((n) => (n[n.x = 0] = "x", n[n.y = 1] = "y", n[n.z = 2] = "z", n[n.w = 3] = "w", n))(s$1 || {});
21
+ ((n) => {
22
+ function t(r) {
23
+ return n[r];
24
+ }
25
+ n.toKey = t;
26
+ function e(r) {
27
+ return n[r];
28
+ }
29
+ n.toIndex = e;
30
+ function o(r) {
31
+ const c = (r + 1) % 4, i = (r + 2) % 4;
32
+ return [c, i];
33
+ }
34
+ n.getCrossAxiss = o;
35
+ })(s$1 || (s$1 = {}));
36
+
37
+ var f = /* @__PURE__ */ ((n) => (n[n.x = 0] = "x", n[n.y = 1] = "y", n[n.z = 2] = "z", n))(f || {});
38
+ ((n) => {
39
+ function t(r) {
40
+ return n[r];
41
+ }
42
+ n.toKey = t;
43
+ function e(r) {
44
+ return n[r];
45
+ }
46
+ n.toIndex = e;
47
+ function o(r) {
48
+ const c = (r + 1) % 3, i = (r + 2) % 3;
49
+ return [c, i];
50
+ }
51
+ n.getCrossAxiss = o;
52
+ })(f || (f = {}));
53
+ var s = /* @__PURE__ */ ((n) => (n[n.x = 0] = "x", n[n.y = 1] = "y", n[n.z = 2] = "z", n[n.w = 3] = "w", n))(s || {});
54
+ ((n) => {
55
+ function t(r) {
56
+ return n[r];
57
+ }
58
+ n.toKey = t;
59
+ function e(r) {
60
+ return n[r];
61
+ }
62
+ n.toIndex = e;
63
+ function o(r) {
64
+ const c = (r + 1) % 4, i = (r + 2) % 4;
65
+ return [c, i];
66
+ }
67
+ n.getCrossAxiss = o;
68
+ })(s || (s = {}));
69
+
70
+ function B$1(e, t, n, a = "srgb") {
71
+ const i = new OffscreenCanvas(t, n).getContext("2d"), o = i.createLinearGradient(0, 0, 256, 1);
72
+ for (const [c, r] of e)
73
+ o.addColorStop(Number(c), r);
74
+ return i.fillStyle = o, i.fillRect(0, 0, t, n), i.getImageData(0, 0, t, n, { colorSpace: a });
75
+ }
76
+ function _$1(e, t) {
77
+ const { x: n, y: a } = t;
78
+ return e.z * a * n + e.y * n + e.x;
79
+ }
80
+ function $$1(e, t, n = 1) {
81
+ let { x: a, y: s, z: i } = t;
82
+ const o = e.size;
83
+ return a = Math.max(0, Math.min(o.x - 1, a)), s = Math.max(0, Math.min(o.y - 1, s)), i = Math.max(0, Math.min(o.z - 1, i)), U$1(e, { x: a, y: s, z: i }, n);
84
+ }
85
+ function U$1(e, t, n = 1) {
86
+ const { data: a, size: s } = e, i = _$1(t, s);
87
+ let o = [];
88
+ if (n > 0) {
89
+ const c = i * n;
90
+ for (let r = 0; r < n; r++)
91
+ o.push(a[c + r]);
92
+ }
93
+ return { index: i, value: o };
94
+ }
95
+ function E$1(e, t, n, a = 1) {
96
+ const { size: s } = e, i = f.toKey(t), [o, c] = f.getCrossAxiss(t), r = f.toKey(o), u = f.toKey(c), h = s[r], g = s[u], l = [], f$1 = s[i];
97
+ n = Math.trunc(n), n = Math.max(0, Math.min(f$1 - 1, n));
98
+ let x = { x: 0, y: 0, z: 0 };
99
+ x[i] = n;
100
+ for (let m = 0; m < g; m++) {
101
+ x[u] = m;
102
+ for (let d = 0; d < h; d++) {
103
+ x[r] = d;
104
+ const { value: y } = U$1(e, x, a);
105
+ l.push(...y);
106
+ }
107
+ }
108
+ return { data: l, size: { x: h, y: g } };
109
+ }
110
+
111
+ var zt = Object.defineProperty;
112
+ var Ut$1 = (t, n, e) => n in t ? zt(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e;
113
+ var j$1 = (t, n, e) => (Ut$1(t, typeof n != "symbol" ? n + "" : n, e), e);
114
+ function Pt$1(t) {
115
+ return t.w !== void 0 ? [Vector4, 4] : t.z !== void 0 ? [Vector3, 3] : [Vector2, 2];
116
+ }
117
+ function En(t) {
118
+ const n = t.length, e = [];
119
+ if (n === 0)
120
+ return e;
121
+ const [o, s] = Pt$1(t[0]);
122
+ for (let c = 0; c < n; c++) {
123
+ const r = t[c], i = new o().copy(r), l = r.radius, u = e[c] ?? (e[c] = []);
124
+ for (let a = c + 1; a < n; a++) {
125
+ const f = t[a];
126
+ i.distanceToSquared(f) <= (f.radius + l) ** 2 && (u.push(a), (e[a] = []).push(c));
127
+ }
128
+ }
129
+ return e;
130
+ }
131
+ let Tt$1;
132
+ function Gn(t) {
133
+ if (typeof t == "string")
134
+ return (Tt$1 || (Tt$1 = new TextureLoader())).load(t);
135
+ if (t.isTexture)
136
+ return t;
137
+ const n = Array.isArray(t) ? B$1(t, 256, 1) : t, e = new Texture(n);
138
+ return n.colorSpace === "srgb" && (e.colorSpace = "srgb"), e.needsUpdate = !0, e;
139
+ }
140
+ function an(t, n) {
141
+ const e = Math.sqrt(t.lengthSq() * n.lengthSq());
142
+ if (e === 0)
143
+ return 0;
144
+ let o = t.dot(n) / e;
145
+ return o = Math.max(-1, Math.min(1, o)), Math.acos(o);
146
+ }
147
+ function J$1(t, n, e) {
148
+ let o = an(t, n);
149
+ return o === 0 ? o : t.clone().cross(n).dot(e) < 0 ? -o : o;
150
+ }
151
+ function fn$1(t, n, e) {
152
+ const o = n.clone().negate(), s = e.clone().projectOnPlane(n), c = t.clone().projectOnPlane(s), r = J$1(n, c, s), i = n.clone().cross(s), l = t.clone().projectOnPlane(i), u = J$1(n, l, i), a = t.clone().projectOnPlane(o), f = J$1(s, a, o);
153
+ return { yaw: r, pitch: u, roll: f };
154
+ }
155
+ const it$1 = 180 / Math.PI, ut = {
156
+ yaw: [
157
+ { name: "前", range: [-15, 15] },
158
+ { name: "左", range: [15, 165] },
159
+ { name: "右", range: [-165, -15] },
160
+ { name: "后", range: [-180.1, -165] },
161
+ { name: "后", range: [165, 180.1] }
162
+ ],
163
+ pitch: [
164
+ { name: "前", range: [-15, 15] },
165
+ { name: "上", range: [15, 165] },
166
+ { name: "下", range: [-165, -15] },
167
+ { name: "后", range: [-180.1, -165] },
168
+ { name: "后", range: [165, 180.1] }
169
+ ],
170
+ roll: [
171
+ { name: "上", range: [-15, 15] },
172
+ { name: "左", range: [15, 165] },
173
+ { name: "右", range: [-165, -15] },
174
+ { name: "下", range: [-180.1, -165] },
175
+ { name: "下", range: [165, 180.1] }
176
+ ]
177
+ };
178
+ function pn$1(t) {
179
+ const n = {};
180
+ for (const [e, o] of Object.entries(t))
181
+ n[e] = Array.isArray(o) ? o : Object.entries(o).map(([s, c]) => ({ name: s, range: c }));
182
+ return n;
183
+ }
184
+ const lt = {
185
+ degrees: !0,
186
+ map: ut,
187
+ front: { x: 0, y: 0, z: 1 },
188
+ up: { x: 0, y: 1, z: 0 }
189
+ };
190
+ let It$1 = class It {
191
+ constructor(n) {
192
+ j$1(this, "_options");
193
+ j$1(this, "_listMap");
194
+ j$1(this, "_front");
195
+ j$1(this, "_up");
196
+ n && (this.options = n);
197
+ }
198
+ static get options() {
199
+ return this._options ?? (this.options = lt);
200
+ }
201
+ static set options(n) {
202
+ this._options = Object.assign({}, structuredClone(ut), n);
203
+ }
204
+ /**
205
+ * 默认选项
206
+ */
207
+ get defaultOptions() {
208
+ return this.constructor.options;
209
+ }
210
+ get options() {
211
+ return this._options ?? (this.options = this.defaultOptions);
212
+ }
213
+ set options(n) {
214
+ this._options = Object.assign({}, structuredClone(this.defaultOptions), n), this._listMap = null, this._front = null, this._up = null;
215
+ }
216
+ /**
217
+ * 是否使用角度,而非弧度
218
+ */
219
+ get degrees() {
220
+ return this.options.degrees ?? (this.options.degrees = this.defaultOptions.degrees ?? !0);
221
+ }
222
+ set degrees(n) {
223
+ this.options.degrees = n;
224
+ }
225
+ get map() {
226
+ return this.options.map || (this.map = this.defaultOptions.map), this.options.map;
227
+ }
228
+ set map(n) {
229
+ const e = structuredClone(this.defaultOptions.map), o = structuredClone(ut);
230
+ n = n ? {
231
+ yaw: n.yaw ?? e.yaw ?? o.yaw,
232
+ pitch: n.pitch ?? e.pitch ?? o.pitch,
233
+ roll: n.roll ?? e.roll ?? o.roll
234
+ } : e, this.options.map = n, this._listMap = null;
235
+ }
236
+ get listMap() {
237
+ return this._listMap ?? (this._listMap = pn$1(this.map ?? {}));
238
+ }
239
+ get front() {
240
+ return this._front || (this.front = this.options.front ?? this.defaultOptions.front ?? lt.front), this._front;
241
+ }
242
+ set front(n) {
243
+ this._front = new Vector3().copy(n);
244
+ }
245
+ get up() {
246
+ return this._up || (this.up = this.options.up ?? this.defaultOptions.up ?? lt.up), this._up;
247
+ }
248
+ set up(n) {
249
+ this._up = new Vector3().copy(n);
250
+ }
251
+ /**
252
+ * 计算方位
253
+ * @param target
254
+ * @param front
255
+ * @param up
256
+ */
257
+ computeAzimuth(n, e, o) {
258
+ const s = new Vector3().copy(n), c = new Vector3().copy(e ?? this.front), r = new Vector3().copy(o ?? this.up);
259
+ let { yaw: i, pitch: l, roll: u } = fn$1(s, c, r);
260
+ return this.degrees && (i *= it$1, l *= it$1, u *= it$1), {
261
+ yaw: {
262
+ angle: i,
263
+ name: this.findAzimuthNames("yaw", i)
264
+ },
265
+ pitch: {
266
+ angle: l,
267
+ name: this.findAzimuthNames("pitch", l)
268
+ },
269
+ roll: {
270
+ angle: u,
271
+ name: this.findAzimuthNames("roll", u)
272
+ }
273
+ };
274
+ }
275
+ /**
276
+ * 查找匹配的方位名字
277
+ * @param type - 类型
278
+ * @param angle - 角度
279
+ * @returns 匹配的名字列表
280
+ */
281
+ findAzimuthNames(n, e) {
282
+ const o = [], s = this.listMap[n];
283
+ if (!s)
284
+ return o;
285
+ for (const { name: c, range: [r, i] } of s)
286
+ (e >= r && e < i || e <= r && e > i) && o.push(c);
287
+ return o;
288
+ }
289
+ };
290
+ j$1(It$1, "_options");
291
+ new It$1(); const mn$1 = {
292
+ [AlphaFormat]: 1,
293
+ [RedFormat]: 1,
294
+ [RedIntegerFormat]: 1,
295
+ [RGFormat]: 3,
296
+ [RGIntegerFormat]: 2,
297
+ [RGBAFormat]: 4,
298
+ [RGBAIntegerFormat]: 4,
299
+ [LuminanceFormat]: 1,
300
+ [LuminanceAlphaFormat]: 2,
301
+ [DepthFormat]: 1,
302
+ [DepthStencilFormat]: 2
303
+ };
304
+ function Mt(t) {
305
+ return mn$1[t];
306
+ }
307
+ function Yn(t, n, e) {
308
+ const { data: o, width: s, height: c, depth: r } = t.image, i = Mt(t.format);
309
+ return E$1({ data: o, size: { x: s, y: c, z: r } }, n, e, i);
310
+ }
311
+ function Zn(t, n) {
312
+ const { data: e, width: o, height: s, depth: c } = t.image, r = Mt(t.format);
313
+ return $$1({ data: e, size: { x: o, y: s, z: c } }, n, r);
314
+ }
315
+ new Matrix3();
316
+
317
+ var T = Object.defineProperty;
318
+ var R = (e, t, n) => t in e ? T(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
319
+ var D = (e, t, n) => (R(e, typeof t != "symbol" ? t + "" : t, n), n);
320
+ function B(e, t, n, a = "srgb") {
321
+ const i = new OffscreenCanvas(t, n).getContext("2d"), o = i.createLinearGradient(0, 0, 256, 1);
322
+ for (const [c, r] of e)
323
+ o.addColorStop(Number(c), r);
324
+ return i.fillStyle = o, i.fillRect(0, 0, t, n), i.getImageData(0, 0, t, n, { colorSpace: a });
325
+ }
326
+ function K(e, t) {
327
+ let { area: n, width: a, height: s, colorSpace: i } = t || {};
328
+ i = i ?? "srgb", n = n || {};
329
+ const o = n.x ?? 0, c = n.y ?? 0, r = b(e), u = n.width ?? r.width, h = n.height ?? r.height;
330
+ a = a ?? u, s = s ?? h;
331
+ const l = new OffscreenCanvas(a, s).getContext("2d");
332
+ return l.drawImage(e, o, c, u, h, 0, 0, a, s), l.getImageData(0, 0, a, s, { colorSpace: i });
333
+ }
334
+ function b(e) {
335
+ let t = 0, n = 0;
336
+ return e instanceof HTMLImageElement ? (t = e.naturalWidth, n = e.naturalHeight) : e instanceof HTMLVideoElement ? (t = e.videoWidth, n = e.videoHeight) : (t = e.width, n = e.height), { width: t, height: n };
337
+ }
338
+ function V(e) {
339
+ const { data: t, width: n, height: a, colorSpace: s } = e, i = t.length, o = new Uint8ClampedArray(i);
340
+ for (let c = 0; c < a; c++) {
341
+ const r = c * n, u = -(r + n), h = u + n, g = t.slice(u * 4, h * 4);
342
+ o.set(g, r * 4);
343
+ }
344
+ return new ImageData(o, n, a, { colorSpace: s });
345
+ }
346
+ function F(e, t) {
347
+ const { data: n, width: a } = e, s = t * a, i = s + a;
348
+ return n.slice(s * 4, i * 4);
349
+ }
350
+ function H(e, t, n) {
351
+ const { data: a, width: s } = e, o = (t * s + n) * 4;
352
+ return a.slice(o, o + 4);
353
+ }
354
+ function Y(e) {
355
+ const t = document.createElement("canvas"), n = t.getContext("2d");
356
+ return t.width = e.width, t.height = e.height, n.putImageData(e, 0, 0), t;
357
+ }
358
+ function J(e) {
359
+ return Y(e).toDataURL();
360
+ }
361
+ function L(e) {
362
+ return e && e.data != null && e.width != null && e.height != null;
363
+ }
364
+ function P(e) {
365
+ return L(e) && e.depth != null;
366
+ }
367
+ function Q(e, t) {
368
+ for (const [n, a] of Object.entries(e))
369
+ if (0 <= a && a <= t[n])
370
+ return !0;
371
+ return !1;
372
+ }
373
+ function _(e, t) {
374
+ const { x: n, y: a } = t;
375
+ return e.z * a * n + e.y * n + e.x;
376
+ }
377
+ function Z(e, t) {
378
+ const { x: n, y: a } = t, s = Math.trunc(e / n), i = e - s * n, o = Math.trunc(s / a), c = s - o * a;
379
+ return { x: i, y: c, z: o };
380
+ }
381
+ function $(e, t, n = 1) {
382
+ let { x: a, y: s, z: i } = t;
383
+ const o = e.size;
384
+ return a = Math.max(0, Math.min(o.x - 1, a)), s = Math.max(0, Math.min(o.y - 1, s)), i = Math.max(0, Math.min(o.z - 1, i)), U(e, { x: a, y: s, z: i }, n);
385
+ }
386
+ function U(e, t, n = 1) {
387
+ const { data: a, size: s } = e, i = _(t, s);
388
+ let o = [];
389
+ if (n > 0) {
390
+ const c = i * n;
391
+ for (let r = 0; r < n; r++)
392
+ o.push(a[c + r]);
393
+ }
394
+ return { index: i, value: o };
395
+ }
396
+ function tt(e, t) {
397
+ let { x: n, y: a, z: s } = t;
398
+ const i = e.size;
399
+ return n = Math.max(0, Math.min(i.x - 1, n)), a = Math.max(0, Math.min(i.y - 1, a)), s = Math.max(0, Math.min(i.z - 1, s)), N(e, { x: n, y: a, z: s });
400
+ }
401
+ function N(e, t) {
402
+ const { data: n, size: a } = e, s = _(t, a);
403
+ return { index: s, value: n[s] };
404
+ }
405
+ function et(e, t) {
406
+ const { voidValue: n, valuesAccumulate: a, verifyVoid: s = () => !1 } = t;
407
+ let { x: i, y: o, z: c } = e[0].size;
408
+ const r = e.length;
409
+ for (let l = 1; l < r; l++) {
410
+ const f = e[l].size;
411
+ i = Math.max(i, f.x), o = Math.max(o, f.y), c = Math.max(c, f.z);
412
+ }
413
+ const u = i * o * c, h = new Array(u), g = i * o;
414
+ for (let l = 0; l < c; l++) {
415
+ const f = l * g;
416
+ for (let x = 0; x < o; x++) {
417
+ const m = f + x * i;
418
+ for (let d = 0; d < i; d++) {
419
+ const y = m + d, v = { x: d, y: x, z: l }, M = [];
420
+ for (const I of e) {
421
+ const p = I.size;
422
+ if (d < p.x && x < p.y && l < p.z)
423
+ continue;
424
+ const { index: C, value: A } = N(I, v);
425
+ s(A, I, C) || M.push({ value: A, index: C, data3D: I, coord: v });
426
+ }
427
+ const S = M.length;
428
+ let w = n;
429
+ S > 1 ? w = a(M) : S === 1 && (w = M[0].value), h[y] = w;
430
+ }
431
+ }
432
+ }
433
+ return {
434
+ data: h,
435
+ size: { x: i, y: o, z: c }
436
+ };
437
+ }
438
+ function E(e, t, n, a = 1) {
439
+ const { size: s } = e, i = f$1.toKey(t), [o, c] = f$1.getCrossAxiss(t), r = f$1.toKey(o), u = f$1.toKey(c), h = s[r], g = s[u], l = [], f = s[i];
440
+ n = Math.trunc(n), n = Math.max(0, Math.min(f - 1, n));
441
+ let x = { x: 0, y: 0, z: 0 };
442
+ x[i] = n;
443
+ for (let m = 0; m < g; m++) {
444
+ x[u] = m;
445
+ for (let d = 0; d < h; d++) {
446
+ x[r] = d;
447
+ const { value: y } = U(e, x, a);
448
+ l.push(...y);
449
+ }
450
+ }
451
+ return { data: l, size: { x: h, y: g } };
452
+ }
453
+ function W(e, t, n) {
454
+ t = Math.trunc(t);
455
+ const { data: a, width: s, height: i, colorSpace: o } = n ? V(e) : e, c = a.length, r = c * t, u = new Uint8ClampedArray(r);
456
+ for (let h = 0; h < t; h++)
457
+ u.set(a, h * c);
458
+ return { data: u, width: s, height: i, depth: t, colorSpace: o };
459
+ }
460
+ function nt(e, t, n) {
461
+ const a = n || {}, s = a.reverseY, i = a.axis ?? "z", o = L(e) ? e : K(e, a);
462
+ return i === "z" ? W(o, t, s) : X(o, i, t, s);
463
+ }
464
+ function X(e, t, n, a) {
465
+ n = Math.trunc(n);
466
+ const { data: s, width: i, height: o, colorSpace: c } = a ? V(e) : e, r = f$1.toKey(t), u = (t + 1) % 3, h = (t + 2) % 3, g = f$1.toKey(u), l = f$1.toKey(h), f = {
467
+ [g]: i,
468
+ [l]: o,
469
+ [r]: n
470
+ }, x = new Uint8ClampedArray(s.length * n), m = { x: 0, y: 0, z: 0 };
471
+ for (let d = 0; d < n; d++) {
472
+ m[r] = d;
473
+ for (let y = 0; y < o; y++) {
474
+ m[l] = y;
475
+ for (let v = 0; v < i; v++) {
476
+ m[g] = v;
477
+ const S = (y * i + v) * 4, w = S + 4, I = s.subarray(S, w), C = _(m, f) * 4;
478
+ x.set(I, C);
479
+ }
480
+ }
481
+ }
482
+ return { data: x, width: f.x, height: f.y, depth: f.z, colorSpace: c };
483
+ }
484
+ function O(e, t) {
485
+ return e.y * t.x + e.x;
486
+ }
487
+ function at$1(e, t) {
488
+ const { x: n } = t, a = Math.trunc(e / n);
489
+ return { x: e - a * n, y: a };
490
+ }
491
+ function st(e, t, n = 1) {
492
+ let { x: a, y: s } = t;
493
+ const i = e.size;
494
+ return a = Math.max(0, Math.min(i.x - 1, a)), s = Math.max(0, Math.min(i.y - 1, s)), G(e, { x: a, y: s }, n);
495
+ }
496
+ function G(e, t, n = 1) {
497
+ const { data: a, size: s } = e, i = O(t, s);
498
+ let o = [];
499
+ if (n > 0) {
500
+ const c = i * n;
501
+ for (let r = 0; r < n; r++)
502
+ o.push(a[c + r]);
503
+ }
504
+ return { index: i, value: o };
505
+ }
506
+ function it(e, t) {
507
+ let { x: n, y: a } = t;
508
+ const s = e.size;
509
+ return n = Math.max(0, Math.min(s.x - 1, n)), a = Math.max(0, Math.min(s.y - 1, a)), j(e, { x: n, y: a });
510
+ }
511
+ function j(e, t) {
512
+ const { data: n, size: a } = e, s = O(t, a);
513
+ return { index: s, value: n[s] };
514
+ }
515
+ function ot$1(e, t, n = 1) {
516
+ const { data: a, size: s } = e, i = s.x, o = t * i, c = o + i;
517
+ return (typeof a.slice == "function" ? a : Array.from(a)).slice(o * n, c * n);
518
+ }
519
+ class ct {
520
+ constructor(t) {
521
+ D(this, "isImageData3DSlice", !0);
522
+ D(this, "_image3D");
523
+ D(this, "_canvas");
524
+ D(this, "_context");
525
+ D(this, "_axis", f$1.z);
526
+ D(this, "_depth", 0);
527
+ D(this, "_sliceSize", null);
528
+ D(this, "_slice");
529
+ this.image3D = t;
530
+ }
531
+ /**
532
+ * 3D图像数据
533
+ */
534
+ get image3D() {
535
+ return this._image3D;
536
+ }
537
+ set image3D(t) {
538
+ this._image3D = t, this.updateSize();
539
+ }
540
+ /**
541
+ * 呈现切片的 canvas 元素
542
+ * @remarks
543
+ * 当 {@link ImageData3DSlice.axis} 或 {@link ImageData3DSlice.depth} 变更时,它会自动更新切片
544
+ */
545
+ get canvas() {
546
+ let t = this._canvas;
547
+ return t || (t = this._canvas = document.createElement("canvas"), t.width = this.sliceSize.x, t.height = this.sliceSize.y), t;
548
+ }
549
+ /**
550
+ * canvas 的 2d 上下文对象
551
+ */
552
+ get context() {
553
+ return this._context ?? (this._context = this.canvas.getContext("2d"));
554
+ }
555
+ /**
556
+ * 轴
557
+ * @remarks
558
+ * 会沿该轴的垂直截面生成切片
559
+ *
560
+ * @defaultValue Axis.z
561
+ */
562
+ get axis() {
563
+ return this._axis;
564
+ }
565
+ set axis(t) {
566
+ this._axis = t, this.updateSize();
567
+ }
568
+ /**
569
+ * 轴上的坐标值
570
+ * @remarks
571
+ * 会在轴的该位置处获取切片
572
+ * @defaultValue 0
573
+ */
574
+ get depth() {
575
+ return this._depth;
576
+ }
577
+ set depth(t) {
578
+ this._depth = t, this.updateSlice();
579
+ }
580
+ /**
581
+ * 切片的尺寸
582
+ * @remarks
583
+ * 不同轴上的切片的尺寸一般不一样
584
+ */
585
+ get sliceSize() {
586
+ let t = this._sliceSize;
587
+ if (!t) {
588
+ const { axis: n, image3D: a } = this, { width: s, height: i, depth: o } = a, [c, r] = f$1.getCrossAxiss(n), u = [s, i, o];
589
+ this._sliceSize = t = {
590
+ x: u[c],
591
+ y: u[r]
592
+ };
593
+ }
594
+ return t;
595
+ }
596
+ /**
597
+ * 获取切片数据
598
+ * @remarks
599
+ * 总是获取当前轴和深度处的切片
600
+ */
601
+ get slice() {
602
+ return this._slice ?? (this._slice = this.getSlice(this.axis, this.depth));
603
+ }
604
+ /**
605
+ * 获取切片数据
606
+ * @remarks
607
+ * 可以指定轴和深度;该方法不会更新 {@link ImageData3DSlice.axis} 和 {@link ImageData3DSlice.depth} 属性
608
+ * @param axis - 轴
609
+ * @param depth - 深度
610
+ * @returns
611
+ */
612
+ getSlice(t, n) {
613
+ const { data: a, width: s, height: i, depth: o, colorSpace: c } = this.image3D, { data: r, size: u } = E({ data: a, size: { x: s, y: i, z: o } }, t, n, 4), h = r instanceof Uint8ClampedArray ? r : Uint8ClampedArray.from(r);
614
+ return new ImageData(h, u.x, u.y, { colorSpace: c });
615
+ }
616
+ /**
617
+ * 获取切片图像的 url
618
+ * @returns
619
+ */
620
+ getDataURL() {
621
+ return this.canvas.toDataURL();
622
+ }
623
+ /**
624
+ * 获取切片上指定坐标处的颜色
625
+ * @param coord - 坐标
626
+ * @returns
627
+ */
628
+ getColor(t) {
629
+ const { x: n, y: a } = t;
630
+ return H(this.slice, a, n);
631
+ }
632
+ /**
633
+ * 更新切片尺寸相关的信息
634
+ */
635
+ updateSize() {
636
+ this._sliceSize = null;
637
+ const t = this.canvas;
638
+ t.width = this.sliceSize.x, t.height = this.sliceSize.y, this.updateSlice();
639
+ }
640
+ /**
641
+ * 更新切片相关的信息
642
+ */
643
+ updateSlice() {
644
+ this._slice = null, this.context.putImageData(this.slice, 0, 0);
645
+ }
646
+ }
647
+
648
+ var at = Object.defineProperty;
649
+ var ot = (o, s, e) => s in o ? at(o, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[s] = e;
650
+ var v = (o, s, e) => (ot(o, typeof s != "symbol" ? s + "" : s, e), e);
651
+ const St = `precision highp sampler3D;
652
+
653
+ uniform sampler3D map;
654
+ uniform vec3 containerMin;
655
+ uniform vec3 containerMax;
656
+
657
+ // 0: 充满;1: 对齐;2: 原始
658
+ uniform int fit;
659
+
660
+
661
+ out vec3 cameraPos;
662
+ out vec3 lookDir;
663
+ out vec3 displayMin;
664
+ out vec3 displayMax;
665
+
666
+
667
+
668
+ void main() {
669
+ cameraPos = vec3( inverse( modelMatrix ) * vec4( cameraPosition, 1.0 ) ).xyz;
670
+ lookDir = position - cameraPos;
671
+
672
+ vec3 containerSize = containerMax - containerMin;
673
+ vec3 origin = containerMin;
674
+ vec3 textSize = vec3(textureSize(map,0));
675
+ displayMin = containerMin;
676
+ displayMax = containerMax;
677
+
678
+ switch (fit) {
679
+ case 1:
680
+ displayMax = displayMin + textSize;
681
+ break;
682
+ case 2:
683
+ origin = vec3(0.0);
684
+ break;
685
+ default:
686
+ textSize = containerSize;
687
+ }
688
+
689
+ vec3 scale = 1.0/textSize;
690
+ cameraPos = (cameraPos - origin)*scale;
691
+ lookDir *= scale;
692
+
693
+ displayMin = max((displayMin - origin)*scale,vec3(0.0));
694
+ displayMax = min((displayMax - origin)*scale,vec3(1.0));
695
+
696
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
697
+ }`;
698
+ var Dt = /* @__PURE__ */ ((o) => (o[o.Fill = 0] = "Fill", o[o.Align = 1] = "Align", o[o.Raw = 2] = "Raw", o))(Dt || {});
699
+ class Xe extends ShaderMaterial {
700
+ constructor(e) {
701
+ const { map: t, opacity: n, accFactor: i, steps: a, alphaRange: r, fit: l, atomize: u, side: c, containerMin: p, containerMax: m, uniforms: f, ...h } = e ?? {}, _ = n ?? 1, M = i ?? 1, S = a ?? 100, D = new Vector2().copy(r ?? { x: 0, y: 0.95 }), w = l ?? 0, x = u ?? !0, y = c ?? FrontSide, g = new Vector3().copy(p ?? { x: 0, y: 0, z: 0 }), z = new Vector3();
702
+ if (m)
703
+ z.copy(m);
704
+ else if (t) {
705
+ const { width: U, height: T, depth: C } = t.image, V = new Vector3(U - 1, T - 1, C - 1);
706
+ z.addVectors(g, V);
707
+ }
708
+ const N = {
709
+ map: { value: t },
710
+ containerMin: { value: g },
711
+ containerMax: { value: z },
712
+ fit: { value: w },
713
+ opacity: { value: _ },
714
+ alphaRange: { value: D },
715
+ accFactor: { value: M },
716
+ steps: { value: S },
717
+ isDoubleSide: { value: !1 },
718
+ atomize: { value: x },
719
+ ...f
720
+ };
721
+ super({
722
+ glslVersion: GLSL3,
723
+ // @ts-ignore
724
+ uniforms: N,
725
+ transparent: !0,
726
+ vertexShader: St,
727
+ ...h
728
+ });
729
+ v(this, "isVolumeMaterial", !0);
730
+ v(this, "_side", FrontSide);
731
+ this.opacity = _, this.side = y;
732
+ }
733
+ /**
734
+ * 三维的纹理
735
+ */
736
+ get map() {
737
+ return this.uniforms.map.value;
738
+ }
739
+ set map(e) {
740
+ this.uniforms.map.value = e, this.uniformsNeedUpdate = !0;
741
+ }
742
+ /**
743
+ * 渲染体积材质的容器的最小点
744
+ * @remarks
745
+ * 容器的最小点和最大点一般是被设置成 geometry 的AABB包围盒;但也可以不是
746
+ * 总之,体积材质的渲染依托于 geometry 的形状,它不会超出 geometry 的尺寸;
747
+ * 但可以控制容器的最小点和最大点来控制体积材质的渲染尺寸;
748
+ */
749
+ get containerMin() {
750
+ return this.uniforms.containerMin.value;
751
+ }
752
+ set containerMin(e) {
753
+ this.uniforms.containerMin.value.copy(e), this.uniformsNeedUpdate = !0;
754
+ }
755
+ /**
756
+ * 渲染体积材质的容器的最大点
757
+ * @remarks
758
+ * 容器的最小点和最大点一般是被设置成 geometry 的AABB包围盒;但也可以不是
759
+ * 总之,体积材质的渲染依托于 geometry 的形状,它不会超出 geometry 的尺寸;
760
+ * 但可以控制容器的最小点和最大点来控制体积材质的渲染尺寸;
761
+ */
762
+ get containerMax() {
763
+ return this.uniforms.containerMax.value;
764
+ }
765
+ set containerMax(e) {
766
+ this.uniforms.containerMax.value.copy(e), this.uniformsNeedUpdate = !0;
767
+ }
768
+ /**
769
+ * 渲染体积材质容器的尺寸
770
+ * @remarks
771
+ * 每次调用都会重新计算
772
+ */
773
+ get containerSize() {
774
+ return this.containerMax.clone().sub(this.containerMin);
775
+ }
776
+ /**
777
+ * 体积材质在容器内的填充模式
778
+ * @defaultValue VolumeFit.Fill
779
+ */
780
+ get fit() {
781
+ return this.uniforms.fit.value;
782
+ }
783
+ set fit(e) {
784
+ this.uniforms.fit.value = e, this.uniformsNeedUpdate = !0;
785
+ }
786
+ /**
787
+ * 获取当前填模式下对 map 的应用的平移
788
+ * @returns
789
+ */
790
+ getFitTranslate() {
791
+ return this.fit === 2 ? new Vector3() : this.containerMin.clone();
792
+ }
793
+ /**
794
+ * 获取当前填模式下对 map 的应用的缩放
795
+ * @returns
796
+ */
797
+ getFitScale() {
798
+ var a;
799
+ const e = new Vector3(1, 1, 1), t = (a = this.map) == null ? void 0 : a.image, n = this.fit;
800
+ if (!t || n === 2 || n === 1)
801
+ return e;
802
+ const i = new Vector3(t.width, t.height, t.depth);
803
+ return e.copy(this.containerSize).divide(i), e;
804
+ }
805
+ /**
806
+ * 获取当前填模式下对 map 的应用的变换矩阵
807
+ * @returns
808
+ */
809
+ getFitMatrix() {
810
+ var i;
811
+ const e = new Matrix4(), t = (i = this.map) == null ? void 0 : i.image, n = this.fit;
812
+ if (!t || n === 2)
813
+ return e;
814
+ if (n === 0) {
815
+ const a = new Vector3(t.width, t.height, t.depth), l = this.containerSize.divide(a);
816
+ e.makeScale(l.x, l.y, l.z);
817
+ }
818
+ return e.setPosition(this.containerMin), e;
819
+ }
820
+ /**
821
+ * 获取当前填模式下对 map 的应用的变换矩阵的逆矩阵
822
+ * @returns
823
+ */
824
+ getFitMatrixInvert() {
825
+ return this.getFitMatrix().invert();
826
+ }
827
+ /**
828
+ * Mesh三角形的渲染面
829
+ * @remarks
830
+ * 可设置为前面、后面、或者两面都渲染
831
+ * 如果只渲染前面,进入体积材质内部,体积材质就会消失
832
+ * 如果只渲染后面,体积初遮挡,就会消失
833
+ * 如果两面都渲染,则会隐藏看到容器的面
834
+ */
835
+ // @ts-ignore
836
+ get side() {
837
+ return this._side;
838
+ }
839
+ set side(e) {
840
+ this._side = e, this.uniforms && (this.uniforms.isDoubleSide.value = e === DoubleSide, this.uniformsNeedUpdate = !0);
841
+ }
842
+ /**
843
+ * 透明度
844
+ * @remarks
845
+ * 决定整体的透明度
846
+ */
847
+ // @ts-ignore
848
+ get opacity() {
849
+ return this.uniforms.opacity.value;
850
+ }
851
+ set opacity(e) {
852
+ this.uniforms && (this.uniforms.opacity.value = e), this.uniformsNeedUpdate = !0;
853
+ }
854
+ /**
855
+ * 有效透明度的取值范围
856
+ * @remarks
857
+ * 如果最终颜色的透明度小于或等于 alphaRange.x ,则被认为是完全透明
858
+ * 如果最终颜色的透明度在于或等于 alphaRange.y ,则被认为是完全不透明
859
+ * 取值范围应当在 0 - 1
860
+ * @defaultValue {x:0,y:0.95}
861
+ */
862
+ get alphaRange() {
863
+ return this.uniforms.alphaRange.value;
864
+ }
865
+ set alphaRange(e) {
866
+ this.uniforms.alphaRange.value.copy(e), this.uniformsNeedUpdate = !0;
867
+ }
868
+ /**
869
+ * 是否开启雾化的效果
870
+ * @remarks
871
+ * 开启后的渲染效果会更像雾
872
+ * @defaultValue true
873
+ */
874
+ get atomize() {
875
+ return this.uniforms.atomize.value;
876
+ }
877
+ set atomize(e) {
878
+ this.uniforms.atomize.value = e, this.uniformsNeedUpdate = !0;
879
+ }
880
+ /**
881
+ * 体积材质渲染的采样数
882
+ * @remarks
883
+ * 采样数越高,占用的GPU资源就越大;所以该数据设置的适宜最好;
884
+ * @defaultValue 100
885
+ */
886
+ get steps() {
887
+ return this.uniforms.steps.value;
888
+ }
889
+ set steps(e) {
890
+ this.uniforms.steps.value = e, this.uniformsNeedUpdate = !0;
891
+ }
892
+ /**
893
+ * 颜色累积系数
894
+ * @remarks
895
+ * 它是对体积材质进行积分时使用的系数;只在开启雾化效果{@link VolumeMaterial.atomize}时才有效;
896
+ * 值越小,最终呈现出的效果就越雾化;
897
+ * @defaultValue 1
898
+ */
899
+ get accFactor() {
900
+ return this.uniforms.accFactor.value;
901
+ }
902
+ set accFactor(e) {
903
+ this.uniforms && (this.uniforms.accFactor.value = e), this.uniformsNeedUpdate = !0;
904
+ }
905
+ /**
906
+ * 将材质空间下的坐标转为 map 空间下的坐标
907
+ * @param coord - 材质空间下的坐标
908
+ * @returns
909
+ */
910
+ toMapPosition(e) {
911
+ const t = new Vector3(e.x, e.y, e.z).applyMatrix4(this.getFitMatrixInvert());
912
+ return t.set(Math.trunc(t.x), Math.trunc(t.y), Math.trunc(t.z)), t;
913
+ }
914
+ /**
915
+ * 将材质空间下的深度转为 map 空间下的深度
916
+ * @param axis - map坐标系下的坐标轴
917
+ * @param depth - 材质空间下的深度
918
+ * @returns
919
+ */
920
+ toMapDepth(e, t) {
921
+ const n = f$1.toKey(e), i = new Vector3();
922
+ i[n] = 1;
923
+ const a = new Matrix3().setFromMatrix4(this.getFitMatrix());
924
+ return i.applyMatrix3(a), t /= i.length(), Math.trunc(t);
925
+ }
926
+ /**
927
+ * 获取3D数据的切片
928
+ * @remarks
929
+ * 切片就是指定轴的指定位置的垂直截面
930
+ * @param axis - map坐标系下的坐标轴
931
+ * @param depth - 材质空间下,在轴方向的坐标值
932
+ * @returns
933
+ */
934
+ getData3DSlice(e, t) {
935
+ const n = this.map;
936
+ return n != null && n.image ? (t = this.toMapDepth(e, t), Yn(n, e, t)) : null;
937
+ }
938
+ /**
939
+ * 获取3D数据中指定坐标处的数据项目
940
+ * @param coord
941
+ * @returns
942
+ */
943
+ getItem(e) {
944
+ const t = this.map;
945
+ return t != null && t.image ? Zn(t, this.toMapPosition(e)).value : null;
946
+ }
947
+ }
948
+ function bt(o) {
949
+ o.boundingBox || o.computeBoundingBox();
950
+ const { x: s, y: e, z: t } = o.boundingBox.min;
951
+ return o.translate(-s, -e, -t), o;
952
+ }
953
+ class rn extends Mesh {
954
+ constructor(e) {
955
+ var r;
956
+ const { width: t, height: n, depth: i } = ((r = e.map) == null ? void 0 : r.image) || {}, a = new BoxGeometry(t, n, i);
957
+ bt(a);
958
+ super(a, e);
959
+ v(this, "isVolumeMesh", !0);
960
+ // @ts-ignore
961
+ // override get geometry(){
962
+ // return this._geometry;
963
+ // }
964
+ // override set geometry(value){
965
+ // this._geometry = value;
966
+ // this.configMaterial();
967
+ // }
968
+ v(this, "_geometry");
969
+ /**
970
+ * 是否自动更新材质
971
+ * @remarks
972
+ * 当启动该选项后,在 VolumeMesh 监测到 geometry 变更时,会自动更新体积材质的相关选项,以适应新的 geometry
973
+ * @defaultValue true
974
+ */
975
+ v(this, "autoUpdateMaterial", !0);
976
+ // @ts-ignore
977
+ // override get material(){
978
+ // return this._material;
979
+ // }
980
+ // override set material(value){
981
+ // this._material = value;
982
+ // this.configGeometry();
983
+ // }
984
+ v(this, "_material");
985
+ /**
986
+ * 是否自动更新几何体
987
+ * @remarks
988
+ * 当启动该选项后,在 VolumeMesh 监测到 material 变更时,会自动更新 geometry 的相关选项,以适应新的 体积材质
989
+ * @defaultValue true
990
+ */
991
+ v(this, "autoUpdateGeometry", !0);
992
+ /**
993
+ * 自动规范化
994
+ * @remarks
995
+ * 开启该选项,设置新的 geometry 时,对 geometry 自动执行规范化操作
996
+ */
997
+ v(this, "autoNormalize", !1);
998
+ Object.defineProperties(this, {
999
+ geometry: {
1000
+ get: () => this._geometry,
1001
+ set: (l) => {
1002
+ this._geometry = l, this.autoNormalize ? this.normalize() : this.autoUpdateMaterial && this.updateMaterial();
1003
+ }
1004
+ },
1005
+ material: {
1006
+ get: () => this._material,
1007
+ set: (l) => {
1008
+ this._material = l, this.autoUpdateGeometry && this.updateGeometry();
1009
+ }
1010
+ }
1011
+ }), this.geometry = a, this.material = e;
1012
+ }
1013
+ /**
1014
+ * 更新材质
1015
+ * @remarks
1016
+ * 更新体积材质的相关选项以使其匹配 geometry
1017
+ */
1018
+ updateMaterial() {
1019
+ const { geometry: e, material: t } = this;
1020
+ if (!(t && e))
1021
+ return !1;
1022
+ e.boundingBox || e.computeBoundingBox();
1023
+ const { min: n, max: i } = e.boundingBox;
1024
+ t.containerMin = n, t.containerMax = i;
1025
+ }
1026
+ /**
1027
+ * 更新几何体
1028
+ * @remarks
1029
+ * 更新 geometry 的相关选项以使其匹配体积材质
1030
+ */
1031
+ updateGeometry() {
1032
+ var c;
1033
+ const { geometry: e, material: t, autoUpdateMaterial: n } = this, i = (c = t.map) == null ? void 0 : c.image;
1034
+ if (!i)
1035
+ return !1;
1036
+ e.boundingBox || e.computeBoundingBox();
1037
+ const { width: a, height: r, depth: l } = i, u = e.boundingBox.getSize(new Vector3());
1038
+ e.scale(a / u.x, r / u.y, l / u.z), n && this.updateMaterial();
1039
+ }
1040
+ /**
1041
+ * 规范化
1042
+ * @remarks
1043
+ * 将 geometry 的原点移动到包围盒的最小点处
1044
+ */
1045
+ normalize() {
1046
+ const { geometry: e, autoUpdateMaterial: t } = this;
1047
+ e.boundingBox || e.computeBoundingBox();
1048
+ const { x: n, y: i, z: a } = e.boundingBox.min;
1049
+ e.translate(-n, -i, -a), t && this.updateMaterial();
1050
+ }
1051
+ /**
1052
+ * 将材质空间下的坐标转为 map 空间下的坐标
1053
+ * @param coord - 材质空间下的坐标
1054
+ * @returns
1055
+ */
1056
+ toMapPosition(e) {
1057
+ const t = this.worldToLocal(new Vector3(e.x, e.y, e.z));
1058
+ return this.material.toMapPosition(t);
1059
+ }
1060
+ /**
1061
+ * 将世界坐标系下的深度转为 material 空间下的深度
1062
+ * @param axis - 材质空间下的坐标轴
1063
+ * @param depth - 深度
1064
+ * @returns
1065
+ */
1066
+ toMaterialDepth(e, t) {
1067
+ const n = f$1.toKey(e), i = new Vector3();
1068
+ i[n] = 1;
1069
+ const a = new Matrix3().setFromMatrix4(this.matrixWorld);
1070
+ return i.applyMatrix3(a), t /= i.length(), t;
1071
+ }
1072
+ /**
1073
+ * 将世界坐标系下的深度转为 map 空间下的深度
1074
+ * @param axis - map空间下的坐标轴
1075
+ * @param depth - 深度
1076
+ * @returns
1077
+ */
1078
+ toMapDepth(e, t) {
1079
+ return t = this.toMaterialDepth(e, t), this.material.toMapDepth(e, t);
1080
+ }
1081
+ /**
1082
+ * 获取3D数据的切片
1083
+ * @remarks
1084
+ * 切片就是指定轴的指定位置的垂直截面;
1085
+ * 轴和深度都是局部坐标系下的
1086
+ * @param axis - map空间下的坐标轴
1087
+ * @param depth - 世界空间下在轴方向上的坐标值
1088
+ * @returns
1089
+ */
1090
+ getData3DSlice(e, t) {
1091
+ return t = this.toMaterialDepth(e, t), this.material.getData3DSlice(e, t);
1092
+ }
1093
+ /**
1094
+ * 获取3D数据中指定坐标处的数据项目
1095
+ * @param coord - 世界坐标系下的坐标
1096
+ * @returns
1097
+ */
1098
+ getItem(e) {
1099
+ const t = this.worldToLocal(new Vector3(e.x, e.y, e.z));
1100
+ return this.material.getItem(t);
1101
+ }
1102
+ }
1103
+ const Ct = `precision highp float;
1104
+ precision highp sampler3D;
1105
+
1106
+ uniform sampler3D map;
1107
+ uniform sampler2D gradient;
1108
+
1109
+ uniform bool atomize;
1110
+ uniform float steps;
1111
+ // 颜色累积系数
1112
+ uniform float accFactor;
1113
+ uniform vec2 range;
1114
+ // 是否丢弃超出范围的像素
1115
+ uniform bool discardOut;
1116
+ // 空值范围
1117
+ uniform vec2 voidRange;
1118
+ uniform float opacity;
1119
+ uniform vec2 alphaRange;
1120
+ uniform bool isDoubleSide;
1121
+
1122
+ in vec3 cameraPos;
1123
+ in vec3 lookDir;
1124
+ in vec3 displayMin;
1125
+ in vec3 displayMax;
1126
+ out vec4 fragColor;
1127
+
1128
+ vec4 colorBlend(vec4 near,vec4 far){
1129
+ float nA = near.a;
1130
+ if (nA >= 1.0){
1131
+ return near;
1132
+ }
1133
+ if (nA <= 0.0){
1134
+ return far;
1135
+ }
1136
+
1137
+ float fA = far.a;
1138
+ float a = fA + nA - fA*nA;
1139
+ vec3 color = (far.rgb * fA * (1.0 - nA) + near.rgb*nA)/a;
1140
+ return vec4(color,a);
1141
+ }
1142
+
1143
+
1144
+
1145
+
1146
+ vec2 intersectBox( vec3 orig, vec3 dir ) {
1147
+ vec3 inv_dir = 1.0 / dir;
1148
+ vec3 tmin_tmp = (displayMin - orig ) * inv_dir;
1149
+ vec3 tmax_tmp = (displayMax - orig ) * inv_dir;
1150
+ vec3 tmin = min( tmin_tmp, tmax_tmp );
1151
+ vec3 tmax = max( tmin_tmp, tmax_tmp );
1152
+ float t0 = max( tmin.x, max( tmin.y, tmin.z ) );
1153
+ float t1 = min( tmax.x, min( tmax.y, tmax.z ) );
1154
+ return vec2( t0, t1 );
1155
+ }
1156
+
1157
+ float getValue( vec3 point ) {
1158
+ return texture( map, point ).r;
1159
+ }
1160
+
1161
+ // 获取梯度颜色
1162
+ vec4 getGradientColor(float val) {
1163
+ val = clamp( val, 0.0,1.0);
1164
+ return texture2D(gradient, vec2(val, 0.5));
1165
+ }
1166
+
1167
+
1168
+
1169
+
1170
+ void main(){
1171
+ vec3 rayDir = normalize( lookDir );
1172
+
1173
+ vec2 times = intersectBox( cameraPos, rayDir );
1174
+ float tMin = times.x;
1175
+ float tMax = times.y;
1176
+ if ( tMin > tMax || tMax < 0.0 ) discard;
1177
+ tMin = max( tMin, 0.0 );
1178
+
1179
+ vec3 point = cameraPos + tMin * rayDir;
1180
+
1181
+ float step = 1.0/steps;
1182
+ float opacityFactor = atomize ? step * accFactor : 1.0;
1183
+
1184
+
1185
+ float invRangeLen = 1.0/(range.y - range.x);
1186
+ vec3 stepDir = rayDir * step;
1187
+
1188
+ vec4 finalColor = vec4( 0,0,0,0);
1189
+ float alphaMax = alphaRange.y;
1190
+
1191
+ for ( float t = tMin; t <= tMax; t += step,point += stepDir ) {
1192
+ float val = getValue( point);
1193
+ if (voidRange.x <= val && val <= voidRange.y ) continue;
1194
+ val = (val - range.x) * invRangeLen;
1195
+ if (discardOut && (val < 0.0 || val > 1.0)) continue;
1196
+
1197
+ vec4 gradientColor = getGradientColor(val);
1198
+ gradientColor.a *= opacityFactor;
1199
+ finalColor = colorBlend(finalColor,gradientColor);
1200
+ if ( finalColor.a >= alphaMax ) break;
1201
+ }
1202
+
1203
+ finalColor.a *= opacity;
1204
+ if ( finalColor.a <= alphaRange.x ) discard;
1205
+ if (isDoubleSide){
1206
+ finalColor.a = 1.0 - sqrt(1.0 - finalColor.a);
1207
+ }
1208
+ fragColor = finalColor;
1209
+
1210
+ }`;
1211
+ class sn extends Xe {
1212
+ constructor(e) {
1213
+ const { gradient: t, range: n, discardOut: i, voidRange: a, ...r } = e ?? {}, l = new Vector2().copy(n ?? { x: 0, y: 100 }), u = i ?? !0, c = new Vector2().copy(a ?? { x: -100, y: -1 }), m = {
1214
+ gradient: { value: t == null ? t : Gn(t) },
1215
+ range: { value: l },
1216
+ discardOut: { value: u },
1217
+ voidRange: { value: c }
1218
+ };
1219
+ super({ ...r, fragmentShader: Ct, uniforms: m });
1220
+ v(this, "isGradientVolumeMaterial", !0);
1221
+ }
1222
+ /**
1223
+ * 数值的梯度映射纹理
1224
+ */
1225
+ get gradient() {
1226
+ return this.uniforms.gradient.value;
1227
+ }
1228
+ set gradient(e) {
1229
+ this.uniforms.gradient.value = e, this.uniformsNeedUpdate = !0;
1230
+ }
1231
+ /**
1232
+ * 数值的映射区间
1233
+ * @remarks
1234
+ * x 为最小值,y 为最大值
1235
+ *
1236
+ * @defaultValue {x:0,y:100}
1237
+ */
1238
+ get range() {
1239
+ return this.uniforms.range.value;
1240
+ }
1241
+ set range(e) {
1242
+ this.uniforms.range.value.copy(e), this.uniformsNeedUpdate = !0;
1243
+ }
1244
+ /**
1245
+ * 是否丢弃超出映射范围的数值
1246
+ * @remarks
1247
+ * 当数值超出映射区间 {@link GradientVolumeMaterial.range} 时,是否丢弃;
1248
+ *
1249
+ * 包含左右边界值
1250
+ * @defaultValue true
1251
+ */
1252
+ get discardOut() {
1253
+ return this.uniforms.discardOut.value;
1254
+ }
1255
+ set discardOut(e) {
1256
+ this.uniforms.discardOut.value = e, this.uniformsNeedUpdate = !0;
1257
+ }
1258
+ /**
1259
+ * 空值的范围
1260
+ * @remarks
1261
+ * 当数值在此范围中时,会被认为是空的值,渲染时会被丢弃
1262
+ *
1263
+ * 包含左右边界值
1264
+ *
1265
+ * @defaultValue {x:-100,y:-1}
1266
+ */
1267
+ get voidRange() {
1268
+ return this.uniforms.voidRange.value;
1269
+ }
1270
+ set voidRange(e) {
1271
+ this.uniforms.voidRange.value.copy(e), this.uniformsNeedUpdate = !0;
1272
+ }
1273
+ }
1274
+ class Pt extends Data3DTexture {
1275
+ constructor(e, t, n, i, a) {
1276
+ super(e, t, n, i);
1277
+ v(this, "isGradientData3DTexture", !0);
1278
+ this.format = RedFormat, this.type = a ?? FloatType, this.minFilter = this.magFilter = LinearFilter, this.unpackAlignment = 1, this.needsUpdate = !0;
1279
+ }
1280
+ /**
1281
+ * 获取3D数据的切片
1282
+ * @remarks
1283
+ * 切片就是指定轴的指定位置的垂直截面
1284
+ * @param axis - 轴
1285
+ * @param depth - 在轴上的坐标值
1286
+ * @returns
1287
+ */
1288
+ getData3DSlice(e, t) {
1289
+ const { data: n, width: i, height: a, depth: r } = this.image;
1290
+ return E({ data: n, size: { x: i, y: a, z: r } }, e, t, 1);
1291
+ }
1292
+ /**
1293
+ * 获取3D数据中指定坐标处的数据项目
1294
+ * @remarks
1295
+ * 在 ImageData3DTexture 中,与 {@link ImageData3DTexture.getColor} 返回的值一样;
1296
+ * @param coord
1297
+ * @returns
1298
+ */
1299
+ getItem(e) {
1300
+ const { data: t, width: n, height: i, depth: a } = this.image;
1301
+ return $({ data: t, size: { x: n, y: i, z: a } }, e).value;
1302
+ }
1303
+ /**
1304
+ * 获取3D数据中指定坐标处的值
1305
+ * @param coord - 坐标
1306
+ * @returns
1307
+ */
1308
+ getValue(e) {
1309
+ const { data: t, width: n, height: i, depth: a } = this.image;
1310
+ return tt({ data: t, size: { x: n, y: i, z: a } }, e).value;
1311
+ }
1312
+ }
1313
+ function ln(o, s) {
1314
+ const { data: e, size: t } = o, { x: n, y: i, z: a } = t, r = n * i * a, { voidValue: l = 0, uint8: u } = s ?? {};
1315
+ let c;
1316
+ if (u) {
1317
+ c = new Uint8Array(r);
1318
+ for (let m = 0; m < r; m++) {
1319
+ const f = e[m] ?? l;
1320
+ c[m] = Math.trunc(f);
1321
+ }
1322
+ } else {
1323
+ c = new Float32Array(r);
1324
+ for (let m = 0; m < r; m++) {
1325
+ const f = e[m] ?? l;
1326
+ c[m] = f;
1327
+ }
1328
+ }
1329
+ const p = u ? UnsignedByteType : FloatType;
1330
+ return new Pt(c, n, i, a, p);
1331
+ }
1332
+ const Nt = `precision highp float;
1333
+ precision highp sampler3D;
1334
+
1335
+ uniform sampler3D map;
1336
+
1337
+
1338
+
1339
+ // 颜色累积系数
1340
+ uniform float accFactor;
1341
+ uniform bool isDoubleSide;
1342
+ uniform bool atomize;
1343
+
1344
+
1345
+ uniform float opacity;
1346
+ uniform vec2 alphaRange;
1347
+ uniform float steps;
1348
+
1349
+ in vec3 cameraPos;
1350
+ in vec3 lookDir;
1351
+ in vec3 displayMin;
1352
+ in vec3 displayMax;
1353
+ out vec4 fragColor;
1354
+
1355
+ // 混合颜色
1356
+ vec4 colorBlend(vec4 near,vec4 far){
1357
+ float nA = near.a;
1358
+ if (nA >= 1.0){
1359
+ return near;
1360
+ }
1361
+ if (nA <= 0.0){
1362
+ return far;
1363
+ }
1364
+
1365
+ float fA = far.a;
1366
+ float a = fA + nA - fA*nA;
1367
+ vec3 color = (far.rgb * fA * (1.0 - nA) + near.rgb*nA)/a;
1368
+ return vec4(color,a);
1369
+ }
1370
+
1371
+
1372
+
1373
+
1374
+ // 包围盒求交
1375
+ vec2 intersectBox( vec3 orig, vec3 dir ) {
1376
+ vec3 inv_dir = 1.0 / dir;
1377
+ vec3 tmin_tmp = (displayMin - orig ) * inv_dir;
1378
+ vec3 tmax_tmp = (displayMax - orig ) * inv_dir;
1379
+ vec3 tmin = min( tmin_tmp, tmax_tmp );
1380
+ vec3 tmax = max( tmin_tmp, tmax_tmp );
1381
+ float t0 = max( tmin.x, max( tmin.y, tmin.z ) );
1382
+ float t1 = min( tmax.x, min( tmax.y, tmax.z ) );
1383
+ return vec2( t0, t1 );
1384
+ }
1385
+
1386
+
1387
+
1388
+ void main(){
1389
+ vec3 rayDir = normalize( lookDir );
1390
+
1391
+ vec2 times = intersectBox( cameraPos, rayDir );
1392
+ float tMin = times.x;
1393
+ float tMax = times.y;
1394
+ if ( tMin > tMax || tMax < 0.0 ) discard;
1395
+ tMin = max( tMin, 0.0 );
1396
+
1397
+ vec3 point = cameraPos + tMin * rayDir;
1398
+
1399
+ float step = 1.0/steps;
1400
+ float opacityFactor = atomize ? step * accFactor : 1.0;
1401
+
1402
+ vec3 stepDir = rayDir * step;
1403
+
1404
+ vec4 finalColor = vec4( 0,0,0,0);
1405
+ float alphaMax = alphaRange.y;
1406
+
1407
+ for ( float t = tMin; t <= tMax; t += step,point += stepDir ) {
1408
+ vec4 textureColor = texture( map, point );
1409
+ textureColor.a *= opacityFactor;
1410
+ finalColor = colorBlend(finalColor,textureColor);
1411
+ if ( finalColor.a >= alphaMax ) break;
1412
+ }
1413
+
1414
+ finalColor.a *= opacity;
1415
+ if ( finalColor.a <= alphaRange.x ) discard;
1416
+ if (isDoubleSide){
1417
+ finalColor.a = 1.0 - sqrt(1.0 - finalColor.a);
1418
+ }
1419
+ fragColor = finalColor;
1420
+
1421
+ }`;
1422
+ class cn extends Xe {
1423
+ constructor(e) {
1424
+ super({ ...e, fragmentShader: Nt });
1425
+ v(this, "isImageVolumeMaterial", !0);
1426
+ }
1427
+ }
1428
+ function Ut(o, s, e) {
1429
+ const t = e ?? {}, { x: n, y: i } = t.range ?? { x: 0, y: 100 }, a = t.discardOut ?? !0, { x: r, y: l } = t.voidRange ?? { x: -100, y: -1 }, u = t.voidColor ?? [0, 0, 0, 0], { width: c, height: p } = s, m = Math.trunc(p / 2), f = c - 1;
1430
+ function h(x) {
1431
+ const y = Math.trunc(f * x);
1432
+ return H(s, m, y);
1433
+ }
1434
+ const _ = 1 / (i - n), { data: M, size: S } = o, D = M.length, w = [];
1435
+ for (let x = 0; x < D; x++) {
1436
+ let y = u, g = M[x];
1437
+ (g <= r || l <= g) && (g = (g - n) * _, a && (g < 0 || g > 1) || (g = Math.min(Math.max(g, 0), 1), y = h(g))), w.push(...y);
1438
+ }
1439
+ return { data: w, size: S };
1440
+ }
1441
+ class $e extends Data3DTexture {
1442
+ constructor(e, t, n, i) {
1443
+ super(e, t, n, i);
1444
+ v(this, "isImageData3DTexture", !0);
1445
+ this.format = RGBAFormat, this.type = UnsignedByteType, this.minFilter = this.magFilter = LinearFilter, this.unpackAlignment = 1, this.needsUpdate = !0;
1446
+ }
1447
+ /**
1448
+ * 获取3D数据的切片
1449
+ * @remarks
1450
+ * 切片就是指定轴的指定位置的垂直截面
1451
+ * @param axis - 轴
1452
+ * @param depth - 在轴上的坐标值
1453
+ * @returns
1454
+ */
1455
+ getData3DSlice(e, t) {
1456
+ const { data: n, width: i, height: a, depth: r } = this.image;
1457
+ return E({ data: n, size: { x: i, y: a, z: r } }, e, t, 4);
1458
+ }
1459
+ /**
1460
+ * 获取3D数据中指定坐标处的数据项目
1461
+ * @remarks
1462
+ * 在 ImageData3DTexture 中,与 {@link ImageData3DTexture.getColor} 返回的值一样;
1463
+ * @param coord
1464
+ * @returns
1465
+ */
1466
+ getItem(e) {
1467
+ return this.getColor(e);
1468
+ }
1469
+ /**
1470
+ * 获取3D图像中指定坐标处的颜色
1471
+ * @param coord - 坐标
1472
+ * @returns
1473
+ */
1474
+ getColor(e) {
1475
+ const { data: t, width: n, height: i, depth: a } = this.image;
1476
+ return $({ data: t, size: { x: n, y: i, z: a } }, e, 4).value;
1477
+ }
1478
+ }
1479
+ function un(o, s, e) {
1480
+ const t = (e == null ? void 0 : e.reverseY) ?? !0, { data: n, width: i, height: a, depth: r, colorSpace: l } = nt(o, s, { ...e, reverseY: t }), u = new $e(n, i, a, r);
1481
+ return l === "srgb" && (u.colorSpace = "srgb"), u;
1482
+ }
1483
+ function mn(o, s) {
1484
+ const e = s.gradient, t = Array.isArray(e) ? B(e, 256, 1) : L(e) ? e : K(e);
1485
+ let n = o;
1486
+ P(o) && (n = {
1487
+ // @ts-ignore
1488
+ data: o.data,
1489
+ size: { x: o.width, y: o.height, z: o.depth }
1490
+ });
1491
+ const { data: i, size: a } = Ut(n, t, s), r = Uint8ClampedArray.from(i);
1492
+ return new $e(r, a.x, a.y, a.z);
1493
+ }
1494
+ const At = `out vec3 lookDir;
1495
+ out vec3 normalDir;
1496
+
1497
+ #if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )
1498
+ out vec4 verColor;
1499
+ #endif
1500
+
1501
+ void main() {
1502
+ vec3 cameraPos = vec3( inverse( modelMatrix ) * vec4( cameraPosition, 1.0 ) ).xyz;
1503
+ lookDir = position - cameraPos;
1504
+ normalDir = normal;
1505
+
1506
+ #if defined( USE_COLOR_ALPHA )
1507
+ verColor = color;
1508
+ #elif defined( USE_INSTANCING_COLOR )
1509
+ overColor = vec3(instanceColor,1.0);
1510
+ #elif defined( USE_COLOR )
1511
+ overColor = vec3(color,1.0);
1512
+ #endif
1513
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
1514
+ }`, Ft = `uniform vec3 color;
1515
+ uniform float solid;
1516
+ uniform float exp;
1517
+
1518
+ uniform float opacity;
1519
+ uniform bool isDoubleSide;
1520
+
1521
+ in vec3 lookDir;
1522
+ in vec3 normalDir;
1523
+
1524
+ #if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )
1525
+ in vec4 verColor;
1526
+ #endif
1527
+
1528
+ out vec4 fragColor;
1529
+
1530
+
1531
+ void main(){
1532
+ #if defined( USE_COLOR_ALPHA ) || defined( USE_COLOR )
1533
+ fragColor = verColor;
1534
+ #else
1535
+ fragColor = vec4(color,1.0);
1536
+ #endif
1537
+
1538
+ vec3 dir = normalize(lookDir);
1539
+ vec3 nor = normalize(normalDir);
1540
+ float depth = abs(dot(nor,dir));
1541
+ float dist = sqrt(1.0 - pow(depth,2.0));
1542
+
1543
+ float finalAlpha = fragColor.a * depth;
1544
+ if (dist > solid) {
1545
+ float distAlpha = 1.0 - (dist - solid)/(1.0 - solid);
1546
+ finalAlpha *= pow(distAlpha,exp);
1547
+ }
1548
+
1549
+ finalAlpha *= opacity;
1550
+ if ( finalAlpha == 0.0 ) discard;
1551
+ if (isDoubleSide){
1552
+ finalAlpha = 1.0 - sqrt(1.0 - finalAlpha);
1553
+ }
1554
+ fragColor.a = finalAlpha;
1555
+ }`;
1556
+ class dn extends ShaderMaterial {
1557
+ constructor(e) {
1558
+ const t = e ?? {}, n = t.color ?? new Color(1, 1, 1), i = t.solid ?? 0, a = t.exp ?? 1, r = t.opacity ?? 1, l = t.side ?? FrontSide;
1559
+ super({
1560
+ glslVersion: GLSL3,
1561
+ // @ts-ignore
1562
+ uniforms: {
1563
+ color: { value: n },
1564
+ solid: { value: i },
1565
+ exp: { value: a },
1566
+ opacity: { value: r },
1567
+ isDoubleSide: { value: !1 }
1568
+ },
1569
+ vertexShader: At,
1570
+ fragmentShader: Ft,
1571
+ side: FrontSide,
1572
+ transparent: !0
1573
+ });
1574
+ v(this, "isSphereFogMaterial", !0);
1575
+ v(this, "_side", FrontSide);
1576
+ this.opacity = r, this.side = l;
1577
+ }
1578
+ /**
1579
+ * Mesh三角形的渲染面
1580
+ * @remarks
1581
+ * 可设置为前面、后面、或者两面都渲染
1582
+ * 如果只渲染前面,进入体积材质内部,体积材质就会消失
1583
+ * 如果只渲染后面,体积初遮挡,就会消失
1584
+ * 如果两面都渲染,则会隐藏看到容器的面
1585
+ */
1586
+ // @ts-ignore
1587
+ get side() {
1588
+ return this._side;
1589
+ }
1590
+ set side(e) {
1591
+ this._side = e, this.uniforms && (this.uniforms.isDoubleSide.value = e === DoubleSide, this.uniformsNeedUpdate = !0);
1592
+ }
1593
+ /**
1594
+ * 球形雾的颜色
1595
+ * @remarks
1596
+ * 当开启顶点颜色 {@link SphereFogMaterial.vertexColors} 时,此设置将无论;
1597
+ */
1598
+ get color() {
1599
+ return this.uniforms.color.value;
1600
+ }
1601
+ set color(e) {
1602
+ this.uniforms.color.value.copy(e), this.uniformsNeedUpdate = !0;
1603
+ }
1604
+ /**
1605
+ * 透明度
1606
+ * @remarks
1607
+ * 决定整体的透明度
1608
+ * @defaultValue 1
1609
+ */
1610
+ // @ts-ignore
1611
+ get opacity() {
1612
+ return this.uniforms.opacity.value;
1613
+ }
1614
+ set opacity(e) {
1615
+ this.uniforms && (this.uniforms.opacity.value = e), this.uniformsNeedUpdate = !0;
1616
+ }
1617
+ /**
1618
+ * 实心因子
1619
+ * @remarks
1620
+ * 在实心范围内,球形雾不会衰减
1621
+ * @defaultValue 0
1622
+ */
1623
+ get solid() {
1624
+ return this.uniforms.solid.value;
1625
+ }
1626
+ set solid(e) {
1627
+ this.uniforms && (this.uniforms.solid.value = e), this.uniformsNeedUpdate = !0;
1628
+ }
1629
+ /**
1630
+ * 雾的衰减指数
1631
+ * @defaultValue 1
1632
+ */
1633
+ get exp() {
1634
+ return this.uniforms.exp.value;
1635
+ }
1636
+ set exp(e) {
1637
+ this.uniforms && (this.uniforms.exp.value = e), this.uniformsNeedUpdate = !0;
1638
+ }
1639
+ }
1640
+ class Ye extends ShaderMaterial {
1641
+ constructor(e, t) {
1642
+ const { solid: n = 0, exp: i = 1, useRadius: a = !0, sizeAttenuation: r = !0, star: l = !1, ...u } = e ?? {}, { uniforms: c, ...p } = t || {}, m = {
1643
+ star: { value: l },
1644
+ solid: { value: n },
1645
+ exp: { value: i }
1646
+ };
1647
+ super({
1648
+ // glslVersion: GLSL3,
1649
+ // @ts-ignore
1650
+ uniforms: UniformsUtils.merge([ShaderLib.points.uniforms, m, c]),
1651
+ transparent: !0,
1652
+ depthTest: !1,
1653
+ // depthWrite:false,
1654
+ defines: {
1655
+ useRadius: a
1656
+ },
1657
+ ...p
1658
+ });
1659
+ v(this, "isFogPointsMaterial", !0);
1660
+ /**
1661
+ * 点的大小是否因相机深度而衰减
1662
+ * @remarks
1663
+ * 仅限透视摄像头
1664
+ *
1665
+ * @defaultValue true
1666
+ */
1667
+ v(this, "sizeAttenuation", !0);
1668
+ Object.assign(this, { ...u, solid: n, exp: i, sizeAttenuation: r });
1669
+ }
1670
+ /**
1671
+ * 使用来自Texture的数据设置点的颜色
1672
+ * @remarks
1673
+ * 可以选择包括一个alpha通道,通常与 .transparent或.alphaTest。
1674
+ */
1675
+ get map() {
1676
+ return this.uniforms.map.value;
1677
+ }
1678
+ set map(e) {
1679
+ this.uniforms.map.value = e, this.uniformsNeedUpdate = !0;
1680
+ }
1681
+ /**
1682
+ * 是否渲染成星星的样式
1683
+ * @remarks
1684
+ * 否则,将被渲染成球形
1685
+ */
1686
+ get star() {
1687
+ return this.uniforms.star.value;
1688
+ }
1689
+ set star(e) {
1690
+ this.uniforms.star.value = e, this.uniformsNeedUpdate = !0;
1691
+ }
1692
+ /**
1693
+ * 点的大小
1694
+ * @defaultValue 1.0
1695
+ */
1696
+ get size() {
1697
+ return this.uniforms.size.value;
1698
+ }
1699
+ set size(e) {
1700
+ this.uniforms.size.value = e, this.uniformsNeedUpdate = !0;
1701
+ }
1702
+ /**
1703
+ * 透明度
1704
+ * @remarks
1705
+ * 决定整体的透明度
1706
+ * @defaultValue 1
1707
+ */
1708
+ // @ts-ignore
1709
+ get opacity() {
1710
+ return this.uniforms.opacity.value;
1711
+ }
1712
+ set opacity(e) {
1713
+ this.uniforms && (this.uniforms.opacity.value = e), this.uniformsNeedUpdate = !0;
1714
+ }
1715
+ /**
1716
+ * 实心因子
1717
+ * @remarks
1718
+ * 在实心范围内,雾点不会衰减
1719
+ * @defaultValue 0
1720
+ */
1721
+ get solid() {
1722
+ return this.uniforms.solid.value;
1723
+ }
1724
+ set solid(e) {
1725
+ this.uniforms && (this.uniforms.solid.value = e), this.uniformsNeedUpdate = !0;
1726
+ }
1727
+ /**
1728
+ * 雾的衰减指数
1729
+ * @defaultValue 1
1730
+ */
1731
+ get exp() {
1732
+ return this.uniforms.exp.value;
1733
+ }
1734
+ set exp(e) {
1735
+ this.uniforms && (this.uniforms.exp.value = e), this.uniformsNeedUpdate = !0;
1736
+ }
1737
+ get scale() {
1738
+ return this.uniforms.scale.value;
1739
+ }
1740
+ set scale(e) {
1741
+ this.uniforms && (this.uniforms.scale.value = e), this.uniformsNeedUpdate = !0;
1742
+ }
1743
+ get fogDensity() {
1744
+ return this.uniforms.fogDensity.value;
1745
+ }
1746
+ set fogDensity(e) {
1747
+ this.uniforms && (this.uniforms.fogDensity.value = e), this.uniformsNeedUpdate = !0;
1748
+ }
1749
+ get fogNear() {
1750
+ return this.uniforms.fogNear.value;
1751
+ }
1752
+ set fogNear(e) {
1753
+ this.uniforms && (this.uniforms.fogNear.value = e), this.uniformsNeedUpdate = !0;
1754
+ }
1755
+ get fogFar() {
1756
+ return this.uniforms.fogFar.value;
1757
+ }
1758
+ set fogFar(e) {
1759
+ this.uniforms && (this.uniforms.fogFar.value = e), this.uniformsNeedUpdate = !0;
1760
+ }
1761
+ get fogColor() {
1762
+ return this.uniforms.fogColor.value;
1763
+ }
1764
+ set fogColor(e) {
1765
+ this.uniforms.fogColor.value.copy(e), this.uniformsNeedUpdate = !0;
1766
+ }
1767
+ }
1768
+ const Rt = `#ifdef useRadius
1769
+ attribute float radius;
1770
+ #endif
1771
+
1772
+ uniform float size;
1773
+ uniform float scale;
1774
+
1775
+ #include <common>
1776
+ #include <color_pars_vertex>
1777
+ #include <fog_pars_vertex>
1778
+ #include <morphtarget_pars_vertex>
1779
+ #include <logdepthbuf_pars_vertex>
1780
+ #include <clipping_planes_pars_vertex>
1781
+
1782
+ #ifdef USE_POINTS_UV
1783
+
1784
+ varying vec2 vUv;
1785
+ uniform mat3 uvTransform;
1786
+
1787
+ #endif
1788
+
1789
+ void main() {
1790
+
1791
+ #ifdef USE_POINTS_UV
1792
+
1793
+ vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
1794
+
1795
+ #endif
1796
+
1797
+ #include <color_vertex>
1798
+ #include <morphcolor_vertex>
1799
+ #include <begin_vertex>
1800
+ #include <morphtarget_vertex>
1801
+ #include <project_vertex>
1802
+
1803
+ #ifdef useRadius
1804
+ gl_PointSize = radius;
1805
+ #else
1806
+ gl_PointSize = size;
1807
+ #endif
1808
+
1809
+ #ifdef USE_SIZEATTENUATION
1810
+
1811
+ bool isPerspective = isPerspectiveMatrix( projectionMatrix );
1812
+
1813
+ if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );
1814
+
1815
+ #endif
1816
+
1817
+ #include <logdepthbuf_vertex>
1818
+ #include <clipping_planes_vertex>
1819
+ #include <worldpos_vertex>
1820
+ #include <fog_vertex>
1821
+
1822
+ }`, It = `uniform float solid;
1823
+ uniform float exp;
1824
+ uniform bool star;
1825
+
1826
+ uniform vec3 diffuse;
1827
+ uniform float opacity;
1828
+
1829
+ #include <common>
1830
+ #include <color_pars_fragment>
1831
+ #include <map_particle_pars_fragment>
1832
+ #include <alphatest_pars_fragment>
1833
+ #include <fog_pars_fragment>
1834
+ #include <logdepthbuf_pars_fragment>
1835
+ #include <clipping_planes_pars_fragment>
1836
+
1837
+
1838
+ vec4 getColor(vec4 originColor){
1839
+ float finalAlpha = originColor.a;
1840
+ float dist = 0.0;
1841
+ if (star){
1842
+ vec2 coord = abs(gl_PointCoord - vec2(0.5));
1843
+ dist = max(coord.x,coord.y);
1844
+ }else{
1845
+ dist = distance(gl_PointCoord,vec2(0.5));
1846
+ if (dist>0.5) discard;
1847
+ }
1848
+ dist /= 0.5;
1849
+ float depth = sqrt(1.0 - pow(dist,2.0));
1850
+ finalAlpha *= depth;
1851
+ if (dist > solid) {
1852
+ float distAlpha = 1.0 - (dist - solid)/(1.0 - solid);
1853
+ finalAlpha *= pow(distAlpha,exp);
1854
+ }
1855
+ originColor.a = finalAlpha;
1856
+ return originColor;
1857
+ }
1858
+
1859
+ void main() {
1860
+
1861
+ #include <clipping_planes_fragment>
1862
+
1863
+ vec3 outgoingLight = vec3( 0.0 );
1864
+ vec4 diffuseColor = vec4( diffuse, opacity );
1865
+
1866
+ #include <logdepthbuf_fragment>
1867
+ #include <map_particle_fragment>
1868
+ #include <color_fragment>
1869
+ #include <alphatest_fragment>
1870
+
1871
+ diffuseColor = getColor(diffuseColor);
1872
+ outgoingLight = diffuseColor.rgb;
1873
+
1874
+ #include <output_fragment>
1875
+ #include <tonemapping_fragment>
1876
+ #include <encodings_fragment>
1877
+ #include <fog_fragment>
1878
+ #include <premultiplied_alpha_fragment>
1879
+
1880
+ }`;
1881
+ class Ot extends Ye {
1882
+ constructor(e) {
1883
+ super(e, { vertexShader: Rt, fragmentShader: It });
1884
+ v(this, "isColorFogPointsMaterial", !0);
1885
+ }
1886
+ /**
1887
+ * 雾点的颜色
1888
+ * @remarks
1889
+ * 当开启顶点颜色 {@link SphereFogMaterial.vertexColors} 时,此设置将无论;
1890
+ */
1891
+ get color() {
1892
+ return this.uniforms.diffuse.value;
1893
+ }
1894
+ set color(e) {
1895
+ this.uniforms.diffuse.value.copy(e), this.uniformsNeedUpdate = !0;
1896
+ }
1897
+ get alphaMap() {
1898
+ return this.uniforms.alphaMap.value;
1899
+ }
1900
+ set alphaMap(e) {
1901
+ this.uniforms && (this.uniforms.alphaMap.value = e), this.uniformsNeedUpdate = !0;
1902
+ }
1903
+ get uvTransform() {
1904
+ return this.uniforms.uvTransform.value;
1905
+ }
1906
+ set uvTransform(e) {
1907
+ this.uniforms && this.uniforms.uvTransform.value.copy(e), this.uniformsNeedUpdate = !0;
1908
+ }
1909
+ }
1910
+ function Tt(o) {
1911
+ const { points: s, radius: e = 10, color: t = [0, 0, 0, 0] } = o, n = [], i = [], a = [];
1912
+ for (const { x: l, y: u, z: c, radius: p, color: m } of s) {
1913
+ n.push(l, u, c), i.push(p ?? e);
1914
+ const f = m ?? t, h = f[3];
1915
+ f[3] = Math.trunc(h * 255), a.push(...f);
1916
+ }
1917
+ const r = new BufferGeometry();
1918
+ return r.setAttribute("position", new Float32BufferAttribute(n, 3)), r.setAttribute("radius", new Float32BufferAttribute(i, 1)), r.setAttribute("color", new Uint8ClampedBufferAttribute(a, 4, !0)), r;
1919
+ }
1920
+ function pn(o) {
1921
+ const s = new Ot(o), e = Tt(o);
1922
+ return new Points(e, s);
1923
+ }
1924
+ const Vt = `attribute float value;
1925
+ uniform vec2 range;
1926
+ varying float vValue;
1927
+ #ifdef useRadius
1928
+ attribute float radius;
1929
+ #endif
1930
+
1931
+
1932
+ uniform float size;
1933
+ uniform float scale;
1934
+
1935
+ #include <common>
1936
+ // #include <color_pars_vertex>
1937
+ #include <fog_pars_vertex>
1938
+ #include <morphtarget_pars_vertex>
1939
+ #include <logdepthbuf_pars_vertex>
1940
+ #include <clipping_planes_pars_vertex>
1941
+
1942
+ #ifdef USE_POINTS_UV
1943
+
1944
+ varying vec2 vUv;
1945
+ uniform mat3 uvTransform;
1946
+
1947
+ #endif
1948
+
1949
+ void main() {
1950
+ vValue = (value - range.x)/(range.y - range.x);
1951
+
1952
+ #ifdef USE_POINTS_UV
1953
+
1954
+ vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
1955
+
1956
+ #endif
1957
+
1958
+ // #include <color_vertex>
1959
+ // #include <morphcolor_vertex>
1960
+ #include <begin_vertex>
1961
+ #include <morphtarget_vertex>
1962
+ #include <project_vertex>
1963
+
1964
+ #ifdef useRadius
1965
+ gl_PointSize = radius;
1966
+ #else
1967
+ gl_PointSize = size;
1968
+ #endif
1969
+
1970
+ #ifdef USE_SIZEATTENUATION
1971
+
1972
+ bool isPerspective = isPerspectiveMatrix( projectionMatrix );
1973
+
1974
+ if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );
1975
+
1976
+ #endif
1977
+
1978
+ #include <logdepthbuf_vertex>
1979
+ #include <clipping_planes_vertex>
1980
+ #include <worldpos_vertex>
1981
+ #include <fog_vertex>
1982
+
1983
+ }`, Et = `varying float vValue;
1984
+ uniform sampler2D map;
1985
+
1986
+
1987
+ uniform float solid;
1988
+ uniform float exp;
1989
+ uniform bool star;
1990
+
1991
+ // uniform vec3 diffuse;
1992
+ uniform float opacity;
1993
+
1994
+ #include <common>
1995
+ // #include <color_pars_fragment>
1996
+ // #include <map_particle_pars_fragment>
1997
+ #include <alphatest_pars_fragment>
1998
+ #include <fog_pars_fragment>
1999
+ #include <logdepthbuf_pars_fragment>
2000
+ #include <clipping_planes_pars_fragment>
2001
+
2002
+
2003
+ // 获取梯度颜色
2004
+ vec4 getGradientColor(float val) {
2005
+ val = clamp( val, 0.0,1.0);
2006
+ return texture2D(map, vec2(val, 0.5));
2007
+ }
2008
+
2009
+
2010
+ vec4 getColor(){
2011
+ float val = vValue;
2012
+ float dist = 0.0;
2013
+ if (star){
2014
+ vec2 coord = abs(gl_PointCoord - vec2(0.5));
2015
+ dist = max(coord.x,coord.y);
2016
+ }else{
2017
+ dist = distance(gl_PointCoord,vec2(0.5));
2018
+ if (dist>0.5) discard;
2019
+ }
2020
+ dist /= 0.5;
2021
+ float depth = sqrt(1.0 - pow(dist,2.0));
2022
+ if (dist > solid) {
2023
+ float solidDist = 1.0 - (dist - solid)/(1.0 - solid);
2024
+ val *= pow(solidDist,exp);
2025
+ }
2026
+ vec4 valColor = getGradientColor(val);
2027
+ valColor.a *= depth * opacity;
2028
+ return valColor;
2029
+ }
2030
+
2031
+ void main() {
2032
+
2033
+ #include <clipping_planes_fragment>
2034
+
2035
+ vec3 outgoingLight = vec3( 0.0 );
2036
+ vec4 diffuseColor = getColor();
2037
+
2038
+ #include <logdepthbuf_fragment>
2039
+ // #include <map_particle_fragment>
2040
+ // #include <color_fragment>
2041
+ #include <alphatest_fragment>
2042
+
2043
+ outgoingLight = diffuseColor.rgb;
2044
+
2045
+ #include <output_fragment>
2046
+ #include <tonemapping_fragment>
2047
+ #include <encodings_fragment>
2048
+ #include <fog_fragment>
2049
+ #include <premultiplied_alpha_fragment>
2050
+
2051
+ }`;
2052
+ class Gt extends Ye {
2053
+ constructor(e) {
2054
+ const { range: t, ...n } = e || {}, a = {
2055
+ range: { value: new Vector2().copy(t ?? { x: 0, y: 100 }) }
2056
+ };
2057
+ super(n, { vertexShader: Vt, fragmentShader: Et, uniforms: a });
2058
+ v(this, "isColorFogPointsMaterial", !0);
2059
+ }
2060
+ /**
2061
+ * 数值的映射区间
2062
+ * @remarks
2063
+ * x 为最小值,y 为最大值
2064
+ *
2065
+ * @defaultValue {x:0,y:100}
2066
+ */
2067
+ get range() {
2068
+ return this.uniforms.range.value;
2069
+ }
2070
+ set range(e) {
2071
+ this.uniforms.range.value.copy(e), this.uniformsNeedUpdate = !0;
2072
+ }
2073
+ }
2074
+ function Bt(o) {
2075
+ const { points: s, radius: e = 10, value: t = 100 } = o, n = [], i = [], a = [];
2076
+ for (const { x: l, y: u, z: c, radius: p, value: m } of s)
2077
+ n.push(l, u, c), i.push(p ?? e), a.push(m ?? t);
2078
+ const r = new BufferGeometry();
2079
+ return r.setAttribute("position", new Float32BufferAttribute(n, 3)), r.setAttribute("radius", new Float32BufferAttribute(i, 1)), r.setAttribute("value", new Float32BufferAttribute(a, 1)), r;
2080
+ }
2081
+ function fn(o) {
2082
+ const s = o.gradient, e = s == null ? s : Gn(s), t = new Gt({ ...o, map: e }), n = Bt(o);
2083
+ return new Points(n, t);
2084
+ }
2085
+ const Lt = ` out vec2 vUv;
2086
+
2087
+ void main() {
2088
+ vUv = uv;
2089
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
2090
+ }`, kt = `precision highp float;
2091
+ precision highp sampler3D;
2092
+
2093
+ uniform sampler3D map;
2094
+
2095
+ uniform float opacity;
2096
+ uniform int axis;
2097
+ uniform float depth;
2098
+
2099
+ in vec2 vUv;
2100
+ out vec4 fragColor;
2101
+
2102
+ void main(){
2103
+ vec3 uv3 = vec3(0.0);
2104
+ int depthSize = textureSize(map,0)[axis];
2105
+ uv3[axis] = depth/float(depthSize);
2106
+ int xIndex = (axis + 1)%3;
2107
+ int yIndex = (axis + 2)%3;
2108
+ uv3[xIndex] = vUv.x;
2109
+ uv3[yIndex] = vUv.y;
2110
+
2111
+ fragColor = texture(map, uv3);
2112
+ fragColor.a *= opacity;
2113
+ }`;
2114
+ class jt extends ShaderMaterial {
2115
+ constructor(e) {
2116
+ const t = e ?? {};
2117
+ let { map: n, opacity: i, axis: a, depth: r, side: l, ...u } = t;
2118
+ i = i ?? 1, a = a ?? f$1.z, r = r ?? 0, l = l ?? DoubleSide;
2119
+ super({
2120
+ ...u,
2121
+ glslVersion: GLSL3,
2122
+ // @ts-ignore
2123
+ uniforms: {
2124
+ map: { value: n },
2125
+ opacity: { value: i },
2126
+ axis: { value: a },
2127
+ depth: { value: r }
2128
+ },
2129
+ transparent: !0,
2130
+ vertexShader: Lt,
2131
+ fragmentShader: kt,
2132
+ side: l
2133
+ });
2134
+ v(this, "isSliceMaterial", !0);
2135
+ v(this, "_sliceSize", null);
2136
+ this.opacity = i;
2137
+ }
2138
+ /**
2139
+ * 三维的纹理
2140
+ */
2141
+ get map() {
2142
+ return this.uniforms.map.value;
2143
+ }
2144
+ set map(e) {
2145
+ this.uniforms.map.value = e, this._sliceSize = null, this.uniformsNeedUpdate = !0;
2146
+ }
2147
+ /**
2148
+ * 透明度
2149
+ * @remarks
2150
+ * 决定整体的透明度
2151
+ * @defaultValue 1
2152
+ */
2153
+ // @ts-ignore
2154
+ get opacity() {
2155
+ return this.uniforms.opacity.value;
2156
+ }
2157
+ set opacity(e) {
2158
+ this.uniforms && (this.uniforms.opacity.value = e), this.uniformsNeedUpdate = !0;
2159
+ }
2160
+ /**
2161
+ * 轴
2162
+ * @remarks
2163
+ * 切片就是垂直于该轴的截面
2164
+ *
2165
+ * @defaultValue Axis.z
2166
+ */
2167
+ get axis() {
2168
+ return this.uniforms.axis.value;
2169
+ }
2170
+ set axis(e) {
2171
+ this.uniforms.axis.value = e, this._sliceSize = null, this.uniformsNeedUpdate = !0;
2172
+ }
2173
+ /**
2174
+ * 轴上的坐标值
2175
+ * @remarks
2176
+ * 会在轴的该位置处获取切片
2177
+ * @defaultValue 0
2178
+ */
2179
+ get depth() {
2180
+ return this.uniforms.depth.value;
2181
+ }
2182
+ set depth(e) {
2183
+ this.uniforms.depth.value = e, this.uniformsNeedUpdate = !0;
2184
+ }
2185
+ /**
2186
+ * 切片的尺寸
2187
+ * @remarks
2188
+ * 不同轴上的切片的尺寸一般不一样
2189
+ */
2190
+ get sliceSize() {
2191
+ let e = this._sliceSize;
2192
+ if (!e) {
2193
+ this._sliceSize = e = new Vector2(1, 1);
2194
+ const { axis: t, map: n } = this;
2195
+ if (n) {
2196
+ const { width: i, height: a, depth: r } = n.image, [l, u] = f$1.getCrossAxiss(t), c = [i, a, r];
2197
+ e.set(c[l], c[u]);
2198
+ }
2199
+ }
2200
+ return e;
2201
+ }
2202
+ }
2203
+ class vn extends Mesh {
2204
+ constructor(e) {
2205
+ const t = new jt(e), n = new PlaneGeometry();
2206
+ super(n, t);
2207
+ v(this, "isSliceMesh", !0);
2208
+ // @ts-ignore
2209
+ // override get geometry(){
2210
+ // return this._geometry;
2211
+ // }
2212
+ // override set geometry(value){
2213
+ // this._geometry = value;
2214
+ // this.configMaterial();
2215
+ // }
2216
+ v(this, "_geometry");
2217
+ // @ts-ignore
2218
+ // override get material(){
2219
+ // return this._material;
2220
+ // }
2221
+ // override set material(value){
2222
+ // this._material = value;
2223
+ // this.configGeometry();
2224
+ // }
2225
+ v(this, "_material");
2226
+ /**
2227
+ * 是否自动更新几何体
2228
+ * @remarks
2229
+ * 当启动该选项后,在 SliceMesh 监测到切片尺寸相关的变更时,会自动更新 geometry 的尺寸,以适应切片的尺寸
2230
+ * @defaultValue true
2231
+ */
2232
+ v(this, "autoUpdateGeometry", !0);
2233
+ Object.defineProperties(this, {
2234
+ geometry: {
2235
+ get: () => this._geometry,
2236
+ set: (i) => {
2237
+ this._geometry = i, this.autoUpdateGeometry && this.updateGeometry();
2238
+ }
2239
+ },
2240
+ material: {
2241
+ get: () => this._material,
2242
+ set: (i) => {
2243
+ this._material = i, this.autoUpdateGeometry && this.updateGeometry();
2244
+ }
2245
+ }
2246
+ }), this.geometry = n, this.material = t;
2247
+ }
2248
+ /**
2249
+ * 更新几何体
2250
+ */
2251
+ updateGeometry() {
2252
+ var r;
2253
+ const { geometry: e, material: t } = this;
2254
+ if (!t || !((r = t.map) == null ? void 0 : r.image))
2255
+ return !1;
2256
+ e.boundingBox || e.computeBoundingBox();
2257
+ const i = t.sliceSize, a = e.boundingBox.getSize(new Vector3());
2258
+ e.scale(i.x / a.x, i.y / a.y, 1);
2259
+ }
2260
+ /**
2261
+ * 三维的纹理
2262
+ */
2263
+ get map() {
2264
+ return this.material.map;
2265
+ }
2266
+ set map(e) {
2267
+ this.material.map = e, this.material = this.material;
2268
+ }
2269
+ /**
2270
+ * 轴
2271
+ * @remarks
2272
+ * 切片就是垂直于该轴的截面
2273
+ *
2274
+ * @defaultValue Axis.z
2275
+ */
2276
+ get axis() {
2277
+ return this.material.axis;
2278
+ }
2279
+ set axis(e) {
2280
+ this.material.axis = e, this.material = this.material;
2281
+ }
2282
+ /**
2283
+ * 轴上的坐标值
2284
+ * @remarks
2285
+ * 会在轴的该位置处获取切片
2286
+ * @defaultValue 0
2287
+ */
2288
+ get depth() {
2289
+ return this.material.depth;
2290
+ }
2291
+ set depth(e) {
2292
+ this.material.depth = e;
2293
+ }
2294
+ /**
2295
+ * 切片的尺寸
2296
+ * @remarks
2297
+ * 不同轴上的切片的尺寸一般不一样
2298
+ */
2299
+ get sliceSize() {
2300
+ return this.material.sliceSize;
2301
+ }
2302
+ }
2303
+ class hn extends ct {
2304
+ constructor(e) {
2305
+ const t = P(e) ? e : e.image;
2306
+ super(t);
2307
+ v(this, "isImageData3DTextureSlice", !0);
2308
+ }
2309
+ /**
2310
+ * 设置材质或 IImageData3 类数据
2311
+ */
2312
+ set texture(e) {
2313
+ this.image3D = P(e) ? e : e.image;
2314
+ }
2315
+ }
2316
+ function Ze({ ratio: o, value: s }) {
2317
+ return s - s * o;
2318
+ }
2319
+ function Ht(o, s) {
2320
+ const { x: e, y: t } = s;
2321
+ let n = 0;
2322
+ for (const { value: i, clim: { x: a, y: r } } of o)
2323
+ n += (i - a) / (r - a);
2324
+ return n * (t - e) + e;
2325
+ }
2326
+ function qt(o, s, e) {
2327
+ const { size: t, data3D: n, tags: i } = s, { clim: a, radius: r, value: l, hollow: u, valueGradient: c, valuesAccumulate: p } = o, m = new Vector3().copy(o), f = [], h = [], _ = {
2328
+ particles: f,
2329
+ values: h
2330
+ }, M = r * u, S = m.clone().subScalar(r), D = m.clone().addScalar(r);
2331
+ S.max(new Vector3(0, 0, 0));
2332
+ const w = new Vector3().copy(t).subScalar(1);
2333
+ D.min(w);
2334
+ let { x, y, z: g } = S;
2335
+ x = Math.trunc(x), y = Math.trunc(y), g = Math.trunc(g);
2336
+ let { x: z, y: N, z: U } = D;
2337
+ if (z = Math.trunc(z), N = Math.trunc(N), U = Math.trunc(U), x > z || y > N || g > U)
2338
+ return _;
2339
+ const { x: T, y: C } = t, V = T * C;
2340
+ for (let A = g; A <= U; A++) {
2341
+ const he = A * V;
2342
+ for (let R = y; R <= N; R++) {
2343
+ const J = he + R * T;
2344
+ e:
2345
+ for (let P = x; P <= z; P++) {
2346
+ const L = J + P;
2347
+ if (i[L])
2348
+ continue;
2349
+ const F = new Vector3(P, R, A), b = F.distanceTo(m);
2350
+ if (b > r || b < M)
2351
+ continue;
2352
+ i[L] = !0;
2353
+ const k = {
2354
+ radius: r,
2355
+ hollow: u,
2356
+ hollowRadius: M,
2357
+ distance: b,
2358
+ clim: a,
2359
+ value: l
2360
+ }, E = [], j = {
2361
+ ...k,
2362
+ ratio: b / r,
2363
+ distance: b,
2364
+ point: F
2365
+ }, H = c(j);
2366
+ E.push({
2367
+ ...o,
2368
+ ...j,
2369
+ value: H
2370
+ });
2371
+ for (const G of e) {
2372
+ const B = F.distanceTo(G), { hollow: ge, radius: X } = G;
2373
+ if (B <= X) {
2374
+ const $ = X * ge;
2375
+ if (B < $)
2376
+ continue e;
2377
+ const I = {
2378
+ ...G,
2379
+ ratio: B / X,
2380
+ distance: B,
2381
+ hollowRadius: $,
2382
+ point: F
2383
+ }, xe = c(I);
2384
+ E.push({ ...I, value: xe });
2385
+ }
2386
+ }
2387
+ const q = p(E, a);
2388
+ n[L] = q, f.push(F), h.push(q);
2389
+ }
2390
+ }
2391
+ }
2392
+ return _;
2393
+ }
2394
+ function gn(o) {
2395
+ const { points: s, clim: e = { x: 0, y: 100 }, radius: t = 10, value: n = 100, hollow: i = 0, valueGradient: a = Ze, valuesAccumulate: r = Ht, size: l } = o, u = { clim: e, radius: t, value: n, hollow: i, valueGradient: a, valuesAccumulate: r }, c = s.map((x) => ({ ...u, ...x }));
2396
+ let p = l;
2397
+ l || (p = new Box3().setFromPoints(c).max.addScalar(1));
2398
+ const m = En(c);
2399
+ let { x: f, y: h, z: _ } = p;
2400
+ f = p.x = Math.trunc(f), h = p.y = Math.trunc(h), _ = p.z = Math.trunc(_);
2401
+ const M = new Array(f * h * _), S = new Array(f * h * _), D = { size: p, data3D: M, tags: S }, w = c.length;
2402
+ for (let x = 0; x < w; x++) {
2403
+ const y = c[x], g = m[x].map((z) => c[z]);
2404
+ qt(y, D, g);
2405
+ }
2406
+ return {
2407
+ data: M,
2408
+ size: p
2409
+ };
2410
+ }
2411
+ function Xt({ startRadius: o, addedRadius: s, ratio: e }) {
2412
+ return s * e + o;
2413
+ }
2414
+ function $t({ startHollow: o, addedHollow: s, ratio: e }) {
2415
+ return s * e + o;
2416
+ }
2417
+ function Yt({ startValue: o, addedValue: s, ratio: e }) {
2418
+ return s * e + o;
2419
+ }
2420
+ function Zt(o, s) {
2421
+ const { x: e, y: t } = s;
2422
+ return o.reduce((n, i) => n + i - e, 0);
2423
+ }
2424
+ function xn(o) {
2425
+ const { points: s, size: e, clim: t = { x: 0, y: 100 }, radius: n = 10, value: i = 100, hollow: a = 0, valueGradient: r = Ze, radiusGradient: l = Xt, hollowGradient: u = $t, lineValueGradient: c = Yt, valuesAccumulate: p = Zt } = o, m = { radius: n, value: i, hollow: a }, f = s.map(function(C) {
2426
+ return Object.assign(new Vector3(), m, C);
2427
+ }), h = e ? new Vector3().copy(e).subScalar(1) : new Box3().setFromPoints(f).max;
2428
+ h.x = Math.trunc(h.x), h.y = Math.trunc(h.y), h.z = Math.trunc(h.z);
2429
+ const _ = h.clone().addScalar(1), { x: M, y: S, z: D } = _, w = M * S, x = new Array(w * D), y = [], g = [], z = {
2430
+ particles: y,
2431
+ values: g,
2432
+ size: _,
2433
+ data: x
2434
+ }, N = new Vector3(0, 0, 0), U = s.length, T = Math.trunc(U / 2);
2435
+ for (let C = 0; C < T; C++) {
2436
+ const V = C * 2, A = f[V], he = V + 1, R = f[he], J = new Line3(A, R), P = J.distance(), L = J.delta(new Vector3()).normalize(), F = new Quaternion();
2437
+ F.setFromUnitVectors(new Vector3(0, 1, 0), L);
2438
+ const b = new Matrix4().makeRotationFromQuaternion(F);
2439
+ b.setPosition(A);
2440
+ const { radius: k, value: E, hollow: j } = A, { radius: H, value: q, hollow: G } = R, B = H - k, ge = q - E, X = G - j, $ = { length: P, startRadius: k, endRadius: H, addedRadius: B, defaultRadius: n, radius: n, startValue: E, endValue: q, addedValue: ge, defaultValue: i, startHollow: j, endHollow: G, addedHollow: X, defaultHollow: a, clim: t }, I = Math.max(k, H), xe = new Vector3(-I, 0, -I), Ke = new Vector3(I, P, I), Se = new Box3(xe, Ke);
2441
+ Se.applyMatrix4(b);
2442
+ const { min: De, max: be } = Se;
2443
+ De.max(N), be.min(h);
2444
+ let { x: ee, y: te, z: ne } = De;
2445
+ ee = Math.trunc(ee), te = Math.trunc(te), ne = Math.trunc(ne);
2446
+ let { x: ie, y: ae, z: oe } = be;
2447
+ if (ie = Math.trunc(ie), ae = Math.trunc(ae), oe = Math.trunc(oe), ee > ie || te > ae || ne > oe)
2448
+ return z;
2449
+ b.invert();
2450
+ for (let re = ne; re <= oe; re++) {
2451
+ const Qe = re * w;
2452
+ for (let se = te; se <= ae; se++) {
2453
+ const Je = Qe + se * M;
2454
+ for (let le = ee; le <= ie; le++) {
2455
+ const Ce = Je + le, ce = new Vector3(le, se, re), Pe = ce.clone();
2456
+ Pe.applyMatrix4(b);
2457
+ const { x: et, y: _e, z: tt } = Pe;
2458
+ if (_e < 0 || _e > P)
2459
+ continue;
2460
+ const ue = Math.hypot(et, tt), me = {
2461
+ ...$,
2462
+ ratio: _e / P,
2463
+ point: ce
2464
+ }, Y = l(me);
2465
+ me.radius = Y;
2466
+ const Ne = u(me), Ue = Y * Ne;
2467
+ if (ue > Y || ue < Ue)
2468
+ continue;
2469
+ const nt = c(me), it = {
2470
+ ...$,
2471
+ value: nt,
2472
+ ratio: ue / Y,
2473
+ radius: Y,
2474
+ hollow: Ne,
2475
+ hollowRadius: Ue,
2476
+ distance: ue,
2477
+ point: ce
2478
+ };
2479
+ let de = r(it);
2480
+ const Ae = g[Ce];
2481
+ Ae !== void 0 && (de = p([Ae, de], t)), x[Ce] = de, y.push(ce), g.push(de);
2482
+ }
2483
+ }
2484
+ }
2485
+ }
2486
+ return z;
2487
+ }
2488
+ function _n(o, s) {
2489
+ const e = new Vector3().setFromMatrixScale(s), t = Math.sqrt(e.lengthSq() / 3), n = new Matrix3().setFromMatrix4(s);
2490
+ let { points: i, size: a, radius: r, ...l } = o;
2491
+ if (a && (a = new Vector3().copy(a).applyMatrix3(n)), r && (r *= t), i) {
2492
+ const u = [];
2493
+ for (let { x: c, y: p, z: m, radius: f, ...h } of i) {
2494
+ f && (f *= t);
2495
+ const _ = new Vector3(c, p, m).applyMatrix4(s);
2496
+ Object.assign(_, h, { radius: f }), u.push(_);
2497
+ }
2498
+ i = u;
2499
+ }
2500
+ return { points: i, size: a, radius: r, ...l };
2501
+ }
2502
+ function Wt(o, s, e = 1) {
2503
+ let { points: t, size: n, radius: i, ...a } = o;
2504
+ if (i && (i *= e), t) {
2505
+ const r = [];
2506
+ for (let { x: l, y: u, z: c, radius: p, ...m } of t) {
2507
+ p && (p *= e);
2508
+ const f = new Vector3(l, u, c).add(s).multiplyScalar(e);
2509
+ Object.assign(f, m, { radius: p }), r.push(f);
2510
+ }
2511
+ t = r;
2512
+ }
2513
+ return n && (n = new Vector3().copy(n).add(s).multiplyScalar(e)), { points: t, size: n, radius: i, ...a };
2514
+ }
2515
+ function yn(o, s) {
2516
+ const { points: e, radius: t } = o;
2517
+ if (!e)
2518
+ return { options: o, position: new Vector3(), scale: 1 };
2519
+ const n = new Box3();
2520
+ for (const p of e) {
2521
+ const m = new Vector3().copy(p), f = p.radius ?? t;
2522
+ f ? (n.expandByPoint(m.clone().subScalar(f)), n.expandByPoint(m.addScalar(f))) : n.expandByPoint(m);
2523
+ }
2524
+ const i = new Vector3().max(n.min), a = n.max.clone().sub(i).addScalar(1);
2525
+ o.size && a.min(o.size);
2526
+ let { scale: r, maxSize: l } = s || {};
2527
+ r || (l = l ?? 100, r = l / Math.max(a.x, a.y, a.z)), a.multiplyScalar(r);
2528
+ const u = i.clone().negate(), c = Wt(o, u, r);
2529
+ return c.size = a, { options: c, position: i, scale: 1 / r };
2530
+ }
2531
+ const Fe = {
2532
+ uniforms: {
2533
+ u_size: { value: new Vector3(1, 1, 1) },
2534
+ u_renderstyle: { value: 0 },
2535
+ u_renderthreshold: { value: 0.5 },
2536
+ u_clim: { value: new Vector2(1, 1) },
2537
+ u_data: { value: null },
2538
+ u_cmdata: { value: null }
2539
+ },
2540
+ vertexShader: (
2541
+ /* glsl */
2542
+ `
2543
+
2544
+ varying vec4 v_nearpos;
2545
+ varying vec4 v_farpos;
2546
+ varying vec3 v_position;
2547
+
2548
+ void main() {
2549
+ // Prepare transforms to map to "camera view". See also:
2550
+ // https://threejs.org/docs/#api/renderers/webgl/WebGLProgram
2551
+ mat4 viewtransformf = modelViewMatrix;
2552
+ mat4 viewtransformi = inverse(modelViewMatrix);
2553
+
2554
+ // Project local vertex coordinate to camera position. Then do a step
2555
+ // backward (in cam coords) to the near clipping plane, and project back. Do
2556
+ // the same for the far clipping plane. This gives us all the information we
2557
+ // need to calculate the ray and truncate it to the viewing cone.
2558
+ vec4 position4 = vec4(position, 1.0);
2559
+ vec4 pos_in_cam = viewtransformf * position4;
2560
+
2561
+ // Intersection of ray and near clipping plane (z = -1 in clip coords)
2562
+ pos_in_cam.z = -pos_in_cam.w;
2563
+ v_nearpos = viewtransformi * pos_in_cam;
2564
+
2565
+ // Intersection of ray and far clipping plane (z = +1 in clip coords)
2566
+ pos_in_cam.z = pos_in_cam.w;
2567
+ v_farpos = viewtransformi * pos_in_cam;
2568
+
2569
+ // Set varyings and output pos
2570
+ v_position = position;
2571
+ gl_Position = projectionMatrix * viewMatrix * modelMatrix * position4;
2572
+ }`
2573
+ ),
2574
+ fragmentShader: (
2575
+ /* glsl */
2576
+ `
2577
+
2578
+ precision highp float;
2579
+ precision mediump sampler3D;
2580
+
2581
+ uniform vec3 u_size;
2582
+ uniform int u_renderstyle;
2583
+ uniform float u_renderthreshold;
2584
+ uniform vec2 u_clim;
2585
+
2586
+ uniform sampler3D u_data;
2587
+ uniform sampler2D u_cmdata;
2588
+
2589
+ varying vec3 v_position;
2590
+ varying vec4 v_nearpos;
2591
+ varying vec4 v_farpos;
2592
+
2593
+ // The maximum distance through our rendering volume is sqrt(3).
2594
+ const int MAX_STEPS = 887; // 887 for 512^3, 1774 for 1024^3
2595
+ const int REFINEMENT_STEPS = 4;
2596
+ const float relative_step_size = 1.0;
2597
+ const vec4 ambient_color = vec4(0.2, 0.4, 0.2, 1.0);
2598
+ const vec4 diffuse_color = vec4(0.8, 0.2, 0.2, 1.0);
2599
+ const vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);
2600
+ const float shininess = 40.0;
2601
+
2602
+ void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);
2603
+ void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);
2604
+
2605
+ float sample1(vec3 texcoords);
2606
+ vec4 apply_colormap(float val);
2607
+ vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray);
2608
+
2609
+
2610
+ void main() {
2611
+ // Normalize clipping plane info
2612
+ vec3 farpos = v_farpos.xyz / v_farpos.w;
2613
+ vec3 nearpos = v_nearpos.xyz / v_nearpos.w;
2614
+
2615
+ // Calculate unit vector pointing in the view direction through this fragment.
2616
+ vec3 view_ray = normalize(nearpos.xyz - farpos.xyz);
2617
+
2618
+ // Compute the (negative) distance to the front surface or near clipping plane.
2619
+ // v_position is the back face of the cuboid, so the initial distance calculated in the dot
2620
+ // product below is the distance from near clip plane to the back of the cuboid
2621
+ float distance = dot(nearpos - v_position, view_ray);
2622
+ distance = max(distance, min((-0.5 - v_position.x) / view_ray.x,
2623
+ (u_size.x - 0.5 - v_position.x) / view_ray.x));
2624
+ distance = max(distance, min((-0.5 - v_position.y) / view_ray.y,
2625
+ (u_size.y - 0.5 - v_position.y) / view_ray.y));
2626
+ distance = max(distance, min((-0.5 - v_position.z) / view_ray.z,
2627
+ (u_size.z - 0.5 - v_position.z) / view_ray.z));
2628
+
2629
+ // Now we have the starting position on the front surface
2630
+ vec3 front = v_position + view_ray * distance;
2631
+
2632
+ // Decide how many steps to take
2633
+ int nsteps = int(-distance / relative_step_size + 0.5);
2634
+ if ( nsteps < 1 )
2635
+ discard;
2636
+
2637
+ // Get starting location and step vector in texture coordinates
2638
+ vec3 step = ((v_position - front) / u_size) / float(nsteps);
2639
+ vec3 start_loc = front / u_size;
2640
+
2641
+ // For testing: show the number of steps. This helps to establish
2642
+ // whether the rays are correctly oriented
2643
+ //'gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0);
2644
+ //'return;
2645
+
2646
+ if (u_renderstyle == 0)
2647
+ cast_mip(start_loc, step, nsteps, view_ray);
2648
+ else if (u_renderstyle == 1)
2649
+ cast_iso(start_loc, step, nsteps, view_ray);
2650
+
2651
+ if (gl_FragColor.a < 0.05)
2652
+ discard;
2653
+ }
2654
+
2655
+
2656
+ float sample1(vec3 texcoords) {
2657
+ /* Sample float value from a 3D texture. Assumes intensity data. */
2658
+ return texture(u_data, texcoords.xyz).r;
2659
+ }
2660
+
2661
+
2662
+ vec4 apply_colormap(float val) {
2663
+ val = (val - u_clim[0]) / (u_clim[1] - u_clim[0]);
2664
+ return texture2D(u_cmdata, vec2(val, 0.5));
2665
+ }
2666
+
2667
+
2668
+ void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {
2669
+
2670
+ float max_val = -1e6;
2671
+ int max_i = 100;
2672
+ vec3 loc = start_loc;
2673
+
2674
+ // Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with
2675
+ // non-constant expression. So we use a hard-coded max, and an additional condition
2676
+ // inside the loop.
2677
+ for (int iter=0; iter<MAX_STEPS; iter++) {
2678
+ if (iter >= nsteps)
2679
+ break;
2680
+ // Sample from the 3D texture
2681
+ float val = sample1(loc);
2682
+ // Apply MIP operation
2683
+ if (val > max_val) {
2684
+ max_val = val;
2685
+ max_i = iter;
2686
+ }
2687
+ // Advance location deeper into the volume
2688
+ loc += step;
2689
+ }
2690
+
2691
+ // Refine location, gives crispier images
2692
+ vec3 iloc = start_loc + step * (float(max_i) - 0.5);
2693
+ vec3 istep = step / float(REFINEMENT_STEPS);
2694
+ for (int i=0; i<REFINEMENT_STEPS; i++) {
2695
+ max_val = max(max_val, sample1(iloc));
2696
+ iloc += istep;
2697
+ }
2698
+
2699
+ // Resolve final color
2700
+ gl_FragColor = apply_colormap(max_val);
2701
+ }
2702
+
2703
+
2704
+ void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {
2705
+
2706
+ gl_FragColor = vec4(0.0); // init transparent
2707
+ vec4 color3 = vec4(0.0); // final color
2708
+ vec3 dstep = 1.5 / u_size; // step to sample derivative
2709
+ vec3 loc = start_loc;
2710
+
2711
+ float low_threshold = u_renderthreshold - 0.02 * (u_clim[1] - u_clim[0]);
2712
+
2713
+ // Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with
2714
+ // non-constant expression. So we use a hard-coded max, and an additional condition
2715
+ // inside the loop.
2716
+ for (int iter=0; iter<MAX_STEPS; iter++) {
2717
+ if (iter >= nsteps)
2718
+ break;
2719
+
2720
+ // Sample from the 3D texture
2721
+ float val = sample1(loc);
2722
+
2723
+ if (val > low_threshold) {
2724
+ // Take the last interval in smaller steps
2725
+ vec3 iloc = loc - 0.5 * step;
2726
+ vec3 istep = step / float(REFINEMENT_STEPS);
2727
+ for (int i=0; i<REFINEMENT_STEPS; i++) {
2728
+ val = sample1(iloc);
2729
+ if (val > u_renderthreshold) {
2730
+ gl_FragColor = add_lighting(val, iloc, dstep, view_ray);
2731
+ return;
2732
+ }
2733
+ iloc += istep;
2734
+ }
2735
+ }
2736
+
2737
+ // Advance location deeper into the volume
2738
+ loc += step;
2739
+ }
2740
+ }
2741
+
2742
+
2743
+ vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray)
2744
+ {
2745
+ // Calculate color by incorporating lighting
2746
+
2747
+ // View direction
2748
+ vec3 V = normalize(view_ray);
2749
+
2750
+ // calculate normal vector from gradient
2751
+ vec3 N;
2752
+ float val1, val2;
2753
+ val1 = sample1(loc + vec3(-step[0], 0.0, 0.0));
2754
+ val2 = sample1(loc + vec3(+step[0], 0.0, 0.0));
2755
+ N[0] = val1 - val2;
2756
+ val = max(max(val1, val2), val);
2757
+ val1 = sample1(loc + vec3(0.0, -step[1], 0.0));
2758
+ val2 = sample1(loc + vec3(0.0, +step[1], 0.0));
2759
+ N[1] = val1 - val2;
2760
+ val = max(max(val1, val2), val);
2761
+ val1 = sample1(loc + vec3(0.0, 0.0, -step[2]));
2762
+ val2 = sample1(loc + vec3(0.0, 0.0, +step[2]));
2763
+ N[2] = val1 - val2;
2764
+ val = max(max(val1, val2), val);
2765
+
2766
+ float gm = length(N); // gradient magnitude
2767
+ N = normalize(N);
2768
+
2769
+ // Flip normal so it points towards viewer
2770
+ float Nselect = float(dot(N, V) > 0.0);
2771
+ N = (2.0 * Nselect - 1.0) * N; // == Nselect * N - (1.0-Nselect)*N;
2772
+
2773
+ // Init colors
2774
+ vec4 ambient_color = vec4(0.0, 0.0, 0.0, 0.0);
2775
+ vec4 diffuse_color = vec4(0.0, 0.0, 0.0, 0.0);
2776
+ vec4 specular_color = vec4(0.0, 0.0, 0.0, 0.0);
2777
+
2778
+ // note: could allow multiple lights
2779
+ for (int i=0; i<1; i++)
2780
+ {
2781
+ // Get light direction (make sure to prevent zero devision)
2782
+ vec3 L = normalize(view_ray); //lightDirs[i];
2783
+ float lightEnabled = float( length(L) > 0.0 );
2784
+ L = normalize(L + (1.0 - lightEnabled));
2785
+
2786
+ // Calculate lighting properties
2787
+ float lambertTerm = clamp(dot(N, L), 0.0, 1.0);
2788
+ vec3 H = normalize(L+V); // Halfway vector
2789
+ float specularTerm = pow(max(dot(H, N), 0.0), shininess);
2790
+
2791
+ // Calculate mask
2792
+ float mask1 = lightEnabled;
2793
+
2794
+ // Calculate colors
2795
+ ambient_color += mask1 * ambient_color; // * gl_LightSource[i].ambient;
2796
+ diffuse_color += mask1 * lambertTerm;
2797
+ specular_color += mask1 * specularTerm * specular_color;
2798
+ }
2799
+
2800
+ // Calculate final color by componing different components
2801
+ vec4 final_color;
2802
+ vec4 color = apply_colormap(val);
2803
+ final_color = color * (ambient_color + diffuse_color) + specular_color;
2804
+ final_color.a = color.a;
2805
+ return final_color;
2806
+ }`
2807
+ )
2808
+ };
2809
+ var Kt = /* @__PURE__ */ ((o) => (o[o.MIP = 0] = "MIP", o[o.ISO = 1] = "ISO", o))(Kt || {});
2810
+ class Mn extends ShaderMaterial {
2811
+ constructor(e) {
2812
+ const { style: t, threshold: n, clim: i, map: a, gradient: r } = e ?? {}, l = new Vector3(1, 1, 1);
2813
+ if (a) {
2814
+ const { width: p, height: m, depth: f } = a.image;
2815
+ l.set(p, m, f);
2816
+ }
2817
+ const u = r == null ? r : Gn(r), c = UniformsUtils.clone(Fe.uniforms);
2818
+ c.u_size.value.copy(l), c.u_clim.value.copy(i ?? new Vector2(1, 1)), c.u_renderstyle.value = t ?? 1, c.u_renderthreshold.value = n ?? 0.5, c.u_data.value = a ?? null, c.u_cmdata.value = u ?? null;
2819
+ super({
2820
+ ...Fe,
2821
+ // @ts-ignore
2822
+ uniforms: c,
2823
+ side: BackSide
2824
+ });
2825
+ v(this, "isExampleVolumeMaterial_1", !0);
2826
+ v(this, "_gradient");
2827
+ }
2828
+ /**
2829
+ * 三维纹理
2830
+ */
2831
+ get map() {
2832
+ return this.uniforms.u_data.value;
2833
+ }
2834
+ set map(e) {
2835
+ this.uniforms.u_data.value = e, this.uniformsNeedUpdate = !0;
2836
+ }
2837
+ /**
2838
+ * 颜色映射纹理
2839
+ * @remarks
2840
+ * 会将垂直居中的那条水平像素从左到右映射到 clim 表示的限制区间,
2841
+ * 即 clim.x 对应最左边的像素,clim.y 对应最右边的像素
2842
+ */
2843
+ get gradientMap() {
2844
+ return this.uniforms.u_cmdata.value;
2845
+ }
2846
+ /**
2847
+ * 颜色映射选项
2848
+ */
2849
+ get gradient() {
2850
+ return this._gradient;
2851
+ }
2852
+ set gradient(e) {
2853
+ this._gradient = e;
2854
+ const t = e == null ? e : Gn(e);
2855
+ this.uniforms.u_cmdata.value = t ?? null, this.uniformsNeedUpdate = !0;
2856
+ }
2857
+ /**
2858
+ * 三维纹理的尺寸
2859
+ * @remarks
2860
+ * 三维纹理的尺寸 要 和 Geometry 的尺寸是一样的,不但比列一样,大小也是一样的
2861
+ * 但 mesh 本身可以进行几何变换;
2862
+ * Geometry 左下角的坐标要从 (0,0,0) 开始;
2863
+ */
2864
+ get size() {
2865
+ return this.uniforms.u_size.value;
2866
+ }
2867
+ set size(e) {
2868
+ this.uniforms.u_size.value.copy(e), this.uniformsNeedUpdate = !0;
2869
+ }
2870
+ /**
2871
+ * 渲染样式
2872
+ */
2873
+ get style() {
2874
+ return this.uniforms.u_renderstyle.value;
2875
+ }
2876
+ set style(e) {
2877
+ this.uniforms.u_renderstyle.value = e, this.uniformsNeedUpdate = !0;
2878
+ }
2879
+ /**
2880
+ * 映射区间
2881
+ * @remarks
2882
+ * x 为最小值,y 为最大值
2883
+ */
2884
+ get clim() {
2885
+ return this.uniforms.u_clim.value;
2886
+ }
2887
+ set clim(e) {
2888
+ this.uniforms.u_clim.value = e, this.uniformsNeedUpdate = !0;
2889
+ }
2890
+ /**
2891
+ * 渲染最低阈值
2892
+ * @remarks
2893
+ * 只对 ISO 样式有效;
2894
+ *
2895
+ * 当三维纹理中的值低于该值时,不会被渲染,即视为空
2896
+ */
2897
+ get threshold() {
2898
+ return this.uniforms.u_renderthreshold.value;
2899
+ }
2900
+ set threshold(e) {
2901
+ this.uniforms.u_renderthreshold.value = e, this.uniformsNeedUpdate = !0;
2902
+ }
2903
+ }
2904
+ const We = `in vec3 position;
2905
+
2906
+ uniform mat4 modelMatrix;
2907
+ uniform mat4 modelViewMatrix;
2908
+ uniform mat4 projectionMatrix;
2909
+ uniform vec3 cameraPos;
2910
+
2911
+ out vec3 vOrigin;
2912
+ out vec3 vDirection;
2913
+
2914
+ void main() {
2915
+ vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
2916
+ vOrigin = vec3( inverse( modelMatrix ) * vec4( cameraPos, 1.0 ) ).xyz;
2917
+ vDirection = position - vOrigin;
2918
+ gl_Position = projectionMatrix * mvPosition;
2919
+ }`, Qt = `precision highp float;
2920
+ precision highp sampler3D;
2921
+
2922
+ uniform mat4 modelViewMatrix;
2923
+ uniform mat4 projectionMatrix;
2924
+
2925
+ in vec3 vOrigin;
2926
+ in vec3 vDirection;
2927
+
2928
+ out vec4 color;
2929
+
2930
+ uniform vec3 base;
2931
+ uniform sampler3D map;
2932
+
2933
+ uniform float threshold;
2934
+ uniform float range;
2935
+ uniform float opacity;
2936
+ uniform float steps;
2937
+ uniform float frame;
2938
+
2939
+ uint wang_hash(uint seed)
2940
+ {
2941
+ seed = (seed ^ 61u) ^ (seed >> 16u);
2942
+ seed *= 9u;
2943
+ seed = seed ^ (seed >> 4u);
2944
+ seed *= 0x27d4eb2du;
2945
+ seed = seed ^ (seed >> 15u);
2946
+ return seed;
2947
+ }
2948
+
2949
+ float randomFloat(inout uint seed)
2950
+ {
2951
+ return float(wang_hash(seed)) / 4294967296.;
2952
+ }
2953
+
2954
+ vec2 hitBox( vec3 orig, vec3 dir ) {
2955
+ const vec3 box_min = vec3( - 0.5 );
2956
+ const vec3 box_max = vec3( 0.5 );
2957
+ vec3 inv_dir = 1.0 / dir;
2958
+ vec3 tmin_tmp = ( box_min - orig ) * inv_dir;
2959
+ vec3 tmax_tmp = ( box_max - orig ) * inv_dir;
2960
+ vec3 tmin = min( tmin_tmp, tmax_tmp );
2961
+ vec3 tmax = max( tmin_tmp, tmax_tmp );
2962
+ float t0 = max( tmin.x, max( tmin.y, tmin.z ) );
2963
+ float t1 = min( tmax.x, min( tmax.y, tmax.z ) );
2964
+ return vec2( t0, t1 );
2965
+ }
2966
+
2967
+ float sample1( vec3 p ) {
2968
+ return texture( map, p ).r;
2969
+ }
2970
+
2971
+ float shading( vec3 coord ) {
2972
+ float step = 0.01;
2973
+ return sample1( coord + vec3( - step ) ) - sample1( coord + vec3( step ) );
2974
+ }
2975
+
2976
+ void main(){
2977
+ vec3 rayDir = normalize( vDirection );
2978
+ vec2 bounds = hitBox( vOrigin, rayDir );
2979
+
2980
+ if ( bounds.x > bounds.y ) discard;
2981
+
2982
+ bounds.x = max( bounds.x, 0.0 );
2983
+
2984
+ vec3 p = vOrigin + bounds.x * rayDir;
2985
+ vec3 inc = 1.0 / abs( rayDir );
2986
+ float delta = min( inc.x, min( inc.y, inc.z ) );
2987
+ delta /= steps;
2988
+
2989
+ // Jitter
2990
+
2991
+ // Nice little seed from
2992
+ // https://blog.demofox.org/2020/05/25/casual-shadertoy-path-tracing-1-basic-camera-diffuse-emissive/
2993
+ uint seed = uint( gl_FragCoord.x ) * uint( 1973 ) + uint( gl_FragCoord.y ) * uint( 9277 ) + uint( frame ) * uint( 26699 );
2994
+ vec3 size = vec3( textureSize( map, 0 ) );
2995
+ float randNum = randomFloat( seed ) * 2.0 - 1.0;
2996
+ p += rayDir * randNum * ( 1.0 / size );
2997
+
2998
+ //
2999
+
3000
+ vec4 ac = vec4( base, 0.0 );
3001
+
3002
+ for ( float t = bounds.x; t < bounds.y; t += delta ) {
3003
+
3004
+ float d = sample1( p + 0.5 );
3005
+
3006
+ d = smoothstep( threshold - range, threshold + range, d ) * opacity;
3007
+
3008
+ float col = shading( p + 0.5 ) * 3.0 + ( ( p.x + p.y ) * 0.25 ) + 0.2;
3009
+
3010
+ ac.rgb += ( 1.0 - ac.a ) * d * col;
3011
+
3012
+ ac.a += ( 1.0 - ac.a ) * d;
3013
+
3014
+ if ( ac.a >= 0.95 ) break;
3015
+
3016
+ p += rayDir * delta;
3017
+
3018
+ }
3019
+
3020
+ color = ac;
3021
+
3022
+ if ( color.a == 0.0 ) discard;
3023
+
3024
+ }`;
3025
+ class zn extends RawShaderMaterial {
3026
+ constructor(e) {
3027
+ let { color: t, threshold: n, map: i, opacity: a, range: r, steps: l, frame: u, cameraPos: c } = e ?? {};
3028
+ t = t ?? new Color(1, 1, 1), n = n ?? 0.25, a = a ?? 0.25, r = r ?? 0.1, l = l ?? 100, u = u ?? 100, c = c ?? new Vector3();
3029
+ super({
3030
+ glslVersion: GLSL3,
3031
+ // @ts-ignore
3032
+ uniforms: {
3033
+ base: { value: t },
3034
+ map: { value: i },
3035
+ cameraPos: { value: c },
3036
+ threshold: { value: n },
3037
+ opacity: { value: a },
3038
+ range: { value: r },
3039
+ steps: { value: l },
3040
+ frame: { value: u }
3041
+ },
3042
+ vertexShader: We,
3043
+ fragmentShader: Qt,
3044
+ side: BackSide,
3045
+ transparent: !0
3046
+ });
3047
+ v(this, "isExampleVolumeMaterial_Cloud", !0);
3048
+ this.opacity = a;
3049
+ }
3050
+ /**
3051
+ * 三维纹理
3052
+ */
3053
+ get map() {
3054
+ return this.uniforms.map.value;
3055
+ }
3056
+ set map(e) {
3057
+ this.uniforms.map.value = e, this.uniformsNeedUpdate = !0;
3058
+ }
3059
+ /**
3060
+ * 颜色
3061
+ */
3062
+ get color() {
3063
+ return this.uniforms.base.value;
3064
+ }
3065
+ set color(e) {
3066
+ this.uniforms.base.value = e, this.uniformsNeedUpdate = !0;
3067
+ }
3068
+ /**
3069
+ * 透明度
3070
+ */
3071
+ // @ts-ignore
3072
+ get opacity() {
3073
+ return this.uniforms.opacity.value;
3074
+ }
3075
+ set opacity(e) {
3076
+ this.uniforms && (this.uniforms.opacity.value = e), this.uniformsNeedUpdate = !0;
3077
+ }
3078
+ /**
3079
+ * 渲染最低阈值
3080
+ */
3081
+ get threshold() {
3082
+ return this.uniforms.threshold.value;
3083
+ }
3084
+ set threshold(e) {
3085
+ this.uniforms.threshold.value = e, this.uniformsNeedUpdate = !0;
3086
+ }
3087
+ /**
3088
+ * 范围
3089
+ */
3090
+ get range() {
3091
+ return this.uniforms.range.value;
3092
+ }
3093
+ set range(e) {
3094
+ this.uniforms.range.value = e, this.uniformsNeedUpdate = !0;
3095
+ }
3096
+ /**
3097
+ * 体积材质渲染的采样数
3098
+ */
3099
+ get steps() {
3100
+ return this.uniforms.steps.value;
3101
+ }
3102
+ set steps(e) {
3103
+ this.uniforms.steps.value = e, this.uniformsNeedUpdate = !0;
3104
+ }
3105
+ /**
3106
+ * 渲染帧次
3107
+ */
3108
+ get frame() {
3109
+ return this.uniforms.frame.value;
3110
+ }
3111
+ set frame(e) {
3112
+ this.uniforms.frame.value = e, this.uniformsNeedUpdate = !0;
3113
+ }
3114
+ /**
3115
+ * 相机的位置
3116
+ */
3117
+ get cameraPos() {
3118
+ return this.uniforms.cameraPos.value;
3119
+ }
3120
+ set cameraPos(e) {
3121
+ this.uniforms.cameraPos.value.copy(e), this.uniformsNeedUpdate = !0;
3122
+ }
3123
+ }
3124
+ const Jt = `precision highp float;
3125
+ precision highp sampler3D;
3126
+
3127
+ uniform mat4 modelViewMatrix;
3128
+ uniform mat4 projectionMatrix;
3129
+
3130
+ in vec3 vOrigin;
3131
+ in vec3 vDirection;
3132
+
3133
+ out vec4 color;
3134
+
3135
+ uniform sampler3D map;
3136
+
3137
+ uniform float threshold;
3138
+ uniform float steps;
3139
+
3140
+ vec2 hitBox( vec3 orig, vec3 dir ) {
3141
+ const vec3 box_min = vec3( - 0.5 );
3142
+ const vec3 box_max = vec3( 0.5 );
3143
+ vec3 inv_dir = 1.0 / dir;
3144
+ vec3 tmin_tmp = ( box_min - orig ) * inv_dir;
3145
+ vec3 tmax_tmp = ( box_max - orig ) * inv_dir;
3146
+ vec3 tmin = min( tmin_tmp, tmax_tmp );
3147
+ vec3 tmax = max( tmin_tmp, tmax_tmp );
3148
+ float t0 = max( tmin.x, max( tmin.y, tmin.z ) );
3149
+ float t1 = min( tmax.x, min( tmax.y, tmax.z ) );
3150
+ return vec2( t0, t1 );
3151
+ }
3152
+
3153
+ float sample1( vec3 p ) {
3154
+ return texture( map, p ).r;
3155
+ }
3156
+
3157
+ #define epsilon .0001
3158
+
3159
+ vec3 normal( vec3 coord ) {
3160
+ if ( coord.x < epsilon ) return vec3( 1.0, 0.0, 0.0 );
3161
+ if ( coord.y < epsilon ) return vec3( 0.0, 1.0, 0.0 );
3162
+ if ( coord.z < epsilon ) return vec3( 0.0, 0.0, 1.0 );
3163
+ if ( coord.x > 1.0 - epsilon ) return vec3( - 1.0, 0.0, 0.0 );
3164
+ if ( coord.y > 1.0 - epsilon ) return vec3( 0.0, - 1.0, 0.0 );
3165
+ if ( coord.z > 1.0 - epsilon ) return vec3( 0.0, 0.0, - 1.0 );
3166
+
3167
+ float step = 0.01;
3168
+ float x = sample1( coord + vec3( - step, 0.0, 0.0 ) ) - sample1( coord + vec3( step, 0.0, 0.0 ) );
3169
+ float y = sample1( coord + vec3( 0.0, - step, 0.0 ) ) - sample1( coord + vec3( 0.0, step, 0.0 ) );
3170
+ float z = sample1( coord + vec3( 0.0, 0.0, - step ) ) - sample1( coord + vec3( 0.0, 0.0, step ) );
3171
+
3172
+ return normalize( vec3( x, y, z ) );
3173
+ }
3174
+
3175
+ void main(){
3176
+
3177
+ vec3 rayDir = normalize( vDirection );
3178
+ vec2 bounds = hitBox( vOrigin, rayDir );
3179
+
3180
+ if ( bounds.x > bounds.y ) discard;
3181
+
3182
+ bounds.x = max( bounds.x, 0.0 );
3183
+
3184
+ vec3 p = vOrigin + bounds.x * rayDir;
3185
+ vec3 inc = 1.0 / abs( rayDir );
3186
+ float delta = min( inc.x, min( inc.y, inc.z ) );
3187
+ delta /= steps;
3188
+
3189
+ for ( float t = bounds.x; t < bounds.y; t += delta ) {
3190
+
3191
+ float d = sample1( p + 0.5 );
3192
+
3193
+ if ( d > threshold ) {
3194
+
3195
+ color.rgb = normal( p + 0.5 ) * 0.5 + ( p * 1.5 + 0.25 );
3196
+ color.a = 1.;
3197
+ break;
3198
+
3199
+ }
3200
+
3201
+ p += rayDir * delta;
3202
+
3203
+ }
3204
+
3205
+ if ( color.a == 0.0 ) discard;
3206
+
3207
+ }`;
3208
+ class wn extends RawShaderMaterial {
3209
+ constructor(e) {
3210
+ let { threshold: t, map: n, steps: i, cameraPos: a } = e ?? {};
3211
+ t = t ?? 0.25, i = i ?? 100, a = a ?? new Vector3();
3212
+ super({
3213
+ glslVersion: GLSL3,
3214
+ // @ts-ignore
3215
+ uniforms: {
3216
+ map: { value: n },
3217
+ cameraPos: { value: a },
3218
+ threshold: { value: t },
3219
+ steps: { value: i }
3220
+ },
3221
+ vertexShader: We,
3222
+ fragmentShader: Jt,
3223
+ side: BackSide,
3224
+ transparent: !0
3225
+ });
3226
+ v(this, "isExampleVolumeMaterial_Perlin", !0);
3227
+ }
3228
+ /**
3229
+ * 三维纹理
3230
+ */
3231
+ get map() {
3232
+ return this.uniforms.map.value;
3233
+ }
3234
+ set map(e) {
3235
+ this.uniforms.map.value = e, this.uniformsNeedUpdate = !0;
3236
+ }
3237
+ /**
3238
+ * 渲染最低阈值
3239
+ */
3240
+ get threshold() {
3241
+ return this.uniforms.threshold.value;
3242
+ }
3243
+ set threshold(e) {
3244
+ this.uniforms.threshold.value = e, this.uniformsNeedUpdate = !0;
3245
+ }
3246
+ /**
3247
+ * 体积材质渲染的采样数
3248
+ */
3249
+ get steps() {
3250
+ return this.uniforms.steps.value;
3251
+ }
3252
+ set steps(e) {
3253
+ this.uniforms.steps.value = e, this.uniformsNeedUpdate = !0;
3254
+ }
3255
+ /**
3256
+ * 相机的位置
3257
+ */
3258
+ get cameraPos() {
3259
+ return this.uniforms.cameraPos.value;
3260
+ }
3261
+ set cameraPos(e) {
3262
+ this.uniforms.cameraPos.value.copy(e), this.uniformsNeedUpdate = !0;
3263
+ }
3264
+ }
3265
+
3266
+ class HeatMapPlugin {
3267
+ constructor(ssp) {
3268
+ this.ssp = ssp;
3269
+ this.defaultColorGradient = [
3270
+ [0, 'rgba(0,255,0,0)'],
3271
+ [0.5, 'rgba(64,255,255,0.5)'],
3272
+ [1, 'rgba(255,64,255,1)']
3273
+ ];
3274
+ this.defaultGradientVolumeMaterialOptions = {
3275
+ fit: Dt.Raw,
3276
+ accFactor: 2,
3277
+ depthTest: false,
3278
+ side: BackSide,
3279
+ discardOut: false,
3280
+ // 数值的梯度映射纹理
3281
+ gradient: Gn(this.defaultColorGradient),
3282
+ };
3283
+ }
3284
+ _createTexture(points, options, isLine = false) {
3285
+ //优化
3286
+ const optimized = yn(Object.assign({ points }, options), Object.assign({ maxSize: 60 }, options));
3287
+ const { options: optimizedOptions, position, scale, } = optimized;
3288
+ //创建热力3D数据
3289
+ const heatData3D = isLine ? xn(optimizedOptions) : gn(optimizedOptions);
3290
+ //创建热力3D纹理
3291
+ const heatTexture = ln(heatData3D, Object.assign({}, options));
3292
+ //创建热力材质
3293
+ const heatMaterial = new sn(Object.assign(Object.assign(Object.assign({}, this.defaultGradientVolumeMaterialOptions), { map: heatTexture }), options));
3294
+ const volumMesh = new rn(heatMaterial);
3295
+ volumMesh.position.copy(position);
3296
+ volumMesh.scale.set(scale, scale, scale);
3297
+ this.ssp.addObject(volumMesh);
3298
+ return volumMesh;
3299
+ }
3300
+ /**
3301
+ * 创建热力云
3302
+ * return material
3303
+ */
3304
+ createHeatCloud(points, options) {
3305
+ return this._createTexture(points, options);
3306
+ }
3307
+ //创建线状热力
3308
+ createLineHeat(points, options) {
3309
+ return this._createTexture(points, options, true);
3310
+ }
3311
+ //创建图片挤压
3312
+ async createImageExtrusion(imageUrl, options) {
3313
+ var _a;
3314
+ const material = new cn(Object.assign({ side: BackSide, depthTest: false }, options));
3315
+ const image = await SoonSpace.utils.imageLoader.loadAsync(imageUrl);
3316
+ const texture = un(image, (_a = options === null || options === void 0 ? void 0 : options.depth) !== null && _a !== void 0 ? _a : 200, options);
3317
+ material.map = texture;
3318
+ const volumMesh = new rn(material);
3319
+ this.ssp.addObject(volumMesh);
3320
+ return volumMesh;
3321
+ }
3322
+ //创建切片
3323
+ createSliceMesh(material, options) {
3324
+ let texture = material.map;
3325
+ if (!texture)
3326
+ return;
3327
+ if (material instanceof sn) {
3328
+ const { gradient, range, discardOut, voidRange, } = material;
3329
+ texture = mn(texture.image, Object.assign({ gradient: gradient === null || gradient === void 0 ? void 0 : gradient.image, range,
3330
+ discardOut,
3331
+ voidRange }, options));
3332
+ }
3333
+ const sliceMesh = new vn(Object.assign({ map: texture }, options));
3334
+ this.ssp.addObject(sliceMesh);
3335
+ return sliceMesh;
3336
+ }
3337
+ //创建切片dom
3338
+ createImageSlice(material, options) {
3339
+ const texture = material.map;
3340
+ if (!texture)
3341
+ return;
3342
+ let imageTexture = null;
3343
+ if (material instanceof sn) {
3344
+ const { gradient, range, discardOut, voidRange, } = material;
3345
+ imageTexture = mn(texture.image, Object.assign({ gradient: gradient === null || gradient === void 0 ? void 0 : gradient.image, range,
3346
+ discardOut,
3347
+ voidRange }, options));
3348
+ }
3349
+ if (material instanceof cn) {
3350
+ imageTexture = texture;
3351
+ }
3352
+ if (!imageTexture)
3353
+ return;
3354
+ const imageSlice = new hn(imageTexture);
3355
+ return imageSlice;
3356
+ }
3357
+ }
3358
+
3359
+ export { Ot as ColorFogPointsMaterial, Mn as ExampleVolumeMaterial_1, zn as ExampleVolumeMaterial_Cloud, wn as ExampleVolumeMaterial_Perlin, Ye as FogPointsMaterial, Pt as GradientData3DTexture, Gt as GradientFogPointsMaterial, sn as GradientVolumeMaterial, HeatMapPlugin, ct as ImageData3DSlice, $e as ImageData3DTexture, hn as ImageData3DTextureSlice, cn as ImageVolumeMaterial, jt as SliceMaterial, vn as SliceMesh, dn as SphereFogMaterial, Dt as VolumeFit, Xe as VolumeMaterial, rn as VolumeMesh, Kt as VolumeRenderStyle, qt as computeHeatData3DForPoint, pn as createColorFogPoints, ln as createGradientData3DTexture, fn as createGradientFogPoints, gn as createHeatData3D, un as createImageData3DTextureByExtrudeImage, mn as createImageData3DTextureFromGradient, xn as createLineData3D, B as createLinearGradientImageData, Gn as createLinearGradientTexture, O as data2DCoordToIndex, at$1 as data2DIndexToCoord, _ as data3DCoordToIndex, Z as data3DIndexToCoord, HeatMapPlugin as default, nt as extrudeImage, W as extrudeImageData, X as extrudeImageDataOnAxis, G as getData2DItem, st as getData2DItemSafe, ot$1 as getData2DRow, j as getData2DValue, it as getData2DValueSafe, U as getData3DItem, $ as getData3DItemSafe, E as getData3DSlice, N as getData3DValue, tt as getData3DValueSafe, H as getImageDateColor, K as getImageDateOfImage, F as getImageDateRow, b as getNaturalSizeOfImageSource, Ut as gradientData3DToImageData3D, $t as hollowGradient_Default, Y as imageDataToCanvas, J as imageDataToUrl, L as isIImageData2, P as isIImageData3, Q as isOutOfSize, Yt as lineValueGradient_Default, bt as makeOriginOnBoundingBoxMinOfGeometry, et as mergeData3Ds, Zt as numberValuesAccumulate_Default, yn as optimizeGradientOptions, Xt as radiusGradient_Default, V as reverseImageDateY, _n as transformGradientOptions, Wt as translateScaleGradientOptions, Ze as valueGradient_Default, Ht as valuesAccumulate_Default };
3360
+ //# sourceMappingURL=index.esm.js.map