NavigationCube.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. import {ViewerBase} from "../custom/viewer/viewerBase.js"
  2. import * as THREE from "../../libs/three.js/build/three.module.js";
  3. import Viewport from "../custom/viewer/Viewport.js"
  4. import {ExtendView} from "./ExtendView.js"
  5. import {LineDraw/* , MeshDraw */} from "../custom/utils/DrawUtil.js";
  6. import {InputHandler} from "../navigation/InputHandlerNew.js";
  7. import {CameraMode } from "../defines.js"
  8. //import {FirstPersonControls} from '../navigation/FirstPersonControlsNew.js'
  9. import {OrbitControls} from "../navigation/OrbitControlsNew.js";
  10. const Colors = {
  11. black : '#161A1A',
  12. blue: '#3290ff',
  13. gray: '#f6f6f6' ,
  14. grayDeep:'#f3f3f3',
  15. white:'#ffffff'
  16. }
  17. let navCubeViewer
  18. class base{
  19. constructor(){
  20. this.faceDefaultColor = Colors.gray//14936556,
  21. /* this.wireframeDefaultColor = 13421772,
  22. this.faceHighlightColor = 12255212,
  23. this.wireframeHighlightColor = 3330982 */
  24. }
  25. createMesh(e) {
  26. for (var t = new THREE.BufferGeometry, i = e.length - 2, n = new Uint32Array(3 * i), o = 0, s = 1; s <= i; s++)
  27. n[o++] = 0,
  28. n[o++] = s,
  29. n[o++] = s + 1;
  30. var r = new THREE.MeshBasicMaterial({
  31. color: this.faceDefaultColor,
  32. side: THREE.DoubleSide,
  33. })
  34. , a = new Float32Array(3 * e.length);
  35. t.setAttribute("position", new THREE.BufferAttribute(a,3).copyVector3sArray(e)),
  36. t.setIndex(new THREE.BufferAttribute(n,1));
  37. var l = new THREE.Mesh(t,r);
  38. return l.componentId = this.componentId,
  39. l
  40. }
  41. createWireframe(e ) {
  42. let line = LineDraw.createFatLine(e,{
  43. color: Colors.grayDeep ,
  44. lineWidth : 2,
  45. viewer: navCubeViewer,
  46. depthTest:true, depthWrite:true,
  47. transparent:true
  48. });
  49. line.renderOrder = 3;
  50. return line
  51. }
  52. getMesh() {
  53. return this.mesh
  54. }
  55. getWireframe() {
  56. return this.wireframeMesh
  57. }
  58. transparent(e) {
  59. e.material && (e.material.transparent = !0,
  60. e.material.opacity = 0)
  61. }
  62. opaque(e) {
  63. e.material && (e.material.transparent = !1,
  64. e.material.opacity = 1)
  65. }
  66. getId() {
  67. return this.componentId
  68. }
  69. }
  70. /*
  71. class Edge extends base{
  72. constructor(t, i, n) {
  73. super()
  74. this.highlightWidth = 3,
  75. this.width = 15,
  76. this.vertices = t,
  77. this.indices = i,
  78. this.componentId = n,
  79. this.highlightWireframeMesh = null,
  80. this.testWireframe = null,
  81. this.build()
  82. }
  83. build() {
  84. var e = this.indices[0]
  85. , t = this.indices[1]
  86. , i = this.vertices[e]
  87. , n = this.vertices[t]
  88. , o = i.clone().add(n).multiplyScalar(.5).clone().multiplyScalar(-1)
  89. , s = o.clone().normalize()
  90. , r = []
  91. , a = n.clone().sub(i).normalize()
  92. , l = i.clone().add(a.clone().multiplyScalar(20))
  93. , h = i.clone().add(a.clone().multiplyScalar(80))
  94. , c = [];
  95. if (0 !== o.x) {
  96. var d = o.x > 0 ? this.width : -this.width;
  97. c.push((new THREE.Vector3).setX(d).add(s))
  98. }
  99. if (0 !== o.y) {
  100. var u = o.y > 0 ? this.width : -this.width;
  101. c.push((new THREE.Vector3).setY(u).add(s))
  102. }
  103. if (0 !== o.z) {
  104. var g = o.z > 0 ? this.width : -this.width;
  105. c.push((new THREE.Vector3).setZ(g).add(s))
  106. }
  107. 2 === c.length && (r.push(l.clone().add(s)),
  108. r.push(l.clone().add(c[0])),
  109. r.push(h.clone().add(c[0])),
  110. r.push(h.clone().add(s)),
  111. r.push(h.clone().add(c[1])),
  112. r.push(l.clone().add(c[1]))),
  113. this.mesh = this.createMesh(r)
  114. this.transparent(this.mesh)
  115. //this.wireframeMesh = this.createWireframe([l, h]),
  116. //this.highlightWireframeMesh = this.createHighlightWireframe([l.sub(s), h.sub(s)])
  117. }
  118. createHighlightWireframe(e) {
  119. for (var t = [], i = 0; i < e.length; i++) {
  120. var n = e[i];
  121. t.push(n.x, n.y, n.z)
  122. }
  123. var o = new THREE.LineGeometry;
  124. o.setPositions(t);
  125. var s = new THREE.LineMaterial({
  126. color: this.wireframeHighlightColor,
  127. linewidth: this.highlightWidth,
  128. dashed: !1
  129. });
  130. s.resolution.set(160, 160);
  131. var r = new THREE.Line2(o,s);
  132. return r.computeLineDistances(),
  133. r.scale.set(1, 1, 1),
  134. r.visible = !1,
  135. r.renderOrder = 100,
  136. r
  137. }
  138. getTestWireframe() {
  139. return this.testWireframe
  140. }
  141. getHighlightWireframeMesh() {
  142. return this.highlightWireframeMesh
  143. }
  144. highlight() {
  145. this.highlightWireframeMesh.visible = !0,
  146. this.highlightWireframeMesh.renderOrder = 100
  147. }
  148. cancelHighlight() {
  149. this.highlightWireframeMesh.visible = !1
  150. }
  151. }
  152. */
  153. class Corner extends base{
  154. constructor(t, i) {
  155. super()
  156. this.length = 20,
  157. this.vertex = t,
  158. this.cornerFace = null,
  159. this.cornerWireframe = null,
  160. this.componentId = i,
  161. this.cornerVertices = null,
  162. this.build()
  163. }
  164. build() {
  165. var e = []
  166. , t = this.vertex.clone()
  167. , i = t.clone().multiplyScalar(-1);
  168. e.push(t);
  169. var n = this.vertex.clone()
  170. , o = i.x > 0 ? this.length : -this.length;
  171. n.x += o,
  172. e.push(n);
  173. var s = this.vertex.clone()
  174. , r = i.y > 0 ? this.length : -this.length;
  175. s.y += r,
  176. e.push(s);
  177. var a = this.vertex.clone()
  178. , l = i.z > 0 ? this.length : -this.length;
  179. a.z += l,
  180. e.push(a),
  181. this.cornerVertices = e
  182. this.mesh = this.createMesh([n, s, a])
  183. /* this.wireframeMesh = this.createWireframe([n, s, a, n], 2),
  184. this.buildCornerFace()
  185. this.buildCornerWireframe() */
  186. }
  187. /* highlight() {
  188. this.wireframeMesh.material.color.setHex(this.wireframeHighlightColor),
  189. this.wireframeMesh.renderOrder = 100,
  190. this.mesh.material.color.setHex(this.faceHighlightColor),
  191. this.cornerFace.material.color.setHex(this.faceHighlightColor),
  192. this.cornerFace.material.transparent = !0,
  193. this.cornerFace.material.opacity = .5,
  194. this.cornerWireframe.material.color.setHex(this.wireframeHighlightColor),
  195. this.cornerWireframe.visible = !0
  196. }
  197. cancelHighlight() {
  198. this.wireframeMesh.material.color.setHex(this.wireframeDefaultColor),
  199. this.wireframeMesh.renderOrder = 0,
  200. this.mesh.material.color.setHex(this.faceDefaultColor),
  201. this.transparent(this.cornerFace),
  202. this.cornerWireframe.visible = !1
  203. }
  204. buildCornerFace() {
  205. if (!this.cornerFace) {
  206. var e = this.cornerVertices;
  207. e.push(e[1])
  208. this.cornerFace = this.createMesh(e)
  209. this.transparent(this.cornerFace)
  210. }
  211. }
  212. getCornerFace() {
  213. return this.cornerFace
  214. }
  215. getCornerWireframe() {
  216. return this.cornerWireframe
  217. }
  218. buildCornerWireframe() {
  219. if (!this.cornerWireframe) {
  220. for (var e = [], t = 1; t < this.cornerVertices.length; t++) {
  221. var i = this.cornerVertices[0]
  222. , n = this.cornerVertices[t];
  223. e.push(i, n)
  224. }
  225. this.cornerWireframe = this.createWireframe(e),
  226. this.cornerWireframe.visible = !1
  227. }
  228. }
  229. */
  230. }
  231. class Face extends base{
  232. constructor(t, i, n, o){
  233. super()
  234. this.length = 60
  235. this.vertices = t,
  236. this.indices = i,
  237. this.componentId = n,
  238. this.vertexUvs = null,
  239. this.texture = o,
  240. this.highlightMesh = null,
  241. this.wireframeMesh = null,
  242. this.vertexUvs = [],
  243. this.vertexUvs.push(new THREE.Vector2(0,.2)),
  244. this.vertexUvs.push(new THREE.Vector2(0,.8)),
  245. this.vertexUvs.push(new THREE.Vector2(.2,1)),
  246. this.vertexUvs.push(new THREE.Vector2(.8,1)),
  247. this.vertexUvs.push(new THREE.Vector2(1,.8)),
  248. this.vertexUvs.push(new THREE.Vector2(1,.2)),
  249. this.vertexUvs.push(new THREE.Vector2(.8,0)),
  250. this.vertexUvs.push(new THREE.Vector2(.2,0)),
  251. this.build()
  252. }
  253. build() {
  254. for (var e = [], t = null, i = null, n = 0, o = this.indices.length; n < o; n++) {
  255. var s = this.indices[n]
  256. , r = this.indices[n + 1];
  257. t = this.vertices[s],
  258. i = this.vertices[r],
  259. n === o - 1 && (i = this.vertices[this.indices[0]]);
  260. var a = i.clone().sub(t).normalize()
  261. , l = t.clone().add(i).multiplyScalar(.5);
  262. e.push(l.clone().sub(a.clone().multiplyScalar(this.length / 2))),
  263. e.push(l.clone().add(a.clone().multiplyScalar(this.length / 2)))
  264. }
  265. this.createTexturedMesh(e);
  266. for (var h = new THREE.Box3, c = 0; c < this.indices.length; c++) {
  267. var d = this.indices[c];
  268. h.expandByPoint(this.vertices[d])
  269. }
  270. for (var u = h.getCenter(new THREE.Vector3).normalize(), g = [], p = 0; p < e.length; p++) {
  271. var m = e[p];
  272. g.push(m.clone().add(u))
  273. }
  274. /* this.highlightMesh = this.createMesh(g)
  275. this.highlightMesh.visible = !1
  276. this.highlightMesh.isHighlightMesh = !0 */
  277. g.push(g[0])
  278. this.wireframeMesh = this.createWireframe(g, 1)
  279. }
  280. /* highlight() {
  281. this.highlightMesh.visible = !0
  282. this.highlightMesh.material.color.setHex(this.faceHighlightColor)
  283. this.highlightMesh.material.transparent = !0
  284. this.highlightMesh.material.opacity = .5
  285. //this.wireframeMesh.material.color.setHex(this.wireframeHighlightColor)
  286. }
  287. cancelHighlight() {
  288. this.highlightMesh.visible = !1
  289. //this.wireframeMesh.material.color.setHex(this.wireframeDefaultColor)
  290. } */
  291. createTexturedMesh(e) {
  292. for (var t = e.length - 2, i = new Uint32Array(3 * t), n = 0, o = 1; o <= t; o++)
  293. i[n++] = 0,
  294. i[n++] = o,
  295. i[n++] = o + 1;
  296. var s = new THREE.BufferGeometry
  297. , r = new Float32Array(3 * e.length)
  298. , a = new Float32Array(2 * this.vertexUvs.length);
  299. s.setAttribute("position", new THREE.BufferAttribute(r,3).copyVector3sArray(e)),
  300. s.setAttribute("uv", new THREE.BufferAttribute(a,2).copyVector2sArray(this.vertexUvs)),
  301. s.setIndex(new THREE.BufferAttribute(i,1));
  302. var l = new THREE.ShaderMaterial({
  303. side: THREE.DoubleSide,
  304. transparent: !1,
  305. uniforms:{
  306. faceColor: {type:'v3', value: new THREE.Color(Colors.white) } ,
  307. textColor: {type:'v3', value: new THREE.Color(Colors.black) } ,
  308. map: {type: 't', value: this.texture },
  309. },
  310. vertexShader:`
  311. varying vec2 vUv;
  312. void main() {
  313. vUv = uv;
  314. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  315. }`,
  316. fragmentShader:`
  317. varying vec2 vUv;
  318. uniform vec3 faceColor;
  319. uniform vec3 textColor;
  320. uniform sampler2D map;
  321. void main() {
  322. //从图上实测
  323. const float mapFaceColorR = 0.85; //0.8862745098039215 (取色)
  324. const float mapTextColotR = 0.66; //0.6431372549019608 (取色)//越高锯齿越强,越低越模糊颜色越灰
  325. vec4 texColor = texture2D(map, vUv);
  326. if(texColor.r > mapFaceColorR){
  327. gl_FragColor = vec4(faceColor, texColor.a);
  328. }else if(texColor.r<mapTextColotR){
  329. gl_FragColor = vec4(textColor, texColor.a);
  330. }else{//抗锯齿 过渡
  331. float faceRatio = (texColor.r - mapTextColotR) / (mapFaceColorR - mapTextColotR);
  332. gl_FragColor = vec4( mix(textColor, faceColor, faceRatio), texColor.a);
  333. }
  334. }
  335. `
  336. });
  337. this.mesh = new THREE.Mesh(s,l),
  338. this.mesh.componentId = this.componentId
  339. }
  340. /* getHighlightMesh() {
  341. return this.highlightMesh
  342. }
  343. buildVertexUvs(e) {
  344. var t = []
  345. , i = (new THREE.Box3).setFromPoints(e)
  346. , n = i.min
  347. , o = new THREE.Vector2;
  348. i.getSize(o);
  349. for (var s = 0 == o.x ? "x" : 0 == o.y ? "y" : "z", r = 0; r < e.length; r++) {
  350. var a = e[r]
  351. , l = (o.x + o.y + o.z) / 2
  352. , h = a.clone().sub(n).multiplyScalar(1 / l)
  353. , c = new THREE.Vector2(h.x,h.y);
  354. "x" == s ? c = new THREE.Vector2(h.y,h.z) : "y" == s && (c = new THREE.Vector2(h.x,h.z)),
  355. t.push(c)
  356. }
  357. return t
  358. } */
  359. }
  360. class NavigationCube{
  361. constructor(scene, length){
  362. this.scene = scene
  363. this.length = length
  364. this.initialize()
  365. /*this.callback = t
  366. this.buildEdges() */
  367. this.buildCorners()
  368. this.buildFaces()
  369. }
  370. initialize(){
  371. this.enumViewMode = {
  372. "2673": "Top", //数字是面的faceIndex组合
  373. "4015": "Bottom",
  374. "0231": "Front",
  375. "5764": "Back",
  376. "1375": "Right",
  377. "4620": "Left",
  378. /* 3: "RoofSouthEast",
  379. 2: "RoofSouthWest",
  380. 7: "RoofNorthEast",
  381. 6: "RoofNorthWest",
  382. 1: "BottomSouthEast",
  383. 0: "BottomSouthWest",
  384. 4: "BottomNorthWest",
  385. 5: "BottomNorthEast",
  386. 32: "RoofFront",
  387. 76: "RoofBack",
  388. 37: "RoofRight",
  389. 26: "RoofLeft",
  390. "01": "BottomFront",
  391. 45: "BottomBack",
  392. 15: "BottomRight",
  393. "04": "BottomLeft",
  394. 13: "SouthEast",
  395. 20: "SouthWest",
  396. 57: "NorthEast",
  397. 64: "NorthWest" */
  398. }
  399. this.vertices = [],
  400. this.vertexIds = [],
  401. this.edgeIds = [],
  402. this.edgeIndices = [],
  403. this.faceIds = [],
  404. this.faceIndices = [],
  405. this.componentList = []
  406. var e = this.length;
  407. //立方体八个点
  408. this.vertices.push(new THREE.Vector3(-e / 2,-e / 2,e / 2)),
  409. this.vertices.push(new THREE.Vector3(e / 2,-e / 2,e / 2)),
  410. this.vertices.push(new THREE.Vector3(-e / 2,e / 2,e / 2)),
  411. this.vertices.push(new THREE.Vector3(e / 2,e / 2,e / 2)),
  412. this.vertices.push(new THREE.Vector3(-e / 2,-e / 2,-e / 2)),
  413. this.vertices.push(new THREE.Vector3(e / 2,-e / 2,-e / 2)),
  414. this.vertices.push(new THREE.Vector3(-e / 2,e / 2,-e / 2)),
  415. this.vertices.push(new THREE.Vector3(e / 2,e / 2,-e / 2));
  416. for (var t = 0; t < 8; t++)
  417. this.vertexIds.push(t + "");
  418. //12条边
  419. /* this.edgeIndices.push([0, 1], [1, 3], [3, 2], [2, 0]),
  420. this.edgeIndices.push([0, 4], [1, 5], [2, 6], [3, 7]),
  421. this.edgeIndices.push([4, 5], [5, 7], [7, 6], [6, 4]);
  422. for (t = 0; t < 12; t++) {
  423. var i = this.edgeIndices[t];
  424. this.edgeIds.push(i[0] + "" + i[1])
  425. } */
  426. //6个面,每个面2个三角形
  427. this.faceIndices.push([0, 2, 3, 1]),
  428. this.faceIndices.push([4, 0, 1, 5]),
  429. this.faceIndices.push([4, 6, 2, 0]),
  430. this.faceIndices.push([2, 6, 7, 3]),
  431. this.faceIndices.push([1, 3, 7, 5]),
  432. this.faceIndices.push([5, 7, 6, 4]);
  433. for (t = 0; t < 6; t++) {
  434. var n = this.faceIndices[t];
  435. this.faceIds.push(n[0] + "" + n[1] + n[2] + n[3])
  436. }
  437. }
  438. buildFaces() {
  439. const directions = {
  440. Top : {dir: new THREE.Vector3(0,0,-1)},
  441. Bottom : {dir: new THREE.Vector3(0,0,1)},
  442. Left : {dir: new THREE.Vector3(1,0,0)},
  443. Right : {dir: new THREE.Vector3(-1,0,0)},
  444. Front : {dir: new THREE.Vector3(0,1,0)},
  445. Back : {dir: new THREE.Vector3(0,-1,0)},
  446. }
  447. let view = new ExtendView()
  448. for(let i in directions){
  449. view.direction = directions[i].dir
  450. directions[i].yaw = view.yaw, directions[i].pitch = view.pitch
  451. }
  452. let texturesLoaded = 0
  453. let create = (n)=>{
  454. let name = this.enumViewMode[this.faceIds[n]]
  455. var url = Potree.resourcePath+'/textures/navigation/' + name + ".png"
  456. , r = new THREE.TextureLoader;
  457. r.setCrossOrigin("anonymous");
  458. r.load(url, (tex)=> {
  459. var face = new Face(e,t[n], this.faceIds[n], tex);
  460. this.componentList.push(face)
  461. let faceMesh = face.getMesh()
  462. this.scene.add(faceMesh)
  463. this.scene.add(face.getWireframe()) //每个面是八边形
  464. /* this.scene.add(face.getHighlightMesh()) */
  465. if(6 == ++texturesLoaded){
  466. navCubeViewer.needRender = true
  467. }
  468. //不过平板无hover事件
  469. faceMesh.addEventListener('mouseover', (e)=>{
  470. if(viewer.mainViewport.view.isFlying())return
  471. faceMesh.material.uniforms.faceColor.value.set(Colors.blue)
  472. //console.log('变', name)
  473. navCubeViewer.dispatchEvent('content_changed')
  474. });
  475. faceMesh.addEventListener('mouseleave', (e)=>{
  476. if(viewer.mainViewport.view.isFlying())return
  477. faceMesh.material.uniforms.faceColor.value.set(Colors.white)
  478. //console.log('回', name)
  479. navCubeViewer.dispatchEvent('content_changed')
  480. });
  481. faceMesh.addEventListener('click', (e)=>{
  482. if(viewer.mainViewport.view.isFlying())return
  483. let dir = directions[name]
  484. if(name == 'Top'){
  485. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2) //使基准线在俯视图中水平
  486. let yaw = baseLine ? new THREE.Vector2().subVectors(baseLine.points[0], baseLine.points[1]).angle() : 0
  487. dir = baseLine ? {dir: new THREE.Vector3(0,0,-1),yaw,pitch: -1.5707963267948966} : directions[name]
  488. }
  489. navCubeViewer.switchView('ortho', dir, ()=>{
  490. faceMesh.material.uniforms.faceColor.value.set(Colors.white)
  491. viewer.dispatchEvent({type:'viewChanged', name })
  492. })
  493. faceMesh.material.uniforms.faceColor.value.set(Colors.blue)
  494. });
  495. })
  496. }
  497. for (var e = this.vertices, t = this.faceIndices, s = 0; s < 6; s++){
  498. create(s)
  499. }
  500. }
  501. buildCorners() {
  502. for (var e = this.vertices, t = this.vertexIds, i = 0; i < 8; i++) {
  503. var n = new Corner(e[i],t[i]);
  504. this.componentList.push(n)
  505. this.scene.add(n.getMesh()) //8个三角形
  506. //this.scene.add(n.getWireframe())
  507. //this.scene.add(n.getCornerFace())
  508. //this.scene.add(n.getCornerWireframe())
  509. }
  510. }
  511. /* buildEdges() {
  512. for (var e = this.vertices, t = this.edgeIndices, i = this.edgeIds, n = 0; n < 12; n++) {
  513. var o = new Edge(e,t[n],i[n]);
  514. this.componentList.push(o)
  515. //this.scene.add(o.getMesh())
  516. //this.scene.add(o.getWireframe())
  517. //this.scene.add(o.getHighlightWireframeMesh())
  518. }
  519. } */
  520. getComponent(e) {
  521. for (var t = 0; t < this.componentList.length; t++) {
  522. var i = this.componentList[t];
  523. if (i.getId() == e)
  524. return i
  525. }
  526. return null
  527. }
  528. }
  529. class NavCubeViewer extends ViewerBase{
  530. constructor(domElement, listenViewport){
  531. super(domElement, {name:'navCube', antialias:true/* , preserveDrawingBuffer:true */} )
  532. domElement.style.opacity = 0.9
  533. navCubeViewer = this
  534. this.scene = new THREE.Scene
  535. this.scene.rotation.x = Math.PI/2 //Yup->Zup
  536. this.listenViewport = listenViewport
  537. let w = 200
  538. this.camera = new THREE.OrthographicCamera(-w/2,w/2,w/2,-w/2 , 1, w*4);
  539. this.camera.zoom = (domElement.clientWidth || 300) / w * 1.267//zoom越大视野越小
  540. this.camera.updateProjectionMatrix()
  541. this.view = new ExtendView();
  542. /* this.view.position.set(0,0,0);
  543. this.view.lookAt(0,0,0) */
  544. this.viewports = [new Viewport( this.view, this.camera, {
  545. left:0, bottom:0, width:1, height: 1, name:'navCube'
  546. }) ]
  547. this.cube = new NavigationCube(this.scene, w/2 )
  548. viewer.addEventListener('camera_changed', e => {
  549. if (e.viewport == listenViewport && (/* e.changeInfo.positionChanged || */e.changeInfo.quaternionChanged)) {
  550. this.updateCamera()
  551. }
  552. })
  553. this.controls = new OrbitControls(this, this.viewports[0]);
  554. this.controls.setEnable(true)
  555. this.controls.setScene(true)
  556. this.view.radius = this.cube.length * 3//相机距离
  557. //事件
  558. this.inputHandler = new InputHandler(this, this.scene);
  559. this.inputHandler.name = 'navCube'
  560. //this.inputHandler.addInputListener(this.controls);
  561. this.inputHandler.registerInteractiveScene(this.scene);//interactiveScenes
  562. this.viewports[0].interactiveScenes = this.inputHandler.interactiveScenes;//供viewer的inputHandler使用
  563. viewer.addEventListener('allLoaded',()=>{
  564. let viewportProps = [{
  565. left:0, bottom:0,
  566. width:1, height:1,
  567. name : "MainView",
  568. //axis:["y","z"],
  569. //direction : new THREE.Vector3(1,0,0),
  570. active: true,
  571. //相机位置在x轴负向 右下角屏
  572. viewContainsPoints:[new THREE.Vector3(0,0,0)],
  573. margin:{x:300, y:250} ,
  574. } ]
  575. viewer.splitScreen.splitStart(viewportProps)
  576. viewer.images360.addEventListener('beginChangeMode',(e)=>{
  577. if(e.mode == 'showPanos'){
  578. this.switchView('perspective',{}, ()=>{
  579. Potree.settings.displayMode = viewer.images360.latestRequestMode
  580. })
  581. }
  582. })
  583. //外部传消息,使进入俯视
  584. this.addEventListener('enterTopView',()=>{
  585. let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2) //使基准线在俯视图中水平
  586. let yaw = baseLine ? new THREE.Vector2().subVectors(baseLine.points[0], baseLine.points[1]).angle() : 0
  587. this.switchView('ortho', {dir: new THREE.Vector3(0,0,-1),yaw,pitch: -1.5707963267948966}, ()=>{
  588. viewer.dispatchEvent({type:'viewChanged', name:'Top' })
  589. })
  590. })
  591. this.addEventListener('leaveTopView',()=>{
  592. if(this.lastView){
  593. this.switchView2(this.lastView)
  594. }
  595. })
  596. })
  597. }
  598. render(){
  599. this.renderer.render(this.scene, this.camera)
  600. }
  601. update(delta){
  602. if(this.renderArea.clientWidth <= 0) return //unvisible
  603. this.updateScreenSize()
  604. this.controls.update(delta)
  605. this.view.applyToCamera(this.camera)
  606. let changed = this.cameraChanged()
  607. if(changed || this.needRender){
  608. this.needRender = false
  609. this.render()
  610. this.applyToMainView()
  611. }
  612. }
  613. updateCamera(){
  614. let view = this.listenViewport.view
  615. this.view.yaw = view.yaw
  616. this.view.pitch = view.pitch
  617. var dir = view.direction; //相机朝向
  618. this.view.position.copy(dir.multiplyScalar(this.view.radius).negate()) //相机绕着指南针中心(000)转动
  619. }
  620. applyToMainView(){
  621. let view = this.listenViewport.view
  622. view.rotation = this.view.rotation
  623. }
  624. pushHomeBtn(){
  625. this.switchView('perspective')
  626. }
  627. switchView(type, {yaw, pitch, dir}={}, done){
  628. if(viewer.mainViewport.view.isFlying())return
  629. let view = viewer.mainViewport.view
  630. let oldlastPerspect = this.lastPerspectView
  631. this.lastView = view.clone()
  632. if(viewer.mainViewport.camera.type == 'OrthographicCamera'){
  633. this.lastView.isOrtho = true;
  634. this.lastView.zoom = viewer.mainViewport.camera.zoom
  635. }else{
  636. this.lastPerspectView = this.lastView
  637. }
  638. if(type == 'ortho'){
  639. let startCamera, endCamera
  640. if(viewer.mainViewport.camera != viewer.scene.cameraO){
  641. startCamera = viewer.scene.cameraP
  642. endCamera = viewer.scene.cameraO
  643. viewer.scene.cameraO.position.copy(viewer.mainViewport.camera.position)
  644. viewer.scene.cameraO.quaternion.copy(viewer.mainViewport.camera.quaternion)
  645. viewer.mainViewport.camera = viewer.scene.cameraO //先设置为cameraO, 才能计算top
  646. viewer.setCameraMode(CameraMode.ORTHOGRAPHIC) //updateScreenSize set cameraO.top
  647. this.controls.setEnable(false)
  648. //假设保持到目前中心的视角范围不变
  649. viewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center)
  650. let dis = new THREE.Vector3().subVectors(viewer.mainViewport.shiftTarget, viewer.scene.cameraO.position).length() ; //-nearestPano[0].score
  651. //根据2d->3d的式子逆求zoom
  652. let halfHeight = Math.abs(dis) * Math.tan( THREE.Math.degToRad(viewer.scene.cameraP.fov/2));
  653. viewer.scene.cameraO.zoom = viewer.scene.cameraO.top / halfHeight;
  654. viewer.scene.cameraO.updateProjectionMatrix();
  655. }
  656. //console.log('变成正交')
  657. viewer.focusOnObject(viewer.bound, 'boundingBox', 1000, {
  658. endPitch: pitch, endYaw: yaw , dir, startCamera, endCamera
  659. }).promise.done(()=>{
  660. /* let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2)
  661. baseLine && Potree.Utils.updateVisible(baseLine,'enterOrthoView',true)//基准线仅在正交视图可见
  662. */
  663. done && done()
  664. navCubeViewer.dispatchEvent('content_changed')
  665. })
  666. }else{
  667. if(viewer.mainViewport.camera == viewer.scene.cameraO){
  668. return this.switchView2(oldlastPerspect, done)
  669. //viewer.scene.cameraP.position.copy(viewer.mainViewport.camera.position)
  670. //viewer.scene.cameraP.quaternion.copy(viewer.mainViewport.camera.quaternion)
  671. viewer.mainViewport.camera = viewer.scene.cameraP
  672. viewer.setCameraMode(CameraMode.PERSPECTIVE)
  673. //假设保持到目前中心的视角范围不变
  674. viewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center)
  675. let halfHeight = viewer.scene.cameraO.top/viewer.scene.cameraO.zoom
  676. let dis = halfHeight / Math.tan( THREE.Math.degToRad(viewer.scene.cameraP.fov/2))
  677. let position = new THREE.Vector3().copy(viewer.mainViewport.shiftTarget).sub(view.direction.clone().multiplyScalar(dis));
  678. //view.position.copy(viewer.mainViewport.shiftTarget).sub(view.direction.clone().multiplyScalar(dis));
  679. this.controls.setEnable(true)
  680. //viewer.dispatchEvent('leaveTopView')
  681. console.log('变回透视')
  682. view.tranCamera(viewer.mainViewport, { position ,
  683. callback:()=>{
  684. done && done()
  685. viewer.dispatchEvent({type:'viewChanged', name:'perspective' })
  686. }, startCamera:viewer.scene.cameraO, endCamera:viewer.scene.cameraP, midCamera:viewer.scene.cameraBasic
  687. }, 500)
  688. }
  689. }
  690. }
  691. switchView2(viewInfo, done){ //直接输入view改变
  692. let view = viewer.mainViewport.view
  693. let startCamera, endCamera
  694. if(viewInfo.isOrtho){
  695. if(viewer.mainViewport.camera != viewer.scene.cameraO){
  696. startCamera = viewer.scene.cameraP
  697. endCamera = viewer.scene.cameraO
  698. }else{
  699. view.moveOrthoCamera(viewer.mainViewport, {endPosition:viewInfo.position,
  700. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw , zoom: viewInfo.zoom,
  701. callback:()=>{
  702. done && done()
  703. },
  704. }, 800)
  705. }
  706. }else{
  707. if(viewer.mainViewport.camera == viewer.scene.cameraO){
  708. startCamera = viewer.scene.cameraO
  709. endCamera = viewer.scene.cameraP
  710. /* let baseLine = viewer.scene.measurements.find(e=>e.isBaseLine && e.points.length == 2)
  711. baseLine && Potree.Utils.updateVisible(baseLine,'enterOrthoView',false) //基准线仅在正交视图可见
  712. */
  713. }else{
  714. console.log('switchView2', 'not ortho')
  715. view.setView({ position:viewInfo.position,
  716. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw ,
  717. startCamera, endCamera,
  718. callback:()=>{
  719. },
  720. }, 800)
  721. }
  722. }
  723. if(startCamera){
  724. if(endCamera == viewer.scene.cameraO){
  725. this.controls.setEnable(false)
  726. }
  727. this.controls.setEnable(false)
  728. view.tranCamera(viewer.mainViewport, { position:viewInfo.position,
  729. endPitch: viewInfo.pitch, endYaw: viewInfo.yaw ,
  730. startCamera, endCamera, midCamera:viewer.scene.cameraBasic ,
  731. callback:()=>{
  732. if(endCamera != viewer.scene.cameraO){
  733. this.controls.setEnable(true)
  734. viewer.dispatchEvent({type:'viewChanged', name:'perspective' })
  735. }else{
  736. viewer.dispatchEvent({type:'viewChanged', name:'perspective' })
  737. }
  738. done && done()
  739. },
  740. }, 800)
  741. }
  742. }
  743. rotateSideCamera(angle){
  744. viewer.splitScreen.rotateSideCamera(viewer.mainViewport,angle)
  745. }
  746. }
  747. export {NavCubeViewer}