TransformationToolNew.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import {Utils} from "../utils.js";
  3. import {LineDraw/* , MeshDraw */} from "../custom/utils/DrawUtil.js";
  4. import History from "../custom/utils/History.js"
  5. //问题:如何转换到世界坐标?(缩放方向有bug。)
  6. //add-------------------------------------
  7. const OpaWhenNotSelect = 0.6
  8. const ScaleRatio = 3
  9. const OutlineColor = 0x666666
  10. //----------------------------------------
  11. const hideFocusHandles = true//add
  12. export class TransformationTool extends THREE.EventDispatcher{
  13. constructor(viewer ) {
  14. super()
  15. this.viewer = viewer;
  16. this.modesEnabled = {}//add
  17. this.style = 'singleMode' //建mesh时按照singleModes建的
  18. this.scene = new THREE.Scene();
  19. this.selection = [];
  20. this.pivot = new THREE.Vector3();
  21. this.dragging = false;
  22. this.showPickVolumes = false;
  23. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  24. this.viewer.inputHandler.addEventListener('selection_changed', (e) => {
  25. /* for(let selected of this.selection){ //若不删除,应该会穿过选中的物体选到别的而不是取消选择
  26. this.viewer.inputHandler.blacklist.delete(selected);
  27. } */
  28. this.selection = e.selection;
  29. /* for(let selected of this.selection){
  30. this.viewer.inputHandler.blacklist.add(selected);
  31. } */
  32. });
  33. this.viewer.addEventListener('global_touchstart',(e)=>{ //add
  34. this.update()
  35. })
  36. this.viewer.addEventListener('global_mousemove',(e)=>{ //add
  37. this.onPointerMove()
  38. })
  39. let red = Potree.config.axis.x.color
  40. let green = Potree.config.axis.y.color
  41. let blue = Potree.config.axis.z.color
  42. let white = Potree.config.axis.xyz.color
  43. this.activeHandle = null;
  44. this.scaleHandles = {
  45. "scale.x+": {name: "scale.x+", node: new THREE.Object3D(), color: red, alignment: [+1, +0, +0]},
  46. "scale.x-": {name: "scale.x-", node: new THREE.Object3D(), color: red, alignment: [-1, +0, +0]},
  47. "scale.y+": {name: "scale.y+", node: new THREE.Object3D(), color: green, alignment: [+0, +1, +0]},
  48. "scale.y-": {name: "scale.y-", node: new THREE.Object3D(), color: green, alignment: [+0, -1, +0]},
  49. "scale.z+": {name: "scale.z+", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, +1]},
  50. "scale.z-": {name: "scale.z-", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, -1]},
  51. "lines": {name:'lines', node: new THREE.Object3D(), dontScale:true }//add
  52. };
  53. this.focusHandles = {
  54. "focus.x+": {name: "focus.x+", node: new THREE.Object3D(), color: red, alignment: [+1, +0, +0]},
  55. "focus.x-": {name: "focus.x-", node: new THREE.Object3D(), color: red, alignment: [-1, +0, +0]},
  56. "focus.y+": {name: "focus.y+", node: new THREE.Object3D(), color: green, alignment: [+0, +1, +0]},
  57. "focus.y-": {name: "focus.y-", node: new THREE.Object3D(), color: green, alignment: [+0, -1, +0]},
  58. "focus.z+": {name: "focus.z+", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, +1]},
  59. "focus.z-": {name: "focus.z-", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, -1]},
  60. };
  61. this.translationHandles = {
  62. "translation.x": {name: "translation.x", node: new THREE.Object3D(), color: red, alignment: [1, 0, 0]},
  63. "translation.y": {name: "translation.y", node: new THREE.Object3D(), color: green, alignment: [0, 1, 0]},
  64. "translation.z": {name: "translation.z", node: new THREE.Object3D(), color: blue, alignment: [0, 0, 1]},
  65. //add
  66. 'translation.xyz':{name: "translation.xyz", node: new THREE.Object3D(),color: white, alignment: [0, 0, 0], alignment2: [1, 1, 1]},
  67. 'translation.plane.xy':{name: "translation.plane.xy", node: new THREE.Object3D(),color: blue,alignment: [0, 0, 1], alignment2: [1, 1, 0]},
  68. 'translation.plane.yz':{name: "translation.plane.yz", node: new THREE.Object3D(),color: red, alignment: [1, 0, 0], alignment2: [0, 1, 1]},
  69. 'translation.plane.xz':{name: "translation.plane.xz", node: new THREE.Object3D(),color: green, alignment: [0, 1, 0], alignment2: [1, 0, 1]},
  70. };
  71. this.rotationHandles = {
  72. "rotation.x": {name: "rotation.x", node: new THREE.Object3D(), color: red, alignment: [1, 0, 0]},
  73. "rotation.y": {name: "rotation.y", node: new THREE.Object3D(), color: green, alignment: [0, 1, 0]},
  74. "rotation.z": {name: "rotation.z", node: new THREE.Object3D(), color: blue, alignment: [0, 0, 1]},
  75. };
  76. this.handles = Object.assign({}, this.scaleHandles, hideFocusHandles?{}:this.focusHandles, this.translationHandles, this.rotationHandles);
  77. this.pickVolumes = [];
  78. this.initializeScaleHandles();
  79. this.initializeFocusHandles();
  80. this.initializeTranslationHandles();
  81. this.initializeRotationHandles();
  82. let boxFrameGeometry = new THREE.Geometry();
  83. {
  84. // bottom
  85. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
  86. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
  87. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
  88. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
  89. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
  90. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
  91. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
  92. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
  93. // top
  94. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
  95. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
  96. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
  97. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
  98. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
  99. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
  100. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
  101. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
  102. // sides
  103. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
  104. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
  105. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
  106. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
  107. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
  108. boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
  109. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
  110. boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
  111. }
  112. this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0xffff00}));
  113. this.scene.add(this.frame);
  114. //------------------add-----------------------
  115. this.setModeEnable(['scale','translation','rotation'])
  116. Potree.Utils.setObjectLayers(this.scene, 'transformationTool' )
  117. this.scene.traverse(e=>{
  118. e.pickDontCheckDis = true; //pick时不需要识别是否在点云之上
  119. })
  120. {
  121. let exist = (object)=>{//是否没被删除(暂时不考虑换了parent)
  122. while(object.parent){
  123. object = object.parent
  124. }
  125. if(object instanceof THREE.Scene){
  126. return true
  127. }
  128. }
  129. this.history = new History({ //也可以写到全局,但需要加个判断物品是否存在的函数
  130. applyData: (data)=>{
  131. if(exist(data.object)){//viewer.scene.volumes.includes(data.box) //或许还要识别是否matrixAuto
  132. data.matrix.decompose( data.object.position, data.object.quaternion, data.object.scale );
  133. viewer.dispatchEvent('content_changed')
  134. return true
  135. }
  136. } ,
  137. getData:(data)=>{
  138. return data
  139. }
  140. })
  141. this.addEventListener('transformed', (e)=>{
  142. let object = viewer.transformationTool.selection[0]
  143. this.history.beforeChange({object, matrix:e.matrixBefore.clone()} )
  144. this.viewer.dispatchEvent('content_changed')
  145. })
  146. this.addEventListener('stopDrag', (e)=>{
  147. let object = viewer.transformationTool.selection[0]
  148. object && this.history.afterChange({object, matrix:object.matrix.clone()} )
  149. })
  150. /* viewer.inputHandler.addEventListener('keydown', (e)=>{
  151. if(e.keyCode == 90 && e.event.ctrlKey){//Z
  152. this.history.undo()
  153. }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
  154. this.history.redo()
  155. }
  156. }) */
  157. }
  158. }
  159. setModeEnable(enableModes=[] ){//xzw add
  160. let length=0;
  161. ['translation','scale','rotation'].forEach(mode=>{
  162. let handels = this[mode + 'Handles']
  163. let enable = enableModes.includes(mode)
  164. for(let o in handels){
  165. Potree.Utils.updateVisible(handels[o].node,'modeForce', !!enable)
  166. }
  167. this.modesEnabled[mode] = !!enable
  168. enable && length++
  169. })
  170. if(this.style == 'singleMode' && length > 1){
  171. this.changeStyle('mixedModes')
  172. }else if(this.style == 'mixedModes' && length == 1){
  173. this.changeStyle('singleMode')
  174. }
  175. }
  176. changeStyle(style){// 切换单个mode & 多个mode混合 风格(因多个混合比较拥挤,需要做调整)
  177. ['x','y','z'].forEach(axis=>{
  178. this.translationHandles['translation.'+axis].node.children.forEach(mesh=>{
  179. if(mesh.name.includes('arrow')){
  180. Potree.Utils.updateVisible(mesh, 'modeStyle', style == 'singleMode')
  181. }else if(mesh.name.includes('handle')){
  182. mesh.material.lineWidth = style == 'singleMode' ? 5 : 8
  183. }
  184. })
  185. });
  186. ['xy','yz','xz'].forEach(axis=>{
  187. let handle = this.translationHandles['translation.plane.'+axis]
  188. let s = style == 'singleMode' ? 15 : 12
  189. handle.node.children[0].scale.set(s,s,s);
  190. handle.node.children[0].position.fromArray(handle.alignment2).multiplyScalar(s*1.5)
  191. })
  192. Potree.Utils.updateVisible(this.scaleHandles['lines'].node, 'modeStyle', style == 'singleMode')
  193. this.style = style
  194. }
  195. initializeTranslationHandles(){//大改
  196. let boxGeometry = new THREE.BoxGeometry(1, 1, 1);
  197. let length = 100 , arrowRadius = 4, arrowHeight = 10
  198. let arrowGeometry = new THREE.CylinderBufferGeometry( 0, arrowRadius, arrowHeight, 12, 1, false );//add 箭头朝(0,1,0)
  199. let arrowInitialQua = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI/2 )//先将qua旋转到朝向0,0,-1, 因为一般quaternion不设置时默认表示朝向0,0,-1,
  200. let octahedronGeometry = new THREE.OctahedronBufferGeometry( 5, 0 );
  201. let planeGeometry = new THREE.PlaneBufferGeometry( 1, 1 )
  202. for(let handleName of Object.keys(this.translationHandles)){
  203. let handle = this.handles[handleName];
  204. let node = handle.node;
  205. this.scene.add(node);
  206. node.name = handleName//add
  207. let alignment = new THREE.Vector3(...handle.alignment)
  208. let geometry , mesh, pickVolume, meshScale, pickScale, rotation, position, lookAtPoint, hasPick = true, meshPickable = false, renderOrder
  209. let matProp = {
  210. color: handle.color,
  211. opacity: OpaWhenNotSelect,
  212. transparent: true,
  213. side: handleName.includes('plane') ? THREE.DoubleSide : THREE.FrontSide
  214. }
  215. let material = new THREE.MeshBasicMaterial(matProp)
  216. let pickMaterial = new THREE.MeshNormalMaterial({
  217. opacity: 0.2,
  218. transparent: true,
  219. visible: this.showPickVolumes
  220. });
  221. if(handleName.includes('xyz') ){
  222. geometry = octahedronGeometry
  223. meshPickable = true
  224. renderOrder = 12;
  225. }else if(handleName.includes('plane') ){
  226. geometry = planeGeometry
  227. meshPickable = true
  228. position = new THREE.Vector3(...handle.alignment2)
  229. lookAtPoint = alignment
  230. if(handleName.includes('xy') ) {
  231. }else if(handleName.includes('yz')){
  232. }else if(handleName.includes('xz')){
  233. }
  234. }else{
  235. geometry = boxGeometry
  236. let point = new THREE.Vector3(0,0,length/2)//new THREE.Vector3().copy(alignment).multiplyScalar(length/2)
  237. mesh = LineDraw.createFatLine([point, point.clone().negate()],{lineWidth:5, mat : new LineDraw.createFatLineMat(matProp)})
  238. lookAtPoint = alignment
  239. renderOrder = 10;
  240. pickScale = new THREE.Vector3(4, 4, length+arrowHeight*2) //pickScale = new THREE.Vector3(4, 4, 1.2)
  241. {
  242. let arrow = new THREE.Mesh(arrowGeometry, material)
  243. arrow.name = `${handleName}.arrow`;
  244. arrow.renderOrder = 11;
  245. arrow.position.set( ...handle.alignment).multiplyScalar(length/2+arrowHeight/2)
  246. arrow.lookAt(0,0,0)
  247. node.add(arrow);
  248. let arrow2 = arrow.clone();
  249. arrow2.position.negate()
  250. arrow2.lookAt(0,0,0)
  251. node.add(arrow2);
  252. arrow.quaternion.multiply(arrowInitialQua) //乘上初始旋转
  253. arrow2.quaternion.multiply(arrowInitialQua)
  254. }
  255. }
  256. mesh || (mesh = new THREE.Mesh(geometry,material))
  257. mesh.name = `${handleName}.handle`;
  258. node.add(mesh);
  259. renderOrder && (mesh.renderOrder = renderOrder)
  260. meshScale && mesh.scale.copy(meshScale)
  261. rotation && mesh.rotation.copy(rotation)
  262. lookAtPoint && mesh.lookAt(lookAtPoint)
  263. position && mesh.position.copy(position)
  264. if(!meshPickable && hasPick){
  265. pickVolume = new THREE.Mesh(geometry, pickMaterial);
  266. pickScale && pickVolume.scale.copy(pickScale)
  267. }else if(hasPick && meshPickable){
  268. pickVolume = mesh
  269. }
  270. if(pickVolume){
  271. if(mesh != pickVolume){
  272. mesh.add(pickVolume);
  273. pickVolume.name = `${handleName}.pick_volume`;
  274. }else{
  275. pickVolume.name += ' & pick_volume'
  276. }
  277. pickVolume.handle = handleName;
  278. this.pickVolumes.push(pickVolume);
  279. }
  280. node.setOpacity = (target) => {
  281. if(handleName.includes('plane')){
  282. let more = 1.5; //减掉更多,使min更低,max还是1
  283. target = 1 - (1-target)*more
  284. }
  285. let opacity = {x: material.opacity};
  286. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  287. t.onUpdate(() => {
  288. mesh.visible = opacity.x > 0;
  289. pickVolume && (pickVolume.visible = opacity.x > 0);
  290. material.opacity = opacity.x;
  291. mesh.material.opacity = opacity.x;
  292. //outlineMaterial.opacity = opacity.x;
  293. pickMaterial.opacity = opacity.x * 0.5;
  294. });
  295. t.start();
  296. };
  297. pickVolume.addEventListener("drag", (e) => {this.dragTranslationHandle(e)});
  298. pickVolume.addEventListener("drop", (e) => {this.dropTranslationHandle(e)});
  299. }
  300. }
  301. initializeScaleHandles(){
  302. let sgSphere = new THREE.SphereGeometry(1, 32, 32);
  303. let sgLowPolySphere = new THREE.SphereGeometry(1, 16, 16);
  304. for(let handleName of Object.keys(this.scaleHandles)){
  305. let handle = this.scaleHandles[handleName];
  306. let node = handle.node;
  307. node.name = handleName//add
  308. this.scene.add(node);
  309. if(handleName == 'lines'){ //add
  310. ['x','y','z'].forEach(axis=>{
  311. let handle1_ = this.scaleHandles['scale.'+axis+'+']
  312. let handle2_ = this.scaleHandles['scale.'+axis+'-']
  313. let line = LineDraw.createFatLine([
  314. new THREE.Vector3().fromArray(handle1_.alignment).multiplyScalar(0.5),
  315. new THREE.Vector3().fromArray(handle2_.alignment).multiplyScalar(0.5) ],
  316. {color:handle1_.color, lineWidth:4} // , dontAlwaysSeen:true
  317. )
  318. node.add(line)
  319. })
  320. node.setOpacity = (opacity) => {
  321. opacity *= 0.6
  322. node.children.forEach(e=>e.material.opacity = opacity)
  323. };
  324. continue;
  325. }
  326. node.position.set(...handle.alignment).multiplyScalar(0.5);
  327. let material = new THREE.MeshBasicMaterial({
  328. color: handle.color,
  329. side:THREE.DoubleSide,//xzw add
  330. opacity: OpaWhenNotSelect,
  331. transparent: true
  332. });
  333. let outlineMaterial = new THREE.MeshBasicMaterial({
  334. color: OutlineColor,
  335. side: THREE.BackSide,
  336. opacity: OpaWhenNotSelect,
  337. transparent: true});
  338. let pickMaterial = new THREE.MeshNormalMaterial({
  339. opacity: 0.2,
  340. transparent: true,
  341. side:THREE.DoubleSide,//xzw add for orthoCam, 缩小画面时因球体放大导致到相机背面去了而看不到球体正面
  342. visible: this.showPickVolumes});
  343. let sphere = new THREE.Mesh(sgSphere, material);
  344. sphere.scale.set(5, 5, 5 );
  345. sphere.name = `${handleName}.handle`;
  346. node.add(sphere);
  347. sphere.renderOrder = 10
  348. /* let outline = new THREE.Mesh(sgSphere, outlineMaterial);
  349. outline.scale.set(1.1, 1.1, 1.1);
  350. outline.name = `${handleName}.outline`;
  351. sphere.add(outline); */
  352. let pickSphere = new THREE.Mesh(sgLowPolySphere, pickMaterial);
  353. pickSphere.name = `${handleName}.pick_volume`;
  354. pickSphere.scale.set(1.5, 1.5, 1.5);
  355. sphere.add(pickSphere);
  356. pickSphere.handle = handleName;
  357. this.pickVolumes.push(pickSphere);
  358. node.setOpacity = (target) => {
  359. let opacity = {x: material.opacity};
  360. let t = new TWEEN.Tween(opacity).to({x: target}, 0); //xzw改 原100毫秒,因为太慢容易选错
  361. t.onUpdate(() => {
  362. sphere.visible = opacity.x > 0;
  363. pickSphere.visible = opacity.x > 0;
  364. material.opacity = opacity.x;
  365. outlineMaterial.opacity = opacity.x;
  366. pickSphere.material.opacity = opacity.x * 0.5;
  367. });
  368. t.start();
  369. };
  370. pickSphere.addEventListener("drag", (e) => this.dragScaleHandle(e));
  371. pickSphere.addEventListener("drop", (e) => this.dropScaleHandle(e));
  372. pickSphere.addEventListener("mouseover", e => {
  373. //node.setOpacity(1);
  374. });
  375. pickSphere.addEventListener("click", e => {
  376. //e.consume();
  377. });
  378. pickSphere.addEventListener("mouseleave", e => {
  379. //node.setOpacity(OpaWhenNotSelect);
  380. });
  381. }
  382. }
  383. initializeRotationHandles(){
  384. let boldAdjust = 2.5;
  385. let torusGeometry = new THREE.TorusGeometry(1.4, boldAdjust * 0.015, 8, 64, Math.PI / 2);
  386. //let outlineGeometry = new THREE.TorusGeometry(1, boldAdjust * 0.018, 8, 64, Math.PI / 2);
  387. let pickGeometry = new THREE.TorusGeometry(1.4, boldAdjust * 0.06, 6, 4, Math.PI / 2);
  388. for(let handleName of Object.keys(this.rotationHandles)){
  389. let handle = this.handles[handleName];
  390. let node = handle.node;
  391. this.scene.add(node);
  392. node.name = handleName//add
  393. let material = new THREE.MeshBasicMaterial({
  394. color: handle.color,
  395. opacity: OpaWhenNotSelect,
  396. transparent: true
  397. });
  398. /* let outlineMaterial = new THREE.MeshBasicMaterial({
  399. color: OutlineColor,
  400. side: THREE.BackSide,
  401. opacity: OpaWhenNotSelect,
  402. transparent: true
  403. }); */
  404. let pickMaterial = new THREE.MeshNormalMaterial({
  405. opacity: 0.2,
  406. transparent: true,
  407. visible: this.showPickVolumes
  408. });
  409. let box = new THREE.Mesh(torusGeometry, material);
  410. box.name = `${handleName}.handle`;
  411. box.scale.set(30, 30, 30);
  412. box.lookAt(new THREE.Vector3(...handle.alignment));
  413. node.add(box);
  414. handle.translateNode = box;
  415. /* let outline = new THREE.Mesh(outlineGeometry, outlineMaterial);
  416. outline.name = `${handleName}.outline`;
  417. outline.scale.set(1, 1, 1);
  418. outline.renderOrder = 0;
  419. box.add(outline);
  420. */
  421. let pickVolume = new THREE.Mesh(pickGeometry, pickMaterial);
  422. pickVolume.name = `${handleName}.pick_volume`;
  423. pickVolume.scale.set(1, 1, 1);
  424. pickVolume.handle = handleName;
  425. box.add(pickVolume);
  426. this.pickVolumes.push(pickVolume);
  427. node.setOpacity = (target) => {
  428. let opacity = {x: material.opacity};
  429. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  430. t.onUpdate(() => {
  431. box.visible = opacity.x > 0;
  432. pickVolume.visible = opacity.x > 0;
  433. material.opacity = opacity.x;
  434. //outlineMaterial.opacity = opacity.x;
  435. pickMaterial.opacity = opacity.x * 0.5;
  436. });
  437. t.start();
  438. };
  439. //pickVolume.addEventListener("mouseover", (e) => {
  440. // //let a = this.viewer.scene.getActiveCamera().getWorldDirection(new THREE.Vector3()).dot(pickVolume.getWorldDirection(new THREE.Vector3()));
  441. // console.log(pickVolume.getWorldDirection(new THREE.Vector3()));
  442. //});
  443. pickVolume.addEventListener("drag", (e) => {this.dragRotationHandle(e)});
  444. pickVolume.addEventListener("drop", (e) => {this.dropRotationHandle(e)});
  445. }
  446. }
  447. initializeFocusHandles(){
  448. if(hideFocusHandles)return//add
  449. //let sgBox = new THREE.BoxGeometry(1, 1, 1);
  450. let sgPlane = new THREE.PlaneGeometry(4, 4, 1, 1);
  451. let sgLowPolySphere = new THREE.SphereGeometry(1, 16, 16);
  452. let texture = new THREE.TextureLoader().load(`${exports.resourcePath}/icons/eye_2.png`);
  453. for(let handleName of Object.keys(this.focusHandles)){
  454. let handle = this.focusHandles[handleName];
  455. let node = handle.node;
  456. this.scene.add(node);
  457. let align = handle.alignment;
  458. node.name = handleName//add
  459. //node.lookAt(new THREE.Vector3().addVectors(node.position, new THREE.Vector3(...align)));
  460. node.lookAt(new THREE.Vector3(...align));
  461. let off = 0.8;
  462. if(align[0] === 1){
  463. node.position.set(1, off, -off).multiplyScalar(0.5);
  464. node.rotation.z = Math.PI / 2;
  465. }else if(align[0] === -1){
  466. node.position.set(-1, -off, -off).multiplyScalar(0.5);
  467. node.rotation.z = Math.PI / 2;
  468. }else if(align[1] === 1){
  469. node.position.set(-off, 1, -off).multiplyScalar(0.5);
  470. node.rotation.set(Math.PI / 2, Math.PI, 0.0);
  471. }else if(align[1] === -1){
  472. node.position.set(off, -1, -off).multiplyScalar(0.5);
  473. node.rotation.set(Math.PI / 2, 0.0, 0.0);
  474. }else if(align[2] === 1){
  475. node.position.set(off, off, 1).multiplyScalar(0.5);
  476. }else if(align[2] === -1){
  477. node.position.set(-off, off, -1).multiplyScalar(0.5);
  478. }
  479. let material = new THREE.MeshBasicMaterial({
  480. color: handle.color,
  481. opacity: 0,
  482. transparent: true,
  483. map: texture
  484. });
  485. //let outlineMaterial = new THREE.MeshBasicMaterial({
  486. // color: 0x000000,
  487. // side: THREE.BackSide,
  488. // opacity: 0,
  489. // transparent: true});
  490. let pickMaterial = new THREE.MeshNormalMaterial({
  491. //opacity: 0,
  492. transparent: true,
  493. visible: this.showPickVolumes});
  494. let box = new THREE.Mesh(sgPlane, material);
  495. box.name = `${handleName}.handle`;
  496. box.scale.set(1.5, 1.5, 1.5);
  497. box.position.set(0, 0, 0);
  498. box.visible = false;
  499. node.add(box);
  500. //handle.focusNode = box;
  501. //let outline = new THREE.Mesh(sgPlane, outlineMaterial);
  502. //outline.scale.set(1.4, 1.4, 1.4);
  503. //outline.name = `${handleName}.outline`;
  504. //box.add(outline);
  505. let pickSphere = new THREE.Mesh(sgLowPolySphere, pickMaterial);
  506. pickSphere.name = `${handleName}.pick_volume`;
  507. pickSphere.scale.set(2, 2, 2);
  508. box.add(pickSphere);
  509. pickSphere.handle = handleName;
  510. this.pickVolumes.push(pickSphere);
  511. node.setOpacity = (target) => {
  512. let opacity = {x: material.opacity};
  513. let t = new TWEEN.Tween(opacity).to({x: target}, 0);
  514. t.onUpdate(() => {
  515. pickSphere.visible = opacity.x > 0;
  516. box.visible = opacity.x > 0;
  517. material.opacity = opacity.x;
  518. //outlineMaterial.opacity = opacity.x;
  519. pickSphere.material.opacity = opacity.x * 0.5;
  520. });
  521. t.start();
  522. };
  523. //pickSphere.addEventListener("drag", e => {});
  524. pickSphere.addEventListener("mouseup", e => {
  525. //e.consume();
  526. });
  527. pickSphere.addEventListener("mousedown", e => {
  528. //e.consume();
  529. });
  530. pickSphere.addEventListener("click", e => {
  531. //e.consume();
  532. let selected = this.selection[0];
  533. let maxScale = Math.max(...selected.scale.toArray());
  534. let minScale = Math.min(...selected.scale.toArray());
  535. let handleLength = Math.abs(selected.scale.dot(new THREE.Vector3(...handle.alignment)));
  536. let alignment = new THREE.Vector3(...handle.alignment).multiplyScalar(2 * maxScale / handleLength);
  537. alignment.applyMatrix4(selected.matrixWorld);
  538. let newCamPos = alignment;
  539. let newCamTarget = selected.getWorldPosition(new THREE.Vector3());
  540. Utils.moveTo(this.viewer.scene, newCamPos, newCamTarget);
  541. });
  542. pickSphere.addEventListener("mouseover", e => {
  543. //box.setOpacity(1);
  544. });
  545. pickSphere.addEventListener("mouseleave", e => {
  546. //box.setOpacity(OpaWhenNotSelect);
  547. });
  548. }
  549. }
  550. dragRotationHandle(e){
  551. let drag = e.drag;
  552. let handle = this.activeHandle;
  553. let camera = this.viewer.mainViewport.camera//this.viewer.scene.getActiveCamera();
  554. if(!handle){
  555. return
  556. };
  557. let localNormal = new THREE.Vector3(...handle.alignment);
  558. let n = new THREE.Vector3();
  559. n.copy(new THREE.Vector4(...localNormal.toArray(), 0).applyMatrix4(handle.node.matrixWorld));
  560. n.normalize();
  561. if (!drag.intersectionStart){
  562. //this.viewer.scene.scene.remove(this.debug);
  563. //this.debug = new THREE.Object3D();
  564. //this.viewer.scene.scene.add(this.debug);
  565. //Utils.debugSphere(this.debug, drag.location, 3, 0xaaaaaa);
  566. //let debugEnd = drag.location.clone().add(n.clone().multiplyScalar(20));
  567. //Utils.debugLine(this.debug, drag.location, debugEnd, 0xff0000);
  568. drag.intersectionStart = drag.location;
  569. drag.objectStart = drag.object.getWorldPosition(new THREE.Vector3());
  570. drag.handle = handle;
  571. let plane = new THREE.Plane().setFromNormalAndCoplanarPoint(n, drag.intersectionStart);
  572. drag.dragPlane = plane;
  573. drag.pivot = drag.intersectionStart;
  574. }else{
  575. handle = drag.handle;
  576. }
  577. if(!drag.dragPlane)return//xzw add 因有时候没有
  578. this.dragging = true;
  579. let pointer = this.viewer.inputHandler.pointer
  580. let domElement = this.viewer.renderer.domElement;
  581. let ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  582. let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
  583. if (I) {
  584. let center = this.scene.getWorldPosition(new THREE.Vector3());
  585. let from = drag.pivot;
  586. let to = I;
  587. let v1 = from.clone().sub(center).normalize();
  588. let v2 = to.clone().sub(center).normalize();
  589. let angle = Math.acos(v1.dot(v2));
  590. let sign = Math.sign(v1.cross(v2).dot(n));
  591. angle = angle * sign;
  592. if (Number.isNaN(angle)) {
  593. return;
  594. }
  595. let matrixBefore = this.selection[0].matrix.clone()
  596. let normal = new THREE.Vector3(...handle.alignment);
  597. for (let selection of this.selection) {
  598. selection.rotateOnAxis(normal, angle);
  599. selection.dispatchEvent({
  600. type: "orientation_changed",
  601. object: selection
  602. });
  603. }
  604. this.dispatchEvent({type:'transformed', changeType: ['orientation'], matrixBefore })//add
  605. drag.pivot = I;
  606. }
  607. }
  608. dropRotationHandle(e){
  609. this.dragging = false;
  610. this.setActiveHandle(null);
  611. this.dispatchEvent({type:'stopDrag', handle:'rotation'})//add
  612. }
  613. dragTranslationHandle(e){//---大改,参考transformControls,为了加上xyz xy yz xz 这四个方向的变换。 (但感觉好像plane上有丢丢延迟?是因为drag延迟还是worldmatrix没更新)
  614. let drag = e.drag;
  615. let handle = this.activeHandle;
  616. let camera = this.viewer.mainViewport.camera//this.viewer.scene.getActiveCamera();
  617. if(handle && this.selection[0]){
  618. let posWorld = this.selection[0].getWorldPosition(new THREE.Vector3()); //是需要世界坐标吗
  619. if(!drag.intersectionStart){
  620. drag.intersectionStart = drag.location;
  621. drag.worldPositionStart = posWorld
  622. drag.objectQua = this.selection[0].quaternion.clone()//不考虑父级
  623. drag.objectQuaInv = drag.objectQua.clone().invert()
  624. this.dragging = true
  625. }
  626. if(drag.intersectionStart){
  627. let pointer = this.viewer.inputHandler.pointer
  628. let ray = Utils.mouseToRay(pointer, camera);
  629. let normal = viewer.mainViewport.view.direction
  630. drag.dragPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, posWorld/* drag.worldPositionStart */)//过center的与视线垂直的平面
  631. let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
  632. if (I) {
  633. let offset = new THREE.Vector3().subVectors( I , drag.worldPositionStart );
  634. //let offset = new THREE.Vector3().subVectors(iOnLine, drag.worldPositionStart);
  635. if(!drag.pointStart){
  636. drag.pointStart = offset
  637. }else{
  638. drag.pointEnd = offset
  639. let diff = new THREE.Vector3().subVectors(drag.pointEnd, drag.pointStart)
  640. diff.applyQuaternion(drag.objectQuaInv) // 得到在该物体local空间上的offset
  641. if(!handle.name.includes('x')) diff.x = 0
  642. if(!handle.name.includes('y')) diff.y = 0
  643. if(!handle.name.includes('z')) diff.z = 0
  644. //恢复为world offset
  645. diff.applyQuaternion(drag.objectQua)
  646. //-------------
  647. let matrixBefore = this.selection[0].matrix.clone()
  648. this.selection[0].position.copy( diff ).add( drag.worldPositionStart );
  649. for (let selection of this.selection) {
  650. selection.dispatchEvent({
  651. type: "position_changed",
  652. object: selection
  653. });
  654. }
  655. this.dispatchEvent({type:'transformed', changeType: ['position'], matrixBefore})//add
  656. }
  657. }
  658. }
  659. }
  660. }
  661. dropTranslationHandle(e){
  662. this.dragging = false;
  663. this.setActiveHandle(null);
  664. this.dispatchEvent({type:'stopDrag', handle:'translation'})//add
  665. }
  666. dropScaleHandle(e){
  667. this.dragging = false;
  668. this.setActiveHandle(null);
  669. this.dispatchEvent({type:'stopDrag', handle:'scale'})//add
  670. }
  671. dragScaleHandle(e){
  672. let drag = e.drag;
  673. let handle = this.activeHandle;
  674. if(!handle)return
  675. let camera = this.viewer.mainViewport.camera//this.viewer.scene.getActiveCamera();
  676. if(!drag.intersectionStart){
  677. drag.intersectionStart = drag.location;
  678. drag.objectStart = drag.object.getWorldPosition(new THREE.Vector3());
  679. drag.handle = handle;
  680. let start = drag.intersectionStart;
  681. let dir = new THREE.Vector4(...handle.alignment, 0).applyMatrix4(this.scene.matrixWorld);
  682. let end = new THREE.Vector3().addVectors(start, dir);
  683. let line = new THREE.Line3(start.clone(), end.clone());
  684. drag.line = line;
  685. let normal
  686. if(camera.type == 'OrthographicCamera'){//xzw add
  687. normal = new THREE.Vector3(0,0,-1).applyQuaternion(camera.quaternion)
  688. }else{
  689. let camOnLine = line.closestPointToPoint(camera.position, false, new THREE.Vector3());
  690. normal = new THREE.Vector3().subVectors(camera.position, camOnLine);
  691. }
  692. let plane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, drag.intersectionStart); //过轴线的一个能铺满屏幕的平面
  693. drag.dragPlane = plane;
  694. drag.pivot = drag.intersectionStart;
  695. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  696. }else{
  697. handle = drag.handle;
  698. }
  699. this.dragging = true;
  700. if(drag.dragPlane){//xzw add 因有时候没有
  701. let pointer = this.viewer.inputHandler.pointer
  702. let domElement = this.viewer.renderer.domElement;
  703. let ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  704. let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
  705. if (I) {
  706. let iOnLine = drag.line.closestPointToPoint(I, false, new THREE.Vector3());
  707. let direction = handle.alignment.reduce( (a, v) => a + v, 0);
  708. let toObjectSpace = this.selection[0].matrixWorld.clone().invert();
  709. let iOnLineOS = iOnLine.clone().applyMatrix4(toObjectSpace);
  710. let pivotOS = drag.pivot.clone().applyMatrix4(toObjectSpace);
  711. let diffOS = new THREE.Vector3().subVectors(iOnLineOS, pivotOS);
  712. let dragDirectionOS = diffOS.clone().normalize();
  713. if(iOnLine.distanceTo(drag.pivot) === 0){
  714. dragDirectionOS.set(0, 0, 0);
  715. }
  716. let dragDirection = dragDirectionOS.dot(new THREE.Vector3(...handle.alignment));
  717. let diff = new THREE.Vector3().subVectors(iOnLine, drag.pivot);
  718. let diffScale = new THREE.Vector3(...handle.alignment).multiplyScalar(diff.length() * direction * dragDirection);
  719. let diffPosition = diff.clone().multiplyScalar(0.5);
  720. let matrixBefore = this.selection[0].matrix.clone()
  721. for (let selection of this.selection) {
  722. //xzw 改:否则不跟手
  723. let diffScale_ = diffScale.clone().divide(selection.boundingBox.getSize(new THREE.Vector3))
  724. selection.scale.add(diffScale_);
  725. //selection.scale.add(diffScale);
  726. selection.scale.x = Math.max(0.1, selection.scale.x);
  727. selection.scale.y = Math.max(0.1, selection.scale.y);
  728. selection.scale.z = Math.max(0.1, selection.scale.z);
  729. selection.position.add(diffPosition);
  730. selection.dispatchEvent({
  731. type: "position_changed",
  732. object: selection
  733. });
  734. selection.dispatchEvent({
  735. type: "scale_changed",
  736. object: selection
  737. });
  738. this.dispatchEvent({type:'transformed', changeType: ['position','scale'], matrixBefore})//add
  739. }
  740. drag.pivot.copy(iOnLine);
  741. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  742. }
  743. }
  744. }
  745. setActiveHandle(handle){
  746. if(this.dragging){
  747. return;
  748. }
  749. if(this.activeHandle === handle){
  750. return;
  751. }
  752. this.activeHandle = handle;
  753. if(handle === null){
  754. for(let handleName of Object.keys(this.handles)){
  755. let handle = this.handles[handleName];
  756. handle.node.setOpacity(0);
  757. }
  758. }
  759. viewer.dispatchEvent({type:'CursorChange', action: this.activeHandle ? 'add' : 'remove', name:'hoverTranHandle'})
  760. if(!hideFocusHandles){
  761. for(let handleName of Object.keys(this.focusHandles)){
  762. let handle = this.focusHandles[handleName];
  763. if(this.activeHandle === handle){
  764. handle.node.setOpacity(1.0);
  765. }else{
  766. handle.node.setOpacity(OpaWhenNotSelect)
  767. }
  768. }
  769. }
  770. for(let handleName of Object.keys(this.translationHandles)){
  771. let handle = this.translationHandles[handleName];
  772. if(this.activeHandle === handle){
  773. handle.node.setOpacity(1.0);
  774. }else{
  775. handle.node.setOpacity(OpaWhenNotSelect)
  776. }
  777. }
  778. for(let handleName of Object.keys(this.rotationHandles)){
  779. let handle = this.rotationHandles[handleName];
  780. //if(this.activeHandle === handle){
  781. // handle.node.setOpacity(1.0);
  782. //}else{
  783. // handle.node.setOpacity(OpaWhenNotSelect)
  784. //}
  785. handle.node.setOpacity(OpaWhenNotSelect);
  786. }
  787. for(let handleName of Object.keys(this.scaleHandles)){
  788. let handle = this.scaleHandles[handleName];
  789. if(this.activeHandle === handle){
  790. handle.node.setOpacity(1.0);
  791. if(!hideFocusHandles){
  792. let relatedFocusHandle = this.focusHandles[handle.name.replace("scale", "focus")];
  793. let relatedFocusNode = relatedFocusHandle.node;
  794. relatedFocusNode.setOpacity(OpaWhenNotSelect);
  795. }
  796. for(let translationHandleName of Object.keys(this.translationHandles)){
  797. let translationHandle = this.translationHandles[translationHandleName];
  798. translationHandle.node.setOpacity(OpaWhenNotSelect);
  799. }
  800. //let relatedTranslationHandle = this.translationHandles[
  801. // handle.name.replace("scale", "translation").replace(/[+-]/g, "")];
  802. //let relatedTranslationNode = relatedTranslationHandle.node;
  803. //relatedTranslationNode.setOpacity(OpaWhenNotSelect);
  804. }else{
  805. handle.node.setOpacity(OpaWhenNotSelect)
  806. }
  807. }
  808. if(handle){
  809. handle.node.setOpacity(1.0);
  810. }
  811. viewer.dispatchEvent('content_changed')
  812. }
  813. update () {
  814. if(this.selection.length === 1){
  815. this.scene.visible = true;
  816. this.scene.updateMatrix();
  817. this.scene.updateMatrixWorld();
  818. let selected = this.selection[0];
  819. let world = selected.matrixWorld;
  820. let camera = this.viewer.mainViewport.camera//this.viewer.scene.getActiveCamera();
  821. let domElement = this.viewer.renderer.domElement;
  822. let center = selected.boundingBox.getCenter(new THREE.Vector3()).clone().applyMatrix4(selected.matrixWorld);
  823. this.scene.scale.copy(selected.boundingBox.getSize(new THREE.Vector3()).multiply(selected.scale));
  824. this.scene.position.copy(center);
  825. this.scene.rotation.copy(selected.rotation); //这里只考虑当前子级的scale rotation
  826. //如果是世界坐标 (缩放方向有bug。)
  827. /*
  828. let boundingBox = selected.boundingBox.clone().applyMatrix4(selected.matrixWorld);
  829. let center = boundingBox.getCenter(new THREE.Vector3())
  830. this.scene.position.copy(center);
  831. this.scene.scale.copy(boundingBox.getSize(new THREE.Vector3()));
  832. */
  833. this.scene.updateMatrixWorld();
  834. {
  835. // adjust rotation handles
  836. if(!this.dragging){
  837. if(this.modesEnabled.rotation || this.modesEnabled.translation){
  838. let tWorld = this.scene.matrixWorld;
  839. let tObject = tWorld.clone().invert();
  840. let camObjectPos = camera.getWorldPosition(new THREE.Vector3()).applyMatrix4(tObject);
  841. if(this.modesEnabled.translation){//add
  842. ['xy','yz','xz'].forEach(axis=>{
  843. let handle = this.translationHandles["translation.plane."+axis]
  844. let pos = handle.node.children[0].position
  845. camObjectPos.x && (pos.x = Math.sign(camObjectPos.x) * Math.abs(pos.x))
  846. camObjectPos.y && (pos.y = Math.sign(camObjectPos.y) * Math.abs(pos.y))
  847. camObjectPos.z && (pos.z = Math.sign(camObjectPos.z) * Math.abs(pos.z))
  848. })
  849. }
  850. if(this.modesEnabled.rotation){
  851. let above = camObjectPos.z > 0;
  852. let below = !above;
  853. let PI_HALF = Math.PI / 2;
  854. let x = this.rotationHandles["rotation.x"].node.rotation;
  855. let y = this.rotationHandles["rotation.y"].node.rotation;
  856. let z = this.rotationHandles["rotation.z"].node.rotation;
  857. x.order = "ZYX";
  858. y.order = "ZYX";
  859. if(above){
  860. if(camObjectPos.x > 0 && camObjectPos.y > 0){
  861. x.x = 1 * PI_HALF;
  862. y.y = 3 * PI_HALF;
  863. z.z = 0 * PI_HALF;
  864. }else if(camObjectPos.x < 0 && camObjectPos.y > 0){
  865. x.x = 1 * PI_HALF;
  866. y.y = 2 * PI_HALF;
  867. z.z = 1 * PI_HALF;
  868. }else if(camObjectPos.x < 0 && camObjectPos.y < 0){
  869. x.x = 2 * PI_HALF;
  870. y.y = 2 * PI_HALF;
  871. z.z = 2 * PI_HALF;
  872. }else if(camObjectPos.x > 0 && camObjectPos.y < 0){
  873. x.x = 2 * PI_HALF;
  874. y.y = 3 * PI_HALF;
  875. z.z = 3 * PI_HALF;
  876. }
  877. }else if(below){
  878. if(camObjectPos.x > 0 && camObjectPos.y > 0){
  879. x.x = 0 * PI_HALF;
  880. y.y = 0 * PI_HALF;
  881. z.z = 0 * PI_HALF;
  882. }else if(camObjectPos.x < 0 && camObjectPos.y > 0){
  883. x.x = 0 * PI_HALF;
  884. y.y = 1 * PI_HALF;
  885. z.z = 1 * PI_HALF;
  886. }else if(camObjectPos.x < 0 && camObjectPos.y < 0){
  887. x.x = 3 * PI_HALF;
  888. y.y = 1 * PI_HALF;
  889. z.z = 2 * PI_HALF;
  890. }else if(camObjectPos.x > 0 && camObjectPos.y < 0){
  891. x.x = 3 * PI_HALF;
  892. y.y = 0 * PI_HALF;
  893. z.z = 3 * PI_HALF;
  894. }
  895. }
  896. }
  897. }
  898. }
  899. // adjust scale of components
  900. for(let handleName of Object.keys(this.handles)){
  901. let handle = this.handles[handleName];
  902. let node = handle.node;
  903. //xzw add:---- -当该轴正对相机时隐藏。(主要针对ortho类型camera。
  904. if(!Potree.Utils.getObjVisiByReason(node,'modeForce') )continue;
  905. let alignment = handle.alignment;
  906. if(alignment && (!handleName.includes('rotation') || camera.type == 'OrthographicCamera')){//旋转的话正常都应该显示
  907. let normal
  908. let dir = new THREE.Vector3(...alignment).applyQuaternion(this.scene.quaternion)
  909. if(camera.type == 'OrthographicCamera'){
  910. normal = new THREE.Vector3(0,0,-1).applyQuaternion(camera.quaternion)
  911. }else{
  912. normal = new THREE.Vector3().subVectors(center, camera.position).normalize()
  913. }
  914. let ifOnLine
  915. if(handleName.includes('rotation') || handleName.includes('plane')){ // 旋转轴和视线垂直时隐藏
  916. ifOnLine = Math.abs(dir.dot(normal)) < 0.1
  917. }else{
  918. ifOnLine = Math.abs(dir.dot(normal)) > 0.995
  919. }
  920. Potree.Utils.updateVisible(node, 'faceToCamHide', !ifOnLine)
  921. }else{
  922. Potree.Utils.updateVisible(node, 'faceToCamHide', true)
  923. }
  924. if(!node.visible)continue;
  925. //------------------------------------------------------------------------
  926. if(handle.dontScale)continue; //add
  927. let handlePos = node.getWorldPosition(new THREE.Vector3());
  928. let distance = handlePos.distanceTo(camera.position);
  929. let pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
  930. let ws = node.parent.getWorldScale(new THREE.Vector3());
  931. let s = (ScaleRatio / pr);
  932. let scale = new THREE.Vector3(s, s, s).divide(ws);
  933. let rot = new THREE.Matrix4().makeRotationFromEuler(node.rotation); //需要使用到旋转,所以我把设置scale的移到旋转后了,否则在视图上下旋转的分界线处rotateHandel会被拉长从而闪烁。
  934. let rotInv = rot.clone().invert();
  935. scale.applyMatrix4(rotInv);
  936. scale.x = Math.abs(scale.x);
  937. scale.y = Math.abs(scale.y);
  938. scale.z = Math.abs(scale.z);
  939. node.scale.copy(scale);
  940. }
  941. }
  942. }else{
  943. this.scene.visible = false;
  944. }
  945. }
  946. onPointerMove(){
  947. let pointer = this.viewer.inputHandler.pointer;
  948. let camera = this.viewer.mainViewport.camera
  949. if( this.selection.length === 1 && !this.dragging ){ //xzw 添加dragging条件
  950. let ray = Utils.mouseToRay(pointer, camera );
  951. let raycaster = new THREE.Raycaster(ray.origin, ray.direction);
  952. raycaster.layers.enableAll()//add
  953. let pickVolumes = this.pickVolumes.filter(v=>{
  954. let mode = v.handle.split('.')[0];
  955. if(!this.modesEnabled[mode])return
  956. return v.parent.parent.visible //可能被隐藏该轴
  957. })
  958. let intersects = raycaster.intersectObjects(pickVolumes, true);
  959. intersects = intersects.sort(function(a,b){
  960. let order2 = b.object.renderOrder || 0
  961. let order1 = a.object.renderOrder || 0
  962. return order2-order1
  963. }) // 降序
  964. if(intersects.length > 0){
  965. let I = intersects[0];
  966. let handleName = I.object.handle;
  967. //console.log(handleName)
  968. this.setActiveHandle(this.handles[handleName]);
  969. }else{
  970. this.setActiveHandle(null);
  971. }
  972. }
  973. }
  974. };
  975. /*
  976. note:
  977. transformationTool.scene会跟随选中物体,其scale就是boundingbox的大小。因此transformationTool.frame这个框也会跟着缩放
  978. */