ModelTextureMaterial.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import Common from '../utils/Common.js'
  3. import math from '../utils/math.js'
  4. import {Features} from "../../Features.js";
  5. import {ExtendPointCloudMaterial} from "../../materials/ExtendPointCloudMaterial.js";
  6. import {Gradients} from "../../materials/Gradients.js";
  7. const prefixVertex ="precision highp float;\nprecision highp int;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\n attribute vec3 position;\n attribute vec3 normal;\n attribute vec2 uv;\n"
  8. const prefixFragment ="#extension GL_EXT_frag_depth : enable \n precision highp float;\nprecision highp int;\n\nuniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"
  9. // otherwise error: 'GL_EXT_frag_depth' : extension is disabled
  10. let getClassificationLUT = ()=>{
  11. const [width, height] = [256, 1];
  12. let data = new Uint8Array(width * 4);
  13. let tex = new THREE.DataTexture(data, width, height, THREE.RGBAFormat);
  14. tex.magFilter = THREE.NearestFilter;
  15. tex.needsUpdate = true;
  16. return tex
  17. }
  18. let shader = {
  19. uniforms: {
  20. opacity: {
  21. type: "f",
  22. // value: 1
  23. },
  24. progress: {
  25. type: "f",
  26. value: 0
  27. },
  28. pano0Map: {
  29. type: "t",
  30. value: null
  31. },
  32. pano1Map: {
  33. type: "t",
  34. value: null
  35. },
  36. depthMap0: {
  37. type: "t",
  38. value: null
  39. },
  40. depthMap1: {
  41. type: "t",
  42. value: null
  43. },
  44. pano0ClassMap: {
  45. type: "t",
  46. value: null
  47. },
  48. pano1ClassMap: {
  49. type: "t",
  50. value: null
  51. },
  52. pano0TempMap: {
  53. type: "t",
  54. value: null
  55. },
  56. pano1TempMap: {
  57. type: "t",
  58. value: null
  59. },
  60. gradient: {
  61. type: "t",
  62. value: null
  63. },
  64. classificationLUT: {
  65. type: "t",
  66. value: null
  67. },
  68. pano0Position: {
  69. type: "v3",
  70. value: new THREE.Vector3
  71. },
  72. pano0Matrix: {
  73. type: "m4",
  74. value: new THREE.Matrix4
  75. },
  76. pano1Position: {
  77. type: "v3",
  78. value: new THREE.Vector3
  79. },
  80. pano1Matrix: {
  81. type: "m4",
  82. value: new THREE.Matrix4
  83. },
  84. /* pano1Matrix2: {
  85. type: "m4",
  86. value: new THREE.Matrix4
  87. },
  88. */
  89. inverseProjectionMatrix: {
  90. value: new THREE.Matrix4
  91. },
  92. /* projectionMatrix:{//需要再写一遍吗
  93. value: new THREE.Matrix4
  94. }, */
  95. viewport: {
  96. value: new THREE.Vector4
  97. },
  98. //如 {x: 0, y: 0, z: 428, w: 969} xy应该是offset, zw是宽高
  99. cameraHeight0: {
  100. type: "f",
  101. value: 1
  102. },
  103. cameraHeight1: {
  104. type: "f",
  105. value: 1
  106. },
  107. ceilHeight0:{
  108. type: "f",
  109. value: 2
  110. },
  111. ceilHeight1:{
  112. type: "f",
  113. value: 2
  114. },
  115. temperRange:{//温度范围
  116. type:'vec2',
  117. value: new THREE.Vector2(math.getKelvinFromCelsius(15), math.getKelvinFromCelsius(60) )
  118. }
  119. },
  120. vertexShader: prefixVertex + `
  121. uniform vec3 pano0Position;
  122. uniform mat4 pano0Matrix;
  123. uniform vec3 pano1Position;
  124. uniform mat4 pano1Matrix;
  125. varying vec2 vUv;
  126. varying vec3 vWorldPosition0;
  127. varying vec3 vWorldPosition1;
  128. varying vec3 vWorldPosition12;
  129. vec3 transformAxis( vec3 direction ) //navvis->4dkk
  130. {
  131. float y = direction.y;
  132. direction.y = direction.z;
  133. direction.z = -y;
  134. return direction;
  135. }
  136. void main() {
  137. vUv = uv;
  138. vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  139. vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
  140. vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;
  141. vWorldPosition0.x *= -1.0;
  142. vWorldPosition0 = transformAxis(vWorldPosition0);
  143. vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
  144. vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;
  145. vWorldPosition1.x *= -1.0;
  146. vWorldPosition1 = transformAxis(vWorldPosition1);
  147. /*
  148. vec3 positionLocalToPanoCenter12 = worldPosition.xyz - pano1Position;
  149. vWorldPosition12 = (vec4(positionLocalToPanoCenter12, 1.0) * pano1Matrix2).xyz;
  150. vWorldPosition12.x *= -1.0;
  151. vWorldPosition12 = transformAxis(vWorldPosition12);
  152. */
  153. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  154. }
  155. `,
  156. fragmentShader: prefixFragment + `
  157. #define PI 3.141592653
  158. uniform float modelAlpha;
  159. uniform float opacity;
  160. uniform float progress;
  161. uniform int tranType;
  162. uniform vec3 pano0Position;
  163. uniform vec3 pano1Position;
  164. uniform float maxDistance;
  165. uniform float minDistance;
  166. uniform float minOpa;
  167. uniform samplerCube pano0Map;
  168. uniform samplerCube pano1Map;
  169. #if defined(useTempMap0) || defined(useTempMap1)
  170. uniform sampler2D gradient;
  171. uniform vec2 temperRange;
  172. #endif
  173. #if defined(useClassMap0) || defined(useClassMap1)
  174. uniform sampler2D classificationLUT;
  175. #endif
  176. #if defined(useTempMap0)
  177. uniform sampler2D pano0TempMap;
  178. #endif
  179. #if defined(useTempMap1)
  180. uniform sampler2D pano1TempMap;
  181. #endif
  182. #if defined(useClassMap0)
  183. uniform sampler2D pano0ClassMap;
  184. #endif
  185. #if defined(useClassMap1)
  186. uniform sampler2D pano1ClassMap;
  187. #endif
  188. varying vec2 vUv;
  189. varying vec3 vWorldPosition0;
  190. varying vec3 vWorldPosition1;
  191. /* vec2 getSamplerCoord( vec3 direction )
  192. {
  193. direction = normalize(direction);
  194. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  195. float ty=acos(direction.z)/PI;
  196. return vec2(tx,ty);
  197. } */
  198. vec2 getSamplerCoord2( vec3 direction )
  199. {
  200. direction = normalize(direction);
  201. float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;
  202. float ty=acos(direction.y)/PI;
  203. return vec2(tx,ty);
  204. }
  205. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  206. uniform sampler2D depthMap0;
  207. uniform sampler2D depthMap1;
  208. uniform mat4 inverseProjectionMatrix;
  209. uniform mat4 projectionMatrix;
  210. uniform vec4 viewport;
  211. uniform float cameraHeight0;
  212. uniform float cameraHeight1;
  213. uniform float ceilHeight0;
  214. uniform float ceilHeight1;
  215. vec2 getDepth(vec3 dir, sampler2D depthMap, float heightDown, float heightUp, vec4 eyePos){
  216. vec2 depthValue = vec2(0.0, 0.0);
  217. vec2 uv2 = getSamplerCoord2( dir.xyz); //暂时只用基于目标漫游点的方向
  218. uv2.x -= 0.25; //全景图和Cube的水平采样起始坐标相差90度,这里矫正 0.25 个采样偏移
  219. vec4 depth = texture2D(depthMap, uv2);
  220. //float distance = depth.r + 256. * (depth.g + 256. * depth.b);
  221. //distance *= 255. * .001; // distance is now in meters
  222. //更改
  223. float distance = (depth.g + depth.r / 256.) * 255.;
  224. if(distance == 0.0){//漫游点底部识别不到的区域,给一个地板高度
  225. if(uv2.y < depthTexUVyLimit) distance = heightUp / dir.y;
  226. else if(uv2.y > 1.0 - depthTexUVyLimit) distance = heightDown / -dir.y;
  227. else distance = 100000.0;//给个超级远的值
  228. }
  229. if(distance == 0.0)distance = 100000.0;//给个超级远的值
  230. depthValue.x = distance;
  231. distance += .1; // add a safety margin
  232. vec4 eyePos2 = vec4(normalize(eyePos.xyz) * distance, 1.);
  233. vec4 clipPos2 = projectionMatrix * eyePos2;
  234. vec4 ndcPos2 = clipPos2 * 1. / clipPos2.w;
  235. depthValue.y = 0.5 * ((gl_DepthRange.far - gl_DepthRange.near) * ndcPos2.z
  236. + gl_DepthRange.near + gl_DepthRange.far);
  237. #if defined(depth_background)
  238. //后排的 skybox 不能挡住chunk
  239. depthValue.y += 0.3;
  240. #endif
  241. return depthValue;
  242. }
  243. //注:未加载好的话,depth为0,导致第一次漫游过去的时候许多mesh会立刻被遮挡,所以要确保加载完
  244. #endif
  245. int unpack16(vec2 channels){
  246. return int(round(channels.y * 255.0)) + (int(round(channels.x * 255.0)) << 8) ; //some phone needs round,such as vivo x30
  247. }
  248. int getIntFromColor(sampler2D map, vec3 dir){//uint16-> int 0-65536
  249. //float texWidth = 1024.;
  250. vec2 uv = getSamplerCoord2(dir.xyz);
  251. uv.x -= 0.25;
  252. vec4 color = texture2D(map, uv);
  253. return unpack16(color.rg);
  254. /* if( fract(uv.x * texWidth) > 0.5){
  255. return unpack16(color.rg);
  256. }else{
  257. return unpack16(color.ba);
  258. } */
  259. }
  260. /*vec4 getColorFromMap(sampler2D map, vec3 dir){
  261. vec2 uv = getSamplerCoord2(dir.xyz);
  262. uv.x -= 0.25;
  263. vec4 color = texture2D(map, uv);
  264. return color;
  265. }*/
  266. //ir热成像
  267. #if defined(useTempMap0) || defined(useTempMap1)
  268. vec4 getTemperature(sampler2D map, vec3 dir){
  269. float temperature = float(getIntFromColor(map, dir))/ 10.0 ;
  270. float w = (temperature - temperRange.x) / (temperRange.y - temperRange.x);
  271. w = clamp(w,0.0,1.0);
  272. vec4 color = vec4(texture2D(gradient, vec2(w,1.0-w)).rgb, 1.0);
  273. return color;
  274. }
  275. #endif
  276. #if defined(useClassMap0) || defined(useClassMap1)
  277. /*vec4 getClassification(sampler2D map, vec3 dir, vec4 originColor){
  278. vec4 color = getColorFromMap(map, dir);
  279. float v = color.r * 255.0;
  280. if(v<=2.01&&v>=1.99){
  281. color = vec4(1.0,0.0,0.0,1.0);
  282. } else{
  283. color = vec4(0.0,0.0,0.0,1.0);
  284. }
  285. return color;
  286. } */
  287. vec4 getClassification(sampler2D map, vec3 dir, vec4 originColor){
  288. int classIndex = getIntFromColor(map, dir);
  289. vec2 uv = vec2(float(classIndex) / 255.0, 0.5); //copy from pointcloud_new.vs
  290. vec4 classColor = texture2D(classificationLUT, uv);
  291. float blendRatio = 0.5;
  292. float classAlpha = classColor.a * blendRatio;
  293. vec4 color = vec4(classColor.rgb * classAlpha + originColor.rgb * (1.0-classAlpha), 1.0); //mix with old rgba
  294. return color;
  295. }
  296. #endif
  297. void main()
  298. {
  299. vec3 vWorldPosition0N = normalize(vWorldPosition0);
  300. vec3 vWorldPosition1N = normalize(vWorldPosition1);
  301. float progress_ = progress;
  302. vec4 colorFromPano0 = vec4(0.0,0.0,0.0,0.0);
  303. #if defined(usePanoMap0)
  304. //即progress < 1.0 通常是1
  305. #if defined(useTempMap0)
  306. colorFromPano0 = getTemperature(pano0TempMap,vWorldPosition0N.xyz);
  307. #else
  308. colorFromPano0 = textureCube(pano0Map,vWorldPosition0N.xyz);
  309. #if defined(useClassMap0)
  310. colorFromPano0 = getClassification(pano0ClassMap,vWorldPosition0N.xyz, colorFromPano0);
  311. #endif
  312. #endif
  313. #else
  314. progress_ = 1.0;
  315. #endif
  316. vec4 colorFromPano1 = vec4(0.0,0.0,0.0,0.0);
  317. #if defined(useTempMap1)
  318. colorFromPano1 = getTemperature(pano1TempMap,vWorldPosition1N.xyz);
  319. #else
  320. colorFromPano1 = textureCube(pano1Map,vWorldPosition1N.xyz);
  321. #if defined(useClassMap1)
  322. colorFromPano1 = getClassification(pano1ClassMap,vWorldPosition1N.xyz, colorFromPano1);
  323. #endif
  324. #endif
  325. gl_FragColor = mix(colorFromPano0,colorFromPano1,progress_);
  326. //深度图修改深度
  327. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  328. vec4 ndcPos;
  329. ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.;
  330. ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
  331. (gl_DepthRange.far - gl_DepthRange.near);
  332. ndcPos.w = 1.0;
  333. vec4 clipPos = ndcPos / gl_FragCoord.w;
  334. vec4 eyePos = inverseProjectionMatrix * clipPos;
  335. vec2 depth0 = vec2(0.0,0.0);
  336. vec2 depth1 = vec2(0.0,0.0);
  337. float depth = 0.0;
  338. bool useDepth0 = false;
  339. bool useDepth1 = true;
  340. #if defined(usePanoMap0)
  341. useDepth0 = true;
  342. #if defined(UnableMixTwoDepth)
  343. if(progress_<0.5){
  344. useDepth1 = false;
  345. }else{
  346. useDepth0 = false;
  347. }
  348. #endif
  349. if(useDepth0) depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, ceilHeight0, eyePos);
  350. #endif
  351. if(useDepth1) depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, ceilHeight1, eyePos);
  352. #if defined(UnableMixTwoDepth)
  353. depth = useDepth0 ? depth0.y : depth1.y;//不支持叠加,只能用其中一个,过渡时无法渐变
  354. #else
  355. depth = mix(depth0.y,depth1.y,progress_);
  356. #endif
  357. gl_FragDepthEXT = clamp(depth, 0.0, 1.0); //防止部分手机出现黑块。ios 16 。 因为我给的超远值超出范围
  358. #endif
  359. }
  360. `
  361. }
  362. //注:gl_FragDepthEXT 修改了确实能像真实mesh那样遮挡住在后面的物体。但是为过渡时不能直接像有模型那样,和角度有关。
  363. export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
  364. constructor( ){
  365. let defines = {depthTexUVyLimit: Potree.config.depthTexUVyLimit}
  366. if(Potree.browser.maybeQilin()){
  367. defines.UnableMixTwoDepth = 1 //该系统在开启硬件加速后,webgl容易出bug。如过渡时黑屏报错,因无法将两个depth叠加。见bug记录
  368. }
  369. let {vs,fs} = Common.changeShaderToWebgl2(shader.vertexShader, shader.fragmentShader, 'RawShaderMaterial')
  370. if(!Potree.settings.isWebgl2){
  371. defines['round(x)'] = 'floor(x + 0.5)' //webgl1 unsupport round
  372. fs = fs.replace('int(round(channels.x * 255.0)) << 8', 'int(round(channels.x * 255.0 * pow(2.0, 8.0)))') //unsupport <<
  373. }
  374. super({
  375. fragmentShader: fs,
  376. vertexShader: vs,
  377. uniforms: THREE.UniformsUtils.clone(shader.uniforms),
  378. side:THREE.DoubleSide,
  379. name: "ModelTextureMaterial",
  380. defines,
  381. })
  382. this.glslVersion = Potree.settings.isWebgl2 && '300 es'
  383. this.uniforms.classificationLUT.value = this.classificationTexture = getClassificationLUT()
  384. let setSize = (e)=>{
  385. let viewport = e.viewport
  386. //let viewportOffset = viewport.offset || new Vector2()
  387. let resolution = viewport.resolution2
  388. //this.uniforms.viewport.value.set(viewportOffset.x, viewportOffset.y, resolution.x, resolution.y)
  389. this.uniforms.viewport.value.set(0,0, resolution.x, resolution.y);// xy是在viewport中的left和bottom,和整个窗口没有关系,所以不是viewportOffset。几乎都是0,0
  390. }
  391. let viewport = viewer.mainViewport;
  392. setSize({viewport})
  393. viewer.addEventListener('resize',(e)=>{
  394. if(e.viewport.name != "MainView")return
  395. setSize(e)
  396. })
  397. //var supportExtDepth = !!Features.EXT_DEPTH.isSupported()
  398. {
  399. //add
  400. viewer.addEventListener('camera_changed', (e)=>{
  401. if(e.viewport.name != "MainView")return
  402. //this.uniforms.projectionMatrix.value.copy(e.camera.projectionMatrix)
  403. e.camera && this.uniforms.inverseProjectionMatrix.value.copy(e.camera.projectionMatrixInverse)
  404. })
  405. let setClass = ()=>{
  406. this.classification = viewer.classifications
  407. ExtendPointCloudMaterial.prototype.recomputeClassification.call(this)
  408. }
  409. viewer.addEventListener('classifications_changed',setClass)
  410. setClass()
  411. this._gradient = Gradients.ir //海拔贴图种类,火灾也是这个
  412. this.uniforms.gradient.value = ExtendPointCloudMaterial.generateGradientTexture(this._gradient);
  413. }
  414. let progress = 0
  415. Object.defineProperty(this.uniforms.progress, 'value', {
  416. get: function () {
  417. return progress
  418. },
  419. set: e => {
  420. if (e < 1 && !Potree.settings.fastTran ) {
  421. if (!('usePanoMap0' in this.defines)) {
  422. this.defines.usePanoMap0 = ''
  423. this.needsUpdate = true
  424. }
  425. } else {
  426. if ('usePanoMap0' in this.defines) {
  427. delete this.defines.usePanoMap0
  428. this.needsUpdate = true
  429. }
  430. }
  431. progress = e
  432. },
  433. })
  434. //-------------------------------------
  435. }
  436. setProjectedPanos(pano0, pano1, progressValue ){
  437. progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
  438. //pano0.ensureSkyboxReadyForRender();
  439. if(pano0){
  440. this.uniforms.pano0Map.value = pano0.getSkyboxTexture();//pano0.texture
  441. this.uniforms.pano0Position.value.copy(pano0.position)
  442. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ );
  443. //pano1.ensureSkyboxReadyForRender();
  444. }
  445. this.uniforms.pano1Map.value = pano1.getSkyboxTexture()//pano1.texture;
  446. this.uniforms.pano1Position.value.copy(pano1.position)
  447. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */ );
  448. this.pano0 = pano0
  449. this.pano1 = pano1
  450. this.updateDepthTex(pano0)
  451. this.updateDepthTex(pano1)
  452. this.updateTempEnable()
  453. this.updateClassEnable()
  454. //console.log('setProjectedPanos', pano0&&pano0.id, pano1&&pano1.id)
  455. this.needsUpdate = true;
  456. }
  457. updateDepthTex(pano, extra){
  458. if( !Potree.settings.useDepthTex || !pano || !pano.depthTex || pano!=this.pano0 && pano!=this.pano1)return
  459. //console.log('updateDepthTex', pano.id, this.pano0 && this.pano0.id, this.pano1 && this.pano1.id)
  460. if(this.pano0){
  461. this.uniforms.depthMap0.value = this.pano0.entered ? this.pano0.depthTex : null; //dispose了就不要赋值否则dispose会失败
  462. this.uniforms.cameraHeight0.value = this.pano0.floorPosition.distanceTo(this.pano0.position)
  463. this.uniforms.ceilHeight0.value = this.pano0.getCeilHeight() - this.pano0.position.z
  464. }
  465. if(this.pano1){
  466. this.uniforms.depthMap1.value = this.pano1.depthTex //pano1还没entered时也需要,可能在飞入
  467. this.uniforms.cameraHeight1.value = this.pano1.floorPosition.distanceTo(this.pano1.position)
  468. this.uniforms.ceilHeight1.value = this.pano1.getCeilHeight() - this.pano1.position.z
  469. }
  470. if(this.dontChangeDepth)return
  471. let hasDepthTex = this.pano0 && this.pano1 && this.pano0.pointcloud.hasDepthTex && this.pano1.pointcloud.hasDepthTex //暂时不知道一个有图一个没图怎么写所以
  472. Potree.Utils.addOrRemoveDefine(this, 'hasDepthTex', hasDepthTex?'add':'remove' )
  473. }
  474. updateTempEnable(){
  475. let tex0 = Potree.settings.showHotTemp && this.pano0.tempTex || Potree.settings.showHotIr && this.pano0.irTex
  476. let tex1 = Potree.settings.showHotTemp && this.pano1.tempTex || Potree.settings.showHotIr && this.pano1.irTex
  477. this.uniforms.pano0TempMap.value = tex0
  478. this.uniforms.pano1TempMap.value = tex1
  479. Potree.Utils.addOrRemoveDefine(this, 'useTempMap0', tex0?'add':'remove' )
  480. Potree.Utils.addOrRemoveDefine(this, 'useTempMap1', tex1?'add':'remove' )
  481. viewer.dispatchEvent('content_changed')
  482. }
  483. updateClassEnable(){
  484. let hasClassTex0 = Potree.settings.showClass && this.pano0.segTex
  485. let hasClassTex1 = Potree.settings.showClass && this.pano1.segTex
  486. this.uniforms.pano0ClassMap.value = this.pano0.segTex
  487. this.uniforms.pano1ClassMap.value = this.pano1.segTex
  488. Potree.Utils.addOrRemoveDefine(this, 'useClassMap0', hasClassTex0?'add':'remove' )
  489. Potree.Utils.addOrRemoveDefine(this, 'useClassMap1', hasClassTex1?'add':'remove' )
  490. viewer.dispatchEvent('content_changed')
  491. }
  492. }
  493. ModelTextureMaterial.prototype.setTempRange = ExtendPointCloudMaterial.prototype.setTempRange