DrawUtil.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import math from './math';
  3. import {Line2} from "../../libs/three.js/lines/Line2.js";
  4. import {LineGeometry} from "../../libs/three.js/lines/LineGeometry.js";
  5. import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
  6. //画线等函数--by 许钟文
  7. var defaultColor = new THREE.Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
  8. var LineDraw = {
  9. createLine: function (posArr, o={}) {
  10. //多段普通线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  11. var mat = o.mat || new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"]({
  12. linewidth: o.linewidth || 1,
  13. //windows无效。 似乎mac/ios上粗细有效 ?
  14. color: o.color || defaultColor,
  15. transparent: o.dontAlwaysSeen ? false : true,
  16. depthTest: o.dontAlwaysSeen ? true : false,
  17. dashSize : o.dashSize || 0.1,
  18. gapSize: o.gapSize || 0.1
  19. })
  20. var line = new THREE.LineSegments(new THREE.BufferGeometry, mat);
  21. line.renderOrder = o.renderOrder || 4
  22. this.moveLine(line, posArr)
  23. return line;
  24. },
  25. moveLine: function (line, posArr) {
  26. if(posArr.length == 0)return
  27. let position = []
  28. posArr.forEach(e=>position.push(e.x,e.y,e.z))
  29. line.geometry.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(position), 3));
  30. line.geometry.attributes.position.needsUpdate = true;
  31. line.geometry.computeBoundingSphere();
  32. if(line.material instanceof THREE.LineDashedMaterial){
  33. line.computeLineDistances()
  34. }
  35. }
  36. ,
  37. /*
  38. 为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
  39. 由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
  40. */
  41. createBoldLine:function(points, o){
  42. o = o || {}
  43. var cylinder = o && o.cylinder;
  44. var CD = points[1].clone().sub(points[0]);
  45. var rotate = function(){//根据端点旋转好模型
  46. cylinder.lastVector = CD;//记录本次的端点向量
  47. var AB = new THREE.Vector3(0,-1,0)
  48. var axisVec = AB.clone().cross(CD).normalize(); //得到垂直于它们的向量,也就是旋转轴
  49. var rotationAngle = AB.angleTo(CD);
  50. cylinder.quaternion.setFromAxisAngle( axisVec, rotationAngle )
  51. }
  52. if(o && o.type == "init"){
  53. cylinder = new THREE.Mesh()
  54. cylinder.material = o.mat
  55. if(CD.length() == 0)return cylinder;
  56. rotate()
  57. }
  58. if(CD.length() == 0)return cylinder;
  59. if(o.type != "update"){
  60. var CDcenter = points[0].clone().add(points[1]).multiplyScalar(.5);
  61. cylinder.position.copy(CDcenter);
  62. if(!cylinder.lastVector || o.type == "moveAndRotate")rotate()
  63. else if(cylinder.lastVector && CD.angleTo(cylinder.lastVector)>0) rotate()//线方向改了or线反向了 重新旋转一下模型
  64. if(config.isEdit && !objects.mainDesign.editing )return cylinder;//节省初始加载时间?
  65. }
  66. //为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
  67. var height = points[0].distanceTo(points[1]);
  68. var standPos = o && o.standPos || objects.player.position;
  69. var k = config.isMobile ? 20 : 40;
  70. var dis1 = points[0].distanceTo(standPos);
  71. var dis2 = points[1].distanceTo(standPos);
  72. var foot = math.getFootPoint(standPos, points[0], points[1]);//垂足
  73. if(o.constantBold || objects.player.mode != "panorama"){
  74. var width = 0.1//0.08;
  75. var pts = [new THREE.Vector2(width ,height/2),new THREE.Vector2(width ,-height/2)]
  76. }else if(foot.clone().sub(points[0]).dot( foot.clone().sub(points[1]) ) > 0){//foot不在线段上
  77. var pts = [new THREE.Vector2(dis1 / k,height/2),new THREE.Vector2(dis2 / k,-height/2)]
  78. }else{//在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
  79. var dis3 = foot.distanceTo(standPos);
  80. var len = foot.distanceTo(points[0])
  81. var pts = [new THREE.Vector2(dis1 / k,height/2), new THREE.Vector2(dis3 / k,height/2-len), new THREE.Vector2(dis2 / k,-height/2)]
  82. }
  83. cylinder.geometry && cylinder.geometry.dispose();//若不删除会占用内存
  84. cylinder.geometry = new THREE.LatheBufferGeometry( pts, 4/* Math.min(dis1,dis2)<10?4:3 */ )
  85. cylinder.renderOrder = 2;
  86. return cylinder;
  87. },
  88. updateBoldLine:function(cylinder, points, type, standPos, constantBold){
  89. this.createBoldLine(points,{type:type, cylinder : cylinder, standPos:standPos, constantBold}) //type:move:平移 会改长短 , type:update根据距离和角度更新 不改长短
  90. },
  91. createFatLineMat : function(o){
  92. var mat = new LineMaterial( {
  93. color: o.color || 0xffffff,
  94. linewidth: o.linewidth || 5, // in pixels
  95. //vertexColors: THREE.VertexColors,//THREE.VertexColors,
  96. resolution: o.resolution || new THREE.Vector2(100,100),// to be set by renderer, eventually
  97. //viewportOffset: o.viewportOffset,
  98. transparent:true, //o.dontAlwaysSeen ? false : true,
  99. depthTest: false,// o.alwaysShow ? false : true,//o.dontAlwaysSeen ? true : false
  100. depthWrite:false,
  101. dashSize : o.dashSize || 0.1,
  102. gapSize: o.gapSize || 0.1,
  103. useDepth: !!o.useDepth,
  104. dashed: !!o.dashed,
  105. dashWithDepth:!!o.dashWithDepth,//只在被遮住的部分显示虚线
  106. /* transparent:o.dontAlwaysSeen ? false : true,
  107. depthTest:o.dontAlwaysSeen ? true : false
  108. */
  109. /* polygonOffset : true,//是否开启多边形偏移 for not cover the lineMesh
  110. polygonOffsetFactor : -o.width*2.5 || -5 ,//多边形偏移因子
  111. polygonOffsetUnits : -4.0,//多边形偏移单位 */
  112. } );
  113. //if(o.dashed)(mat.defines.USE_DASH = "")
  114. var opa = 0
  115. Object.defineProperty( mat, "opacity", {
  116. get: function () {
  117. return opa;
  118. },
  119. set: function(o){
  120. mat.uniforms.opacity.value = opa = o;
  121. }
  122. })
  123. mat.opacity = o.opacity != void 0 ? o.opacity : 1;
  124. return mat;
  125. },
  126. /*
  127. 创建可以改变粗细的线。
  128. */
  129. createFatLine : function(posArr, o){
  130. var geometry = new LineGeometry();
  131. geometry.setPositions( posArr );
  132. geometry.setColors( o.color || [1,1,1]);
  133. var matLine = o.material || this.createFatLineMat(o);
  134. var line = new Line2( geometry, matLine );
  135. //line.computeLineDistances();
  136. if(line.material.defines.USE_DASH != void 0){
  137. //line.geometry.verticesNeedUpdate = true;
  138. //line.geometry.computeBoundingSphere();
  139. line.computeLineDistances();
  140. }
  141. line.scale.set( 1, 1, 1 );
  142. line.renderOrder = 2;
  143. return line;
  144. },
  145. moveFatLine: function(line, posArr){
  146. var geometry = line.geometry;
  147. geometry.setPositions( [
  148. ...posArr[0].toArray(), ...posArr[1].toArray(),
  149. ]);
  150. if(line.material.defines.USE_DASH != void 0){
  151. //line.geometry.verticesNeedUpdate = true;
  152. //line.geometry.computeBoundingSphere();
  153. line.computeLineDistances();
  154. }
  155. },
  156. updateLine: function(line, posArr){
  157. if(line instanceof Line2){
  158. LineDraw.moveFatLine(line,posArr)
  159. }else{
  160. LineDraw.moveLine(line,posArr)
  161. }
  162. }
  163. }
  164. var MeshDraw = {
  165. getShape:function(points, holes){
  166. var shape = new THREE.Shape();
  167. shape.moveTo( points[0].x, points[0].y );
  168. for(var i=1,len=points.length; i<len; i++){
  169. shape.lineTo(points[i].x, points[i].y )
  170. }
  171. /* var holePath = new THREE.Path()
  172. .moveTo( 20, 10 )
  173. .absarc( 10, 10, 10, 0, Math.PI * 2, true )
  174. arcShape.holes.push( holePath );
  175. */
  176. if(holes){//挖空
  177. holes.forEach((points)=>{
  178. var holePath = new THREE.Path()
  179. holePath.moveTo( points[0].x, points[0].y )
  180. for(var i=1,len=points.length; i<len; i++){
  181. holePath.lineTo(points[i].x, points[i].y )
  182. }
  183. shape.holes.push( holePath );
  184. })
  185. }
  186. return shape
  187. },
  188. getShapeGeo: function(points, holes){//获取任意形状(多边形或弧形)的形状面 //quadraticCurveTo() 这是弧形的含函数
  189. var geometry = new THREE.ShapeBufferGeometry( this.getShape(points, holes) ); //ShapeGeometry
  190. /* var matrix = new THREE.Matrix4();//将竖直的面变为水平
  191. matrix.set(//z = y
  192. 1, 0, 0, 0,
  193. 0, 0, 0, 0,
  194. 0, 1, 0, 0,
  195. 0, 0, 0, 1
  196. )
  197. geometry.applyMatrix(matrix) */
  198. //geometry.computeVertexNormals();//对于光照需要的是点法线
  199. return geometry;
  200. },
  201. getExtrudeGeo: function(points, height){//获得挤出棱柱
  202. var shape = this.getShape(points)
  203. var extrudeSettings = {
  204. steps: 1,
  205. bevelEnabled: false,
  206. depth: height,
  207. };
  208. var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
  209. return geometry;
  210. },
  211. getUnPosPlaneGeo : function(){//获取还没有赋值位置的plane geometry
  212. var e = new Uint16Array([0, 1, 2, 0, 2, 3])
  213. // , t = new Float32Array([-.5, -.5, 0, .5, -.5, 0, .5, .5, 0, -.5, .5, 0])
  214. , i = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1])
  215. , g = new THREE.BufferGeometry;
  216. g.setIndex(new THREE.BufferAttribute(e, 1)),
  217. //g.addAttribute("position", new n.BufferAttribute(t, 3)),
  218. g.setAttribute("uv", new THREE.BufferAttribute(i, 2))
  219. return function(){
  220. return g
  221. }
  222. }(),
  223. getPlaneGeo : function(A,B,C,D){
  224. var geo = this.getUnPosPlaneGeo().clone();
  225. var pos = new Float32Array([
  226. A.x, A.y, A.z,
  227. B.x, B.y, B.z,
  228. C.x, C.y, C.z,
  229. D.x, D.y, D.z
  230. ])
  231. geo.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  232. geo.computeVertexNormals()
  233. geo.computeBoundingSphere() //for raycaster
  234. return geo;
  235. },
  236. drawPlane : function(A,B,C,D, material){
  237. var wall = new THREE.Mesh(this.getPlaneGeo(A,B,C,D), material);
  238. return wall;
  239. },
  240. movePlane: function(mesh, A,B,C,D){
  241. var pos = new Float32Array([
  242. A.x, A.y, A.z,
  243. B.x, B.y, B.z,
  244. C.x, C.y, C.z,
  245. D.x, D.y, D.z
  246. ])
  247. mesh.geometry.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  248. mesh.geometry.computeBoundingSphere()//for checkIntersect
  249. }
  250. }
  251. export {LineDraw, MeshDraw} ;