Common.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import math from './math.js'
  3. import '../../../libs/other/UPNG.js'
  4. var Common = {
  5. autoPlayList:[],
  6. sortByScore: function(list, request, rank){
  7. var i = request ? Common.filterAll(list, request) : list
  8. return 0 === i.length ? [] : i = i.map(function(e) {
  9. let results = rank.map(function(f){return f(e)})
  10. let scores = results.map(e=>e.score != void 0 ? e.score : e)
  11. let logs = results.map(e=>e.log)
  12. return {
  13. item: e,
  14. scores,
  15. logs,
  16. score: scores.reduce(function(t, i) {//总分
  17. return t + i
  18. }, 0)
  19. }
  20. }).sort(function(e, t) {
  21. return t.score - e.score;
  22. })
  23. }
  24. ,
  25. filterAll: function(e, t) {
  26. return e.filter(function (e) {
  27. return t.every(function (t) {
  28. return t(e)
  29. })
  30. })
  31. },
  32. //---------------
  33. find : function(list, request, rank, sortByScore ) {
  34. if(sortByScore){
  35. var r = this.sortByScore(list, request, rank)
  36. return r[0] && r[0].item
  37. }else{
  38. var i = request ? Common.filterAll(list, request) : list
  39. return 0 === i.length ? null : (rank && rank.forEach(function(e) {
  40. i = Common.stableSort(i, e)
  41. }),
  42. i[0])
  43. }
  44. }
  45. ,
  46. stableSort: function(e, f) {//用到排序函数,涉及到两个item相减
  47. return e.map(function(e, i) {
  48. return {
  49. value: e,
  50. index: i
  51. }
  52. }).sort(function(e, u) {
  53. var n = f(e.value, u.value);
  54. return 0 !== n ? n : e.index - u.index //似乎就是加多了这一步:若差距为0,按照原顺序
  55. }).map(function(e) {
  56. return e.value
  57. })
  58. },
  59. average: function (e, t) {
  60. if (0 === e.length)
  61. return null;
  62. for (var i = 0, n = 0, r = 0; r < e.length; r++) {
  63. var o = t ? e[r][t] : e[r];
  64. i += o,
  65. n++
  66. }
  67. return i / n
  68. },
  69. //---------------------------
  70. getMixedSet : function(arr1, arr2){//交集
  71. return arr1.filter(item=>arr2.includes(item));
  72. },
  73. getUnionSet : function(arr1, arr2){//并集
  74. return arr1.concat(arr2.filter(item=>!arr1.includes(item)))
  75. },
  76. getDifferenceSet : function(arr1, arr2){//差集 不能识别重复的,如getDifferenceSet([1,2,2],[1,1,2]) 为空
  77. var arr11 = arr1.filter(item=>!arr2.includes(item));
  78. var arr22 = arr2.filter(item=>!arr1.includes(item));
  79. return arr11.concat(arr22)
  80. },
  81. getDifferenceSetMuti : function(arr){//收集绝对没有重复的元素,也就是判断出现次数=1的
  82. var set = [];
  83. arr.forEach(arr1=>{
  84. arr1.forEach(item=>{
  85. var index = set.indexOf(item)
  86. if(index>-1){
  87. set.splice(index, 1)
  88. }else{
  89. set.push(item)
  90. }
  91. })
  92. })
  93. return set;
  94. }
  95. ,
  96. CloneJson : function(data){
  97. var str = JSON.stringify(data)
  98. return JSON.parse(str)
  99. }
  100. ,
  101. CloneObject : function (copyObj, isSimpleCopy, simpleCopyList = [], judgeSimpleCopyFun) {
  102. //isSimpleCopy 只复制最外层
  103. //复制json result的可能:普通数字或字符串、普通数组、复杂对象
  104. judgeSimpleCopyFun || (judgeSimpleCopyFun=()=>{})
  105. if (!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' ||copyObj.isObject3D || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className) || judgeSimpleCopyFun(copyObj)) {
  106. return copyObj
  107. }
  108. if (copyObj instanceof Array) {
  109. return copyObj.map(e => {
  110. return this.CloneObject(e, isSimpleCopy, simpleCopyList, judgeSimpleCopyFun)
  111. })
  112. } else {
  113. if (copyObj.clone instanceof Function) {
  114. //解决一部分
  115. return copyObj.clone()
  116. }
  117. }
  118. let result = {}
  119. for (var key in copyObj) {
  120. if (copyObj[key] instanceof Object && !isSimpleCopy ) result[key] = this.CloneObject(copyObj[key], isSimpleCopy, simpleCopyList, judgeSimpleCopyFun)
  121. else result[key] = copyObj[key]
  122. //如果是函数类同基本数据,即复制引用
  123. }
  124. return result
  125. }
  126. ,
  127. CloneClassObject :function(copyObj, {ignoreList=[],simpleCopyList=[]}={}){//复杂类对象
  128. var newobj = new copyObj.constructor();
  129. this.CopyClassObject(newobj, copyObj, {ignoreList,simpleCopyList})
  130. return newobj
  131. }
  132. ,
  133. CopyClassObject :function(targetObj, copyObj, {ignoreList=[],simpleCopyList=[]}={}){//复杂类对象
  134. for(let i in copyObj){
  135. if(i in copyObj.__proto__)break; //到函数了跳出
  136. if(ignoreList.includes(i)){
  137. continue;
  138. }else if(simpleCopyList.includes(i)){
  139. targetObj[i] = copyObj[i]
  140. }else{
  141. targetObj[i] = this.CloneObject(copyObj[i], false, simpleCopyList )
  142. }
  143. /* else if(copyObj[i].clone instanceof Function ){
  144. targetObj[i] = copyObj[i].clone()
  145. }else{
  146. targetObj[i] = copyObj[i];
  147. } */
  148. }
  149. }
  150. ,
  151. ifSame : function(object1, object2, simpleEqualClass=[]){ //对于复杂的类对象,若能简单判断就直接写进simpleEqualClass
  152. if(object1 == object2 )return true // 0 != undefined , 0 == ''
  153. else if(!object1 || !object2) return false
  154. else if(object1.constructor != object2.constructor){
  155. return false
  156. }else if(simpleEqualClass.some(className => object1 instanceof className)){
  157. return object1 == object2
  158. }else if(object1 instanceof Array ) {
  159. if(object1.length != object2.length)return false;
  160. var _object2 = object2.slice(0);
  161. for(let i=0;i<object1.length;i++){
  162. var u = _object2.find(e=>Common.ifSame(object1[i], e, simpleEqualClass));
  163. if(u == void 0 && !_object2.includes(u) && !object1.includes(u))return false;
  164. else{
  165. let index = _object2.indexOf(u);
  166. _object2.splice(index,1);
  167. }
  168. }
  169. return true
  170. }else if(object1.equals instanceof Function ){//复杂数据仅支持这种,其他的可能卡住?
  171. return object1.equals(object2)
  172. }else if(typeof object1 == 'number' || typeof object1 == 'string'){
  173. if(isNaN(object1) && isNaN(object2))return true
  174. else return object1 == object2
  175. }else if(typeof object1 == "object"){
  176. var keys1 = Object.keys(object1)
  177. var keys2 = Object.keys(object2)
  178. if(!Common.ifSame(keys1,keys2,simpleEqualClass))return false;
  179. for(let i in object1){
  180. var same = Common.ifSame(object1[i], object2[i],simpleEqualClass);
  181. if(!same)return false
  182. }
  183. return true
  184. }else{
  185. console.log('isSame出现例外')
  186. }
  187. }
  188. ,
  189. downloadFile : function(data, filename, cb) {
  190. var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  191. save_link.href = data;
  192. save_link.download = filename;
  193. var event = document.createEvent('MouseEvents');
  194. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  195. save_link.dispatchEvent(event);
  196. cb && cb();
  197. },
  198. replaceAll : function (str, f, e ) {
  199. //f全部替换成e
  200. if(str.replaceAll ) return str.replaceAll(f, e)
  201. else{
  202. let escapeRegExp = (string)=>{
  203. return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  204. }
  205. return str.replace(new RegExp(escapeRegExp(f), 'g'), e);
  206. /* var reg = new RegExp(f, "g"); //创建正则RegExp对象 这个没法转换'('
  207. return str.replace(reg, e); //str.split(f).join(e); */
  208. }
  209. },
  210. dealURL(url=''){
  211. let urlNew = this.replaceAll(url, "+", "%2B"); //this.replaceAll(url, "\\+", "%2B");// 浏览器似乎不支持访问带+的地址
  212. urlNew = this.replaceAll(urlNew, "/.//", "/") //去除双斜杠(/.//)
  213. //urlNew = encodeURIComponent(url)
  214. return urlNew
  215. },
  216. getNameFromURL(url, removePostfix){
  217. if(!url)return ''
  218. let get = (e)=>{
  219. let a = e.split('/').pop()
  220. if(removePostfix) a = a.split('.')[0]
  221. return a
  222. }
  223. if(url instanceof Array){
  224. return url.map(e=>get(e))
  225. }
  226. return get(url)
  227. },
  228. //---------------------------
  229. intervalTool:{ //延时update,防止卡顿
  230. list:[],
  231. /* isWaiting:function(name, func, delayTime){
  232. if(!this.list.includes(name)){ //如果没有该项, 则开始判断
  233. var needWait = func(); //触发了改变,则等待一段时间后再自动判断
  234. if(needWait){
  235. this.list.push(name);
  236. setTimeout(()=>{
  237. var a = this.list.indexOf(name);
  238. this.list.splice(a,1);
  239. this.isWaiting(name, func, delayTime) //循环
  240. },delayTime)
  241. }
  242. }
  243. }, */
  244. isWaiting:function(name, func, delayTime/* , autoCycle */){
  245. let item = this.list.find(e=>e.name == name)
  246. if(!item){ //如果没有该项, 则加入循环
  247. let ifContinue = func()
  248. item = {name, func, delayTime}
  249. /* if(name == 'processPriorityQueue'){
  250. console.log('isWaiting', delayTime)
  251. } */
  252. this.list.push(item);
  253. setTimeout(()=>{
  254. var a = this.list.indexOf(item);
  255. this.list.splice(a,1);
  256. let {func, delayTime} = item
  257. if(item.requestUpdate || ifContinue ) this.isWaiting(name, func, delayTime) //循环
  258. },delayTime)
  259. }else{//如果有该项,说明现在请求下一次继续更新
  260. //if(delayTime == 0){//想立刻更新一次
  261. // func()
  262. //}else{
  263. //更新属性
  264. item.func = func
  265. item.delayTime = delayTime
  266. item.requestUpdate = true
  267. //}
  268. }
  269. },
  270. }
  271. ,
  272. waitTool:{//定时器,在等待的这段时间内如果又触发则重新计时
  273. list:[],
  274. wait(name, func, time){
  275. let item = this.list.find(e=>e.name == name)
  276. let timer = setTimeout(()=>{
  277. func()
  278. let index = this.list.indexOf(item)
  279. this.list.splice(index, 1)
  280. }, time)
  281. if(item){
  282. clearTimeout(item.timer)
  283. }else{
  284. item = {name}
  285. this.list.push(item)
  286. }
  287. item.timer = timer
  288. },
  289. cancel(name){
  290. let index = this.list.findIndex(e=>e.name == name)
  291. index>-1 && this.list.splice(index, 1)
  292. }
  293. }
  294. ,
  295. pushToGroupAuto : function(items, groups, recognizeFunction, recognizeGroup){//自动分组。 items是将分到一起的组合。items.length = 1 or 2.
  296. recognizeFunction = recognizeFunction || function(){}
  297. if(recognizeGroup){ //有更复杂的识别处理,直接传递整个组
  298. var atGroups = groups.filter(group=>recognizeGroup(group, items))
  299. }else{
  300. var atGroups = groups.filter(group=>group.find(
  301. item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1])
  302. ))
  303. }
  304. if(atGroups.length){//在不同组
  305. //因为items是一组的,所以先都放入组1
  306. items.forEach(item=> {if(!atGroups[0].includes(item)) atGroups[0].push(item);})
  307. if(atGroups.length>1){//如果在不同组,说明这两个组需要合并
  308. var combineGroup = []
  309. atGroups.forEach(group=>{
  310. combineGroup = Common.getUnionSet(combineGroup, group)
  311. groups.splice(groups.indexOf(group),1)
  312. })
  313. groups.push(combineGroup)
  314. }
  315. }else{//直接加入为一组
  316. groups.push(items)
  317. }
  318. },
  319. getBestCount : (function(){
  320. let lastCount = {}
  321. return function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog, maxHistory){
  322. let timeStamp = performance.getEntriesByName("loop-start");
  323. let count
  324. if(timeStamp.length){
  325. let dur = performance.now() - timeStamp[timeStamp.length-1].startTime; //dur在iphoneX中静止有7,pc是2
  326. count = Math.round(math.linearClamp(dur, [durBound1,durBound2], [maxCount, minCount]))
  327. if (maxHistory) {
  328. if (!lastCount[name]) lastCount[name] = []
  329. if (count == 0 && lastCount[name].length > maxHistory - 1 && !lastCount[name].some(e => e > 0)) {
  330. count = 1
  331. }
  332. lastCount[name].push(count)
  333. if (lastCount[name].length > maxHistory) lastCount[name].splice(0, 1)
  334. }
  335. if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
  336. name && count && console.log(name, count , ' ,dur:', dur.toFixed(3))
  337. }
  338. }else{
  339. count = maxCount // ?
  340. }
  341. //主要在手机端有效果。
  342. return count
  343. }
  344. })(),
  345. getBestCountFPS(name, ifLog, minCount=1, maxCount=6, minFps = 10, maxFps = 60, minPanoCount = 200, maxPanoCount = 1000 ){
  346. let fps = Potree.fps
  347. let count = math.linearClamp(fps, [minFps, maxFps], [minCount, maxCount])
  348. let count2 = math.linearClamp(viewer.images360.panos.length, [minPanoCount, maxPanoCount], [minCount, maxCount])
  349. count = (count + count2)/2
  350. count = Math.round(count)
  351. if(ifLog){
  352. name && count && console.log(name, count , ' ,fps:', fps.toFixed(3))
  353. }
  354. return count
  355. },
  356. batchHandling : {//分批处理
  357. lists:[],
  358. getSlice : function(name, items , {stopWhenAllUsed, min=5,max=100, durBound1 , durBound2, useEquals , maxUseCount}){
  359. if(items.length == 0 ||
  360. ((maxUseCount = maxUseCount == void 0 ? Common.getBestCount(name, min,max , durBound1, durBound2 /* , true */ ) : maxUseCount), !maxUseCount) //本次最多可以使用的个数
  361. ){
  362. return {list:[]}
  363. }
  364. if(!this.lists[name]) this.lists[name] = {list:[] }
  365. //更新列表项目,但不变原来的顺序
  366. let list = this.lists[name].list.filter(a=>items.some(item=> useEquals ? a.item.equals(item) : a.item == item))//去掉已经不在items里的项目
  367. this.lists[name].list = list
  368. items.forEach(item=>{//增加新的项目。
  369. if(!list.some(a=>useEquals ? a.item.equals(item) : a.item == item )){
  370. list.push({item, count:0})
  371. }
  372. })
  373. //至此,在后排的都是未使用的
  374. let unUsed = list.filter(e=>e.count == 0)//未使用的项目(count为0)优先
  375. let result = []
  376. unUsed.slice(0,maxUseCount).forEach(e=>{
  377. result.push(e.item);
  378. e.count ++;
  379. })
  380. if(unUsed.length > maxUseCount){
  381. //还是剩有未使用的项目,等待下一次
  382. }else{
  383. //所有项目都能使用一次
  384. if(!stopWhenAllUsed){ //若不是全部使用就停止
  385. let wholeCount = Math.min(items.length, maxUseCount);
  386. let restCount = wholeCount - result.length; //补齐
  387. list.slice(0,restCount).forEach(e=>{
  388. result.push(e.item);
  389. e.count ++;
  390. })
  391. }
  392. list.forEach(e=>e.count--) //复原,等待新的循环
  393. }
  394. /* result.forEach((e,i)=>{//有重复的
  395. if( result.slice(0,i).some(a=>a.equals(e)) || result.slice(i+1).some(a=>a.equals(e)) ) {
  396. console.log(e)
  397. }
  398. }) */
  399. return {list:result }
  400. }
  401. },
  402. getRootWindow(){//获取包含Potree的根window
  403. let win = window
  404. try{
  405. while(win.parent!=win && win.parent.Potree){
  406. win = win.parent
  407. }
  408. if(window != win)return win
  409. }catch(e){
  410. //console.log(e) //可能跨域,从而win.parent.Potree报错
  411. console.log('getRootWindow 跨域')
  412. return
  413. }
  414. },
  415. watch: function(object, propName, initialValue){ //监听某个属性的变化
  416. let v = initialValue
  417. Object.defineProperty(object, propName, {
  418. get: function() {
  419. return v
  420. },
  421. set: function(e) {
  422. console.warn('watch:',propName, e)
  423. v = e
  424. }
  425. })
  426. },
  427. imgAddLabel : function (img, labelImg, labelInfo = {}) {
  428. //图上加另一张小图,用于添加水印
  429. let canvas
  430. if(img instanceof Image){
  431. canvas = document.createElement('canvas')
  432. }else{
  433. canvas = img
  434. }
  435. let context = canvas.getContext('2d')
  436. let marginLeft = labelInfo.bgMargin && labelInfo.bgMargin.left || 0
  437. let marginRight = labelInfo.bgMargin && labelInfo.bgMargin.right || 0
  438. let marginTop = labelInfo.bgMargin && labelInfo.bgMargin.top || 0
  439. let marginBottom = labelInfo.bgMargin && labelInfo.bgMargin.bottom || 0
  440. if(img instanceof Image){//如果img是canvas,说明已绘制在canvas上了就不用绘制了
  441. let width = img.width + marginLeft + marginRight
  442. let height = img.height + marginTop + marginBottom
  443. canvas.width = width
  444. canvas.height = height
  445. if(labelInfo.bgColor){
  446. context.fillStyle = 'rgba(' + labelInfo.bgColor.r + ',' + labelInfo.bgColor.g + ',' + labelInfo.bgColor.b + ',' + labelInfo.bgColor.a + ')';
  447. context.fillRect(0,0,width,height);
  448. }
  449. context.drawImage(img, marginLeft, marginTop, img.width, img.height)
  450. }
  451. let labelWidth = labelInfo.widthRatioToImg ? img.width * labelInfo.widthRatioToImg : labelImg.width //widthRatioToImg:label的width占img的width的比例
  452. let labelHeight = (labelWidth * labelImg.height) / labelImg.width
  453. if (labelInfo.leftRatioToImg == void 0 && labelInfo.rightRatioToImg != void 0) {
  454. labelInfo.leftRatioToImg = 1 - labelInfo.rightRatioToImg - (labelInfo.widthRatioToImg || labelImg.width / img.width)
  455. }
  456. if (labelInfo.topRatioToImg == void 0 && labelInfo.bottomRatioToImg != void 0) {
  457. labelInfo.topRatioToImg = 1 - labelInfo.bottomRatioToImg - labelHeight / img.height
  458. }
  459. let labelLeft = img.width * labelInfo.leftRatioToImg + marginLeft //leftRatioToImg:label的left占img的width的比例
  460. let labelTop = img.height * labelInfo.topRatioToImg + marginTop //topRatioToImg:label的top占img的height的比例
  461. context.globalAlpha = labelInfo.opacity != void 0 ? labelInfo.opacity : 1
  462. context.drawImage(labelImg, labelLeft, labelTop, labelWidth, labelHeight)
  463. if(labelInfo.outputCanvas){
  464. return canvas
  465. }
  466. var dataUrl = canvas.toDataURL('image/png', labelInfo.compressRatio)
  467. //Common.downloadFile(dataUrl, 'screenshot.png')
  468. context.clearRect(0,0,canvas.width,canvas.height)
  469. return dataUrl
  470. },
  471. mobileAutoPlay(media, playFun){//移动端。不这么写video不会播放 . (2022.11.29: 可为何加了Hot.updateHots之后又会自动播了?https有关?
  472. if(this.autoPlayList.includes(media))return
  473. this.autoPlayList.push(media)
  474. viewer.addEventListener
  475. let events = ['global_touchstart','global_mousedown']
  476. let fun = ()=>{
  477. let index = this.autoPlayList.indexOf(media)
  478. if(index>-1){
  479. console.log( 'try autoplay '+ media.src)
  480. playFun()
  481. this.autoPlayList.splice(index,1)
  482. events.forEach((eventName)=>{
  483. viewer.removeEventListener(eventName,fun)
  484. })
  485. }
  486. }
  487. events.forEach((eventName)=>{
  488. viewer.addEventListener(eventName,fun)
  489. })
  490. },
  491. /* changeShaderToWebgl2(vs, fs, matType, otherReplaces=[]){//部分shader要根据webgl版本作更改
  492. if(!Potree.settings.isWebgl2)return {vs, fs}
  493. let turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT') )
  494. let addV300 = turnTo300 && matType != 'RawShaderMaterial' // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
  495. let change = (shader, shaderType)=>{
  496. let newShader = shader
  497. if(turnTo300){ //非shaderMaterial需要手动改为300 es的写法
  498. addV300 && (newShader = '#version 300 es \n' + newShader) //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
  499. newShader = newShader.replaceAll('varying ', shaderType == 'vs' ? 'out ' : 'in ')
  500. newShader = newShader.replaceAll('attribute ', 'in ')
  501. if(shaderType == 'fs'){
  502. newShader = newShader.replaceAll('gl_FragColor', 'fragColor')
  503. newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main' )//在void main前加入这个声明
  504. }
  505. newShader = newShader.replaceAll('gl_FragDepthEXT','gl_FragDepth')
  506. newShader = newShader.replaceAll('texture2D','texture')
  507. newShader = newShader.replaceAll('textureCube','texture')
  508. }
  509. newShader = newShader.replace('#extension GL_EXT_frag_depth : enable','')
  510. newShader = newShader.replaceAll('defined(GL_EXT_frag_depth) &&','')
  511. otherReplaces.forEach(({oldStr,newStr})=>{
  512. newShader = newShader.replaceAll(oldStr,newStr)
  513. })
  514. return newShader
  515. }
  516. vs = change(vs,'vs')
  517. fs = change(fs,'fs')
  518. //console.log('成功替换为webgl2' )
  519. return {vs,fs}
  520. }//three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
  521. */
  522. changeShaderToWebgl2(vs, fs, matType, otherReplaces=[]){//部分shader要根据webgl版本作更改
  523. if(!Potree.settings.isWebgl2)return {vs, fs}
  524. let turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT') )
  525. let addV300 = turnTo300 && matType != 'RawShaderMaterial' // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
  526. let change = (shader, shaderType)=>{
  527. let newShader = shader
  528. if(turnTo300){ //非shaderMaterial需要手动改为300 es的写法
  529. addV300 && (newShader = '#version 300 es \n' + newShader) //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
  530. newShader = this.replaceAll(newShader, 'varying ', shaderType == 'vs' ? 'out ' : 'in ')
  531. newShader = this.replaceAll(newShader, 'attribute ', 'in ')
  532. if(shaderType == 'fs'){
  533. newShader = this.replaceAll(newShader, 'gl_FragColor', 'fragColor')
  534. newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main' )//在void main前加入这个声明
  535. }
  536. newShader = this.replaceAll(newShader, 'gl_FragDepthEXT','gl_FragDepth')
  537. newShader = this.replaceAll(newShader, 'texture2D','texture')
  538. newShader = this.replaceAll(newShader, 'textureCube','texture')
  539. }
  540. newShader = newShader.replace('#extension GL_EXT_frag_depth : enable','')
  541. newShader = this.replaceAll(newShader,'defined(GL_EXT_frag_depth) &&','')
  542. otherReplaces.forEach(({oldStr,newStr})=>{
  543. newShader = this.replaceAll(newShader, oldStr, newStr)
  544. })
  545. return newShader
  546. }
  547. vs = change(vs,'vs')
  548. fs = change(fs,'fs')
  549. //console.log('成功替换为webgl2' )
  550. return {vs,fs}
  551. },//three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
  552. load16bitPngTex(src,onLoad,onError, pixelFun){//单通道无符号16位的png (正常图片是32位一个像素)
  553. const texture = new THREE.DataTexture
  554. fetch(src)
  555. .then(response => {
  556. if(!response.ok){
  557. console.log('loadFile失败' , src )
  558. return onError && onError()
  559. }
  560. return response.arrayBuffer()
  561. }).then(arrayBuffer => { //文件数据
  562. const png = UPNG.decode(arrayBuffer); //解析出像素数据
  563. let pixelCount = png.width * png.height
  564. let data = new Uint8Array(pixelCount * 4)
  565. let view = new DataView(data.buffer);
  566. for(let i=0;i<pixelCount;i++){ //将uint16的只有两个byte的扩充到四个byte,因为贴图只支持4个byte的
  567. let r = png.data[i*2]
  568. let g = png.data[i*2+1]
  569. data[i*4+0] = g //反了
  570. data[i*4+1] = r
  571. data[i*4+2] = data[i*4+3] = 255; //无用值填充
  572. if(pixelFun){
  573. pixelFun(view.getUint16(i*4,true), i , pixelCount) //原值
  574. }
  575. }
  576. texture.image.data = data
  577. texture.image.width = png.width;
  578. texture.image.height = png.height;
  579. texture.image.src = src
  580. texture.needsUpdate = true;
  581. onLoad && onLoad()
  582. })
  583. .catch(error => {
  584. onError && onError(error)
  585. });
  586. return texture
  587. }
  588. }
  589. Potree.Common = Common
  590. export default Common