utils.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. var lerp = {
  2. vector: function(e, t, f) {//xzw change, add f
  3. var i = e.clone();
  4. return t = t.clone(),
  5. function(n) {
  6. e.set(i.x * (1 - n) + t.x * n, i.y * (1 - n) + t.y * n, i.z * (1 - n) + t.z * n)
  7. f && f(e,n);
  8. }
  9. },
  10. quaternion: function(e, t, f) {//xzw change, add f
  11. var i = e.clone();
  12. return function(n) {
  13. e.copy(i).slerp(t, n);
  14. f && f(e,n);
  15. }
  16. },
  17. property: function(e, t, i, n) {
  18. var r = e[t];
  19. return function(o) {
  20. e[t] = r * (1 - o) + i * o,
  21. n && n(e[t])
  22. }
  23. },
  24. uniform: function(e, t, i) {
  25. var n = e.material.uniforms[t].value;
  26. return function(r) {
  27. try{
  28. e.material.uniforms[t] && (e.material.uniforms[t].value = n * (1 - r) + i * r)
  29. }catch(e){
  30. console.log(1)
  31. }
  32. }
  33. },
  34. matrix4: function(e, t) {
  35. var i = e.clone();
  36. return function(n) {
  37. for (var r = e.elements, o = i.elements, a = t.elements, s = 0; s < 16; s++)
  38. r[s] = o[s] * (1 - n) + a[s] * n
  39. }
  40. },
  41. allUniforms: function(e, t, i) {
  42. var n = e.map(function(e) {
  43. return this.uniform(e, t, i)
  44. }
  45. .bind(this));
  46. return function(e) {
  47. n.forEach(function(t) {
  48. t(e)
  49. })
  50. }
  51. }
  52. };
  53. //////
  54. var easing = {};
  55. //渐变曲线函数,反应加速度的变化
  56. easing.linearTween = function(e, t, i, n) {
  57. return i * e / n + t
  58. }
  59. ,
  60. easing.easeInQuad = function(e, t, i, n) {
  61. return e /= n,
  62. i * e * e + t
  63. }
  64. ,
  65. easing.easeOutQuad = function(e, t, i, n) {
  66. return e /= n,
  67. -i * e * (e - 2) + t
  68. }
  69. ,
  70. easing.easeInOutQuad = function(e, t, i, n) {
  71. return e /= n / 2,
  72. e < 1 ? i / 2 * e * e + t : (e--,
  73. -i / 2 * (e * (e - 2) - 1) + t)
  74. }
  75. ,
  76. easing.easeInCubic = function(e, t, i, n) {
  77. return e /= n,
  78. i * e * e * e + t
  79. }
  80. ,
  81. easing.easeOutCubic = function(e, t, i, n) {
  82. return e /= n,
  83. e--,
  84. i * (e * e * e + 1) + t
  85. }
  86. ,
  87. easing.easeInOutCubic = function(e, t, i, n) {
  88. return e /= n / 2,
  89. e < 1 ? i / 2 * e * e * e + t : (e -= 2,
  90. i / 2 * (e * e * e + 2) + t)
  91. }
  92. ,
  93. easing.easeInQuart = function(e, t, i, n) {
  94. return e /= n,
  95. i * e * e * e * e + t
  96. }
  97. ,
  98. easing.easeOutQuart = function(e, t, i, n) {
  99. return e /= n,
  100. e--,
  101. -i * (e * e * e * e - 1) + t
  102. }
  103. ,
  104. easing.easeInOutQuart = function(e, t, i, n) {
  105. return e /= n / 2,
  106. e < 1 ? i / 2 * e * e * e * e + t : (e -= 2,
  107. -i / 2 * (e * e * e * e - 2) + t)
  108. }
  109. ,
  110. easing.easeInQuint = function(e, t, i, n) {
  111. return e /= n,
  112. i * e * e * e * e * e + t
  113. }
  114. ,
  115. easing.easeOutQuint = function(e, t, i, n) {
  116. return e /= n,
  117. e--,
  118. i * (e * e * e * e * e + 1) + t
  119. }
  120. ,
  121. easing.easeInOutQuint = function(e, t, i, n) {
  122. return e /= n / 2,
  123. e < 1 ? i / 2 * e * e * e * e * e + t : (e -= 2,
  124. i / 2 * (e * e * e * e * e + 2) + t)
  125. }
  126. ,
  127. easing.easeInSine = function(e, t, i, n) {
  128. return -i * Math.cos(e / n * (Math.PI / 2)) + i + t
  129. }
  130. ,
  131. easing.easeOutSine = function(e, t, i, n) {
  132. return i * Math.sin(e / n * (Math.PI / 2)) + t
  133. }
  134. ,
  135. easing.easeInOutSine = function(e, t, i, n) {
  136. return -i / 2 * (Math.cos(Math.PI * e / n) - 1) + t
  137. }
  138. ,
  139. easing.easeInExpo = function(e, t, i, n) {
  140. return i * Math.pow(2, 10 * (e / n - 1)) + t
  141. }
  142. ,
  143. easing.easeOutExpo = function(e, t, i, n) {
  144. return i * (-Math.pow(2, -10 * e / n) + 1) + t
  145. }
  146. ,
  147. easing.easeInOutExpo = function(e, t, i, n) {
  148. return e /= n / 2,
  149. e < 1 ? i / 2 * Math.pow(2, 10 * (e - 1)) + t : (e--,
  150. i / 2 * (-Math.pow(2, -10 * e) + 2) + t)
  151. }
  152. ,
  153. easing.easeInCirc = function(e, t, i, n) {
  154. return e /= n,
  155. -i * (Math.sqrt(1 - e * e) - 1) + t
  156. }
  157. ,
  158. easing.easeOutCirc = function(e, t, i, n) {
  159. return e /= n,
  160. e--,
  161. i * Math.sqrt(1 - e * e) + t
  162. }
  163. ,
  164. easing.easeInOutCirc = function(e, t, i, n) {
  165. return e /= n / 2,
  166. e < 1 ? -i / 2 * (Math.sqrt(1 - e * e) - 1) + t : (e -= 2,
  167. i / 2 * (Math.sqrt(1 - e * e) + 1) + t)
  168. }
  169. ,
  170. easing.easeInElastic = function(e, t, i, n) {
  171. var r = 1.70158
  172. , o = 0
  173. , a = i;
  174. return 0 === e ? t : 1 === (e /= n) ? t + i : (o || (o = .3 * n),
  175. a < Math.abs(i) ? (a = i,
  176. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
  177. -(a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o)) + t)
  178. }
  179. ,
  180. easing.easeOutElastic = function(e, t, i, n) {
  181. var r = 1.70158
  182. , o = 0
  183. , a = i;
  184. return 0 === e ? t : 1 === (e /= n) ? t + i : (o || (o = .3 * n),
  185. a < Math.abs(i) ? (a = i,
  186. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
  187. a * Math.pow(2, -10 * e) * Math.sin((e * n - r) * (2 * Math.PI) / o) + i + t)
  188. }
  189. ,
  190. easing.easeInOutElastic = function(e, t, i, n) {
  191. var r = 1.70158
  192. , o = 0
  193. , a = i;
  194. return 0 === e ? t : 2 === (e /= n / 2) ? t + i : (o || (o = n * (.3 * 1.5)),
  195. a < Math.abs(i) ? (a = i,
  196. r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
  197. e < 1 ? -.5 * (a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o)) + t : a * Math.pow(2, -10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o) * .5 + i + t)
  198. }
  199. ,
  200. easing.easeInBack = function(e, t, i, n, r) {
  201. return void 0 === r && (r = 1.70158),
  202. i * (e /= n) * e * ((r + 1) * e - r) + t
  203. }
  204. ,
  205. easing.easeOutBack = function(e, t, i, n, r) {
  206. return void 0 === r && (r = 1.70158),
  207. i * ((e = e / n - 1) * e * ((r + 1) * e + r) + 1) + t
  208. }
  209. ,
  210. easing.easeInOutBack = function(e, t, i, n, r) {
  211. return void 0 === r && (r = 1.70158),
  212. (e /= n / 2) < 1 ? i / 2 * (e * e * (((r *= 1.525) + 1) * e - r)) + t : i / 2 * ((e -= 2) * e * (((r *= 1.525) + 1) * e + r) + 2) + t
  213. }
  214. ,
  215. easing.easeOutBounce = function(e, t, i, n) {
  216. return (e /= n) < 1 / 2.75 ? i * (7.5625 * e * e) + t : e < 2 / 2.75 ? i * (7.5625 * (e -= 1.5 / 2.75) * e + .75) + t : e < 2.5 / 2.75 ? i * (7.5625 * (e -= 2.25 / 2.75) * e + .9375) + t : i * (7.5625 * (e -= 2.625 / 2.75) * e + .984375) + t
  217. }
  218. ,
  219. easing.easeInBounce = function(e, t, i, r) {
  220. return i - easing.easeOutBounce(r - e, 0, i, r) + t
  221. }
  222. ,
  223. easing.easeInOutBounce = function(e, t, i, r) {
  224. return e < r / 2 ? .5 * easing.easeInBounce(2 * e, 0, i, r) + t : .5 * easing.easeOutBounce(x, 2 * e - r, 0, i, r) + .5 * i + t
  225. }
  226. /*
  227. 渐变
  228. */
  229. var transitions = {
  230. globalDone: null,
  231. funcs: [],
  232. counter: 0,
  233. uniqueID: 0,
  234. start: function(e, t, i, r, o, a, s, cancelFun) {
  235. r = r || 0
  236. let info = {
  237. func: e,
  238. current: -r * Math.abs(t), //当前时间
  239. duration: (1 - Math.max(r, 0)) * Math.abs(t), //总时长
  240. done: i,
  241. easing: o || easing.linearTween, //渐变曲线
  242. cycling: t < 0,
  243. running: !0,
  244. debug: r < 0,
  245. name: a || "T" + this.counter,
  246. id: void 0 === s ? this.counter : s,
  247. paused: !1,
  248. cancelFun : cancelFun, //取消时执行的函数
  249. }
  250. this.funcs.push(info),
  251. e(0, 16),
  252. this.counter += 1
  253. return info
  254. },
  255. trigger: function(e) {
  256. var t = void 0 === e.delayRatio ? 0 : e.delayRatio
  257. , i = e.func || function() {}
  258. , r = void 0 === e.duration ? 0 : e.duration;
  259. void 0 !== e.cycling && e.cycling && (r = -Math.abs(r));
  260. var o = e.done || null
  261. , a = e.easing || easing.linearTween
  262. , s = e.name || "R" + this.counter
  263. , l = void 0 === e.id ? this.counter : e.id;
  264. return this.start(i, r, o, t, a, s, l)
  265. },
  266. setTimeout: function(e, t, i) {
  267. var n = void 0 === i ? this.counter : i;
  268. return this.trigger({
  269. done: e,
  270. duration: void 0 === t ? 0 : t,
  271. name: "O" + this.counter,
  272. id: n
  273. })
  274. },
  275. pause: function() {
  276. this.paused = !0
  277. },
  278. resume: function() {
  279. this.paused = !1
  280. },
  281. update: function(e) {
  282. this.funcs.forEach(function(t) {
  283. if (!(t.paused || (t.current += 1e3 * e, t.current < 0))){
  284. if (t.current >= t.duration && !t.cycling) {
  285. var i = t.easing(1, 0, 1, 1);
  286. t.func(i, 1e3 * e),
  287. t.done && t.done(),
  288. t.running = !1
  289. } else {
  290. var n = t.easing(t.current % t.duration / t.duration, 0, 1, 1)
  291. , r = t.func(n, 1e3 * e) || !1;
  292. r && (t.done && t.done(),
  293. t.running = !1)
  294. }
  295. }
  296. });
  297. var t = this.funcs.length;
  298. this.funcs = this.funcs.filter(function(e) {
  299. return e.running
  300. });
  301. var i = this.funcs.length;
  302. if (t > 0 && 0 === i && this.globalDone) {
  303. var n = this.globalDone;
  304. this.globalDone = null,
  305. n()
  306. }
  307. },
  308. adjustSpeed: function(e, t) {
  309. for (var i = this.getById(e), n = 0; n < i.length; n++) {
  310. var r = i[n];
  311. r.duration /= t,
  312. r.current /= t
  313. }
  314. },
  315. getById: function(e) {
  316. return this.funcs.filter(function(t) {
  317. return e === t.id
  318. })
  319. },
  320. get: function(e) {
  321. for (var t = 0; t < this.funcs.length; t += 1)
  322. if (this.funcs[t].func === e)
  323. return this.funcs[t];
  324. return null
  325. },
  326. isRunning: function(e) {
  327. var t = this.get(e);
  328. return null !== t && t.running
  329. },
  330. countActive: function() {
  331. for (var e = 0, t = 0; t < this.funcs.length; t += 1)
  332. e += this.funcs[t].running;
  333. return e
  334. },
  335. listActive: function() {
  336. for (var e = [], t = 0; t < this.funcs.length; t += 1)
  337. this.funcs[t].running && e.push(this.funcs[t].name);
  338. return e
  339. },
  340. done: function(e) {
  341. this.globalDone = e
  342. },
  343. cancelById: function(e, dealCancelFun) { //xzw add dealDone
  344. var t = void 0 === e ? 0 : e;
  345. this.funcs = this.funcs.filter(function(e) {
  346. var is = e.id == t;
  347. if(is && dealCancelFun){
  348. e.cancelFun && e.cancelFun()
  349. }
  350. return !is
  351. })
  352. },
  353. cancel: function(e) {
  354. this.funcs = this.funcs.filter(function(t) {
  355. return t.func !== e
  356. })
  357. },
  358. getUniqueId: function() {
  359. return this.uniqueID -= 1,
  360. this.uniqueID
  361. }
  362. };
  363. let convertTool = {
  364. getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
  365. if(!camera)return
  366. var pos = point.clone().project(camera) //比之前hotspot的计算方式写得简单 project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
  367. var x,y;
  368. x = (pos.x + 1) / 2 * dom.clientWidth;
  369. y = (1 - (pos.y + 1) / 2) * dom.clientHeight;
  370. var inSight = x <= dom.clientWidth && x >= 0 //是否在屏幕中
  371. && y <= dom.clientHeight && y >= 0
  372. return {
  373. pos: new THREE.Vector2(x,y), // 屏幕像素坐标
  374. vector: pos, //(范围 -1 ~ 1)
  375. trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点 参见Tag.update
  376. inSight : inSight //在屏幕范围内可见
  377. };
  378. },
  379. ifShelter: function (pos3d, pos2d, camera, colliders, margin=0 ) {
  380. //检测某点在视线中是否被mesh遮挡
  381. if (!pos2d) pos2d = convertTool.getPos2d(pos3d )
  382. camera = camera || player.camera
  383. var ori = new THREE.Vector3(pos2d.x, pos2d.y, -1).unproject(camera) //找到视线原点
  384. var dir = pos3d.clone().sub(ori).normalize()
  385. var ray = new THREE.Raycaster(ori, dir); //由外向里 因为模型从内侧是可见的所以从外侧
  386. var o = ray.intersectObjects(colliders);
  387. var len = pos3d.distanceTo(ori);
  388. if (o && o.length) {
  389. for(var i=0;i<o.length;i++){
  390. if(o[i].distance < len-margin){ return true; }//有遮挡
  391. }
  392. }
  393. },
  394. updateVisible : function(object, reason, ifShow, level=0, type){//当所有加入的条件都不为false时才显示. reason='force'一般是强制、临时的
  395. if(!object.unvisibleReasons) object.unvisibleReasons = []; //如果length>0代表不可见
  396. if(!object.visibleReasons) object.visibleReasons = []; //在同级时,优先可见
  397. var update = function(){
  398. //先按从高到低的level排列
  399. object.unvisibleReasons = object.unvisibleReasons.sort((a,b)=>b.level-a.level)
  400. object.visibleReasons = object.visibleReasons.sort((a,b)=>b.level-a.level)
  401. var maxVisiLevel = object.visibleReasons[0] ? object.visibleReasons[0].level : -1
  402. var maxunVisiLevel = object.unvisibleReasons[0] ? object.unvisibleReasons[0].level : -1
  403. var shouldVisi = maxVisiLevel >= maxunVisiLevel
  404. var visiBefore = object.visible
  405. if(visiBefore != shouldVisi){
  406. object.visible = shouldVisi
  407. object.dispatchEvent({
  408. type: 'isVisible',
  409. visible: shouldVisi,
  410. reason,
  411. })
  412. }
  413. }
  414. if(ifShow){
  415. var index = object.unvisibleReasons.findIndex(e=>e.reason == reason)
  416. if(index > -1){
  417. type = 'cancel'
  418. object.unvisibleReasons.splice(index, 1);
  419. }
  420. if(type == 'add' ){
  421. if(!object.visibleReasons.some(e=>e.reason == reason)){
  422. object.visibleReasons.push({reason,level})
  423. }
  424. }
  425. }else{
  426. var index = object.visibleReasons.findIndex(e=>e.reason == reason)
  427. if(index > -1){
  428. type = 'cancel'
  429. object.visibleReasons.splice(index, 1);
  430. }
  431. if(type != 'cancel' ){
  432. if(!object.unvisibleReasons.some(e=>e.reason == reason)){
  433. object.unvisibleReasons.push({reason,level})
  434. }
  435. }
  436. }
  437. update()
  438. },
  439. toPrecision: function (e, t) {//xzw change 保留小数
  440. var f = function (e, t) {
  441. var i = Math.pow(10, t);
  442. return Math.round(e * i) / i
  443. }
  444. if (e instanceof Array) {
  445. for (var s = 0; s < e.length; s++) {
  446. e[s] = f(e[s], t);
  447. }
  448. return e;
  449. } else if (e instanceof Object) {
  450. for (var s in e) {
  451. e[s] = f(e[s], t);
  452. }
  453. return e;
  454. } else return f(e, t)
  455. },
  456. intervalTool:{ //延时update,防止卡顿
  457. list:[],
  458. isWaiting:function(name, func, delayTime){
  459. if(!this.list.includes(name)){ //如果没有该项, 则开始判断
  460. var needWait = func(); //触发了改变,则等待一段时间后再自动判断
  461. if(needWait){
  462. this.list.push(name);
  463. setTimeout(()=>{
  464. var a = this.list.indexOf(name);
  465. this.list.splice(a,1);
  466. this.isWaiting(name, func, delayTime) //循环
  467. },delayTime)
  468. }
  469. }
  470. },
  471. }
  472. ,
  473. }
  474. let math = {
  475. closeTo : function(a,b, precision=1e-6){
  476. let f = (a,b)=>{
  477. return Math.abs(a-b) < precision;
  478. };
  479. if(typeof (a) == 'number'){
  480. return f(a, b);
  481. }else {
  482. let judge = (name)=>{
  483. if(a[name] == void 0)return true //有值就判断,没值就不判断
  484. else return f(a[name],b[name])
  485. };
  486. return judge('x') && judge('y') && judge('z') && judge('w')
  487. }
  488. },
  489. linearClamp(value, xArr , yArr){ //xArr需要按顺序从小到大,yArr对应xArr中的值
  490. let len = xArr.length;
  491. if(value <= xArr[0]) return yArr[0]
  492. if(value >= xArr[len - 1]) return yArr[len - 1]
  493. let i = 0;
  494. while(++i < len ){
  495. if(value < xArr[i]){
  496. let x1 = xArr[i-1], x2 = xArr[i], y1 = yArr[i-1], y2 = yArr[i];
  497. value = y1 + ( y2 - y1) * (value - x1) / (x2 - x1);
  498. break
  499. }
  500. }
  501. return value
  502. }
  503. }
  504. var cameraLight = {
  505. clampVFOV: function(currentFov, maxHFov, width, height) {//限制currentFov, 使之造成的横向fov不大于指定值maxHFov
  506. var r = cameraLight.getHFOVFromVFOV(currentFov, width, height);
  507. return r > maxHFov ? cameraLight.getVFOVFromHFOV(maxHFov, width, height) : currentFov
  508. },
  509. getHFOVForCamera: function(camera, getRad) {
  510. return cameraLight.getHFOVByScreenPrecent(camera.fov, camera.aspect, getRad)
  511. },
  512. //add
  513. getHFOVByScreenPrecent: function(fov, percent, getRad) { //当fov为占比百分百时,percent代表在屏幕上从中心到边缘的占比
  514. let rad = 2 * Math.atan(percent * Math.tan(THREE.Math.degToRad(fov * 2)));
  515. if(getRad)return rad
  516. else return rad * MathLight.DEGREES_PER_RADIAN;
  517. }
  518. };
  519. let texLoader = new THREE.TextureLoader;
  520. let texs = new Map
  521. let common = {
  522. urlHasValue(key, isGetValue) {
  523. let querys = window.location.search.substr(1).split('?')
  524. if (isGetValue) {
  525. for (let i = 0; i < querys.length; i++) {
  526. let keypair = querys[i].split('=')
  527. if (keypair.length === 2 && keypair[0] === key) {
  528. return keypair[1]
  529. }
  530. }
  531. return ''
  532. } else {
  533. //return window.location.search.match("&" + key + "|\\?" + key) != null 有bug
  534. for (let i = 0; i < querys.length; i++) {
  535. let keypair = querys[i].split('=')
  536. if(keypair[0] == key){
  537. return true
  538. }
  539. }
  540. return false
  541. }
  542. },
  543. dataURLtoBlob(dataurl) {//将base64转换blob
  544. var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
  545. bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  546. while (n--) {
  547. u8arr[n] = bstr.charCodeAt(n);
  548. }
  549. return new Blob([u8arr], { type: mime });
  550. },
  551. loadTexture(src,done){
  552. let o = texs.get(src)
  553. if(o){
  554. if(o.tex.image) done && done(o.tex)//加载完毕
  555. else{
  556. o.callbacks.push(done)//等待加载
  557. }
  558. return
  559. }
  560. let callbacks = []
  561. let tex = texLoader.load(src,(tex)=>{
  562. callbacks.forEach(done=>done(tex))
  563. })
  564. done && callbacks.push(done)
  565. texs.set(src,{tex,callbacks})
  566. return tex
  567. }
  568. }