DrawUtil.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import math from './math.js';
  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. import {Features} from "../../Features.js";
  8. import Common from './Common.js'
  9. var defaultColor = new THREE.Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
  10. function dealPosArr(points){//识别是否每个点都不一样,把连续点变为不连续的片段连接
  11. let add = (points)=>{
  12. let points2 = [] , len = points.length
  13. for(let i=0;i<len-1;i++){
  14. points2.push(points[i], points[i+1])
  15. }
  16. return points2
  17. }
  18. if(points[0] && points[0] instanceof Array){//多组,每组间连续,但组之间不连续
  19. let points2 = []
  20. points.forEach(ps=>points2.push(...add(ps)))
  21. return points2
  22. }else if(points.length > 2 && !points[2].equals(points[1])){
  23. return add(points)
  24. }else return points
  25. }
  26. let center = new THREE.Vector3
  27. function extractPos(posArr){//尽量让所有点都靠近原点
  28. //console.log('extractPos', posArr.map(e=>e.clone()))
  29. let bound = new THREE.Box3
  30. posArr.forEach(e=>bound.expandByPoint(e))
  31. bound.getCenter(center)
  32. posArr.forEach(e=>e.sub(center))
  33. //console.log('extractPos2 ', posArr.map(e=>e.clone()), center.clone())
  34. return center.clone()
  35. }
  36. var LineDraw = {
  37. createLine: function (posArr, o={}) {
  38. //多段普通线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  39. var mat
  40. if(o.mat){
  41. mat = o.mat
  42. }else{
  43. let prop = Object.assign({
  44. lineWidth: o.lineWidth || 1,
  45. //windows无效。 似乎mac/ios上粗细有效 ?
  46. color: o.color || defaultColor
  47. },o)
  48. if(o.deshed ){
  49. prop.dashSize = o.dashSize || 0.1,
  50. prop.gapSize = o.gapSize || 0.1
  51. }
  52. mat = new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"](prop)
  53. }
  54. var line = new THREE.LineSegments(new THREE.BufferGeometry, mat);
  55. line.renderOrder = o.renderOrder || Potree.config.renderOrders.line
  56. line.avoidBigNumber = o.avoidBigNumber
  57. this.moveLine(line, posArr)
  58. return line;
  59. },
  60. moveLine: function (line, posArr) {
  61. posArr = Common.CloneObject(posArr)
  62. //if(posArr.length == 0)return
  63. if(!line.uncontinuous || posArr[0] && posArr[0] instanceof Array)posArr = dealPosArr(posArr)
  64. let position = []
  65. posArr.forEach(e=>position.push(e.x,e.y,e.z))
  66. if(line.avoidBigNumber){
  67. let moveVec = extractPos(posArr)
  68. line.position.copy(moveVec)//无视原本的position!
  69. }
  70. line.geometry.setAttribute('position', new THREE.Float32BufferAttribute(/* new Float32Array( */position/* ) */, 3));
  71. line.geometry.attributes.position.needsUpdate = true;
  72. line.geometry.computeBoundingSphere();
  73. if(line.material instanceof THREE.LineDashedMaterial){
  74. line.computeLineDistances()
  75. //line.geometry.attributes.lineDistance.needsUpdate = true;
  76. line.geometry.verticesNeedUpdate = true; //没用
  77. }
  78. }
  79. ,
  80. createFatLineMat : function(o){
  81. var supportExtDepth = !!Features.EXT_DEPTH.isSupported()
  82. let params = $.extend({}, {
  83. //默认
  84. lineWidth : 5,
  85. color:0xffffff,
  86. transparent : true, depthWrite:false, depthTest:false,
  87. dashSize : 0.1, gapSize:0.1,
  88. }, o, {
  89. //修正覆盖:
  90. dashed: o.dashWithDepth ? supportExtDepth && !!o.dashed : !!o.dashed ,
  91. dashWithDepth:!!o.dashWithDepth,//只在被遮住的部分显示虚线
  92. useDepth: !!o.useDepth,
  93. supportExtDepth,
  94. })
  95. var mat = new LineMaterial(params)
  96. //if(o.dashed)(mat.defines.USE_DASH = "")
  97. return mat;
  98. },
  99. /*
  100. 创建可以改变粗细的线。
  101. */
  102. createFatLine : function(posArr, o){
  103. var geometry = new LineGeometry();
  104. geometry.setColors( o.color || [1,1,1]);
  105. var matLine = o.mat || this.createFatLineMat(o);
  106. var line = new Line2( geometry, matLine );
  107. //line.computeLineDistances();
  108. line.uncontinuous = o.uncontinuous //线不连续,由线段组成
  109. line.avoidBigNumber = o.avoidBigNumber
  110. line.scale.set( 1, 1, 1 );
  111. line.renderOrder = Potree.config.renderOrders.line;
  112. this.moveFatLine(line, posArr)
  113. return line;
  114. },
  115. moveFatLine: function(line, posArr ){
  116. posArr = Common.CloneObject(posArr)
  117. var geometry = line.geometry;
  118. var positions = [];
  119. if(!line.uncontinuous || posArr[0] && posArr[0] instanceof Array) posArr = dealPosArr(posArr)
  120. if(line.avoidBigNumber){
  121. let moveVec = extractPos(posArr)
  122. line.position.copy(moveVec)//无视原本的position!
  123. }
  124. posArr.forEach(e=>{positions.push(...e.toArray())})
  125. if(!geometry){
  126. geometry = line.geometry = new LineGeometry();
  127. }
  128. if(geometry.attributes.instanceEnd && geometry.attributes.instanceEnd.data.array.length != positions.length){//positions个数改变会有部分显示不出来,所以重建
  129. geometry.dispose();
  130. geometry = new LineGeometry();
  131. line.geometry = geometry
  132. }
  133. geometry.setPositions( positions )
  134. if(line.material.defines.USE_DASH != void 0){
  135. //line.geometry.verticesNeedUpdate = true; //没用
  136. line.geometry.computeBoundingSphere(); //for raycaster
  137. line.computeLineDistances();
  138. }
  139. },
  140. updateLine: function(line, posArr){
  141. if(line instanceof Line2){
  142. LineDraw.moveFatLine(line,posArr)
  143. }else{
  144. LineDraw.moveLine(line,posArr)
  145. }
  146. },
  147. /*
  148. 为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
  149. 由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
  150. */
  151. createBoldLine:function(points, o){
  152. o = o || {}
  153. var cylinder = o && o.cylinder;
  154. var CD = points[1].clone().sub(points[0]);
  155. var rotate = function(){//根据端点旋转好模型
  156. cylinder.lastVector = CD;//记录本次的端点向量
  157. var AB = new THREE.Vector3(0,-1,0)
  158. var axisVec = AB.clone().cross(CD).normalize(); //得到垂直于它们的向量,也就是旋转轴
  159. var rotationAngle = AB.angleTo(CD);
  160. cylinder.quaternion.setFromAxisAngle( axisVec, rotationAngle )
  161. }
  162. if(o && o.type == "init"){
  163. cylinder = new THREE.Mesh()
  164. cylinder.material = o.mat
  165. if(CD.length() == 0)return cylinder;
  166. rotate()
  167. }
  168. if(CD.length() == 0)return cylinder;
  169. if(o.type != "update"){
  170. var CDcenter = points[0].clone().add(points[1]).multiplyScalar(.5);
  171. cylinder.position.copy(CDcenter);
  172. if(!cylinder.lastVector || o.type == "moveAndRotate")rotate()
  173. else if(cylinder.lastVector && CD.angleTo(cylinder.lastVector)>0) rotate()//线方向改了or线反向了 重新旋转一下模型
  174. if(config.isEdit && !objects.mainDesign.editing )return cylinder;//节省初始加载时间?
  175. }
  176. //为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
  177. var height = points[0].distanceTo(points[1]);
  178. var standPos = o && o.standPos || objects.player.position;
  179. var k = config.isMobile ? 20 : 40;
  180. var dis1 = points[0].distanceTo(standPos);
  181. var dis2 = points[1].distanceTo(standPos);
  182. var foot = math.getFootPoint(standPos, points[0], points[1]);//垂足
  183. if(o.constantBold || objects.player.mode != "panorama"){
  184. var width = 0.1//0.08;
  185. var pts = [new THREE.Vector2(width ,height/2),new THREE.Vector2(width ,-height/2)]
  186. }else if(foot.clone().sub(points[0]).dot( foot.clone().sub(points[1]) ) > 0){//foot不在线段上
  187. var pts = [new THREE.Vector2(dis1 / k,height/2),new THREE.Vector2(dis2 / k,-height/2)]
  188. }else{//在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
  189. var dis3 = foot.distanceTo(standPos);
  190. var len = foot.distanceTo(points[0])
  191. var pts = [new THREE.Vector2(dis1 / k,height/2), new THREE.Vector2(dis3 / k,height/2-len), new THREE.Vector2(dis2 / k,-height/2)]
  192. }
  193. cylinder.geometry && cylinder.geometry.dispose();//若不删除会占用内存
  194. cylinder.geometry = new THREE.LatheBufferGeometry( pts, 4/* Math.min(dis1,dis2)<10?4:3 */ )
  195. cylinder.renderOrder = 2;
  196. return cylinder;
  197. },
  198. updateBoldLine:function(cylinder, points, type, standPos, constantBold){
  199. this.createBoldLine(points,{type:type, cylinder : cylinder, standPos:standPos, constantBold}) //type:move:平移 会改长短 , type:update根据距离和角度更新 不改长短
  200. },
  201. }
  202. var MeshDraw = {
  203. getShape: function(shapes, holes){
  204. //不一定闭合 暂时所有shapes共享holes。如果要单独的话, shapes改为[{shape:[],holes:[]},{}]的形式
  205. if(shapes[0] && !(shapes[0] instanceof Array) ){//仅是一个shape的点
  206. shapes = [shapes]
  207. }
  208. let holesArr = []
  209. if(holes){//挖空
  210. holes.forEach((points)=>{
  211. var holePath = new THREE.Path()
  212. holePath.moveTo( points[0].x, points[0].y )
  213. for(var i=1,len=points.length; i<len; i++){
  214. holePath.lineTo(points[i].x, points[i].y )
  215. }
  216. holesArr.push( holePath );
  217. })
  218. }
  219. let shapesArr = shapes.map(points=>{
  220. var shape = new THREE.Shape();
  221. shape.moveTo( points[0].x, points[0].y );
  222. for(var i=1,len=points.length; i<len; i++){
  223. shape.lineTo(points[i].x, points[i].y )
  224. }
  225. shape.holes.push(...holesArr)
  226. shape.dontClose = points.dontClose //add 有的shape不需要闭合
  227. return shape
  228. })
  229. return shapesArr
  230. },
  231. /* getShape:function(shapes, holes){
  232. var shape = new THREE.Shape();
  233. if(shapes[0] && !(shapes[0] instanceof Array) ){//仅是一个shape的点
  234. shapes = [shapes]
  235. }
  236. shapes.forEach((points)=>{
  237. shape.moveTo( points[0].x, points[0].y );
  238. for(var i=1,len=points.length; i<len; i++){
  239. shape.lineTo(points[i].x, points[i].y )
  240. }
  241. })
  242. //多个points的数组绘制在一个shape中,缺点是这些数组之间可能绘制出来会连在一起。
  243. if(holes){//挖空
  244. holes.forEach((points)=>{
  245. var holePath = new THREE.Path()
  246. holePath.moveTo( points[0].x, points[0].y )
  247. for(var i=1,len=points.length; i<len; i++){
  248. holePath.lineTo(points[i].x, points[i].y )
  249. }
  250. shape.holes.push( holePath );
  251. })
  252. }
  253. return shape
  254. }, */
  255. getShapeGeo: function(shapes, holes){//获取任意形状(多边形或弧形)的形状面 //quadraticCurveTo() 这是弧形的含函数
  256. var geometry = new THREE.ShapeBufferGeometry( this.getShape(shapes, holes) ); //ShapeGeometry
  257. /* var matrix = new THREE.Matrix4();//将竖直的面变为水平
  258. matrix.set(//z = y
  259. 1, 0, 0, 0,
  260. 0, 0, 0, 0,
  261. 0, 1, 0, 0,
  262. 0, 0, 0, 1
  263. )
  264. geometry.applyMatrix(matrix) */
  265. //geometry.computeVertexNormals();//对于光照需要的是点法线
  266. return geometry;
  267. },
  268. lessCurvePoints: function(points, oldCount, minRad=0.03, UtoTMapArr){//减少点数(拐弯的部分紧凑些,直线部分宽松些):
  269. let count = points.length
  270. let newUtoTMapArr = []
  271. let newPoints = []
  272. let pointIndexs = []
  273. let lastVec
  274. let startTime = performance.now()
  275. /* if(UtoTMapArr){
  276. for(let n=1;n<oldCount-1;n++){
  277. pointIndexs.push( UtoTMapArr.findIndex(e=>e>= n / (oldCount-1) ) )
  278. }
  279. } */
  280. //console.log('cost dur:', performance.now() - startTime )
  281. let nextUtoTIndex = 1
  282. for(let i=0;i<count;i++){
  283. let point = points[i];
  284. let last = points[i-1]
  285. let next = points[i+1]
  286. if(i == 0 || i == count-1 ) {
  287. newPoints.push(point) //直接加入
  288. UtoTMapArr && newUtoTMapArr.push(i == 0 ? 0 : 1)
  289. }else{
  290. let curVec = new THREE.Vector3().subVectors(next,point)
  291. if(!lastVec) lastVec = curVec
  292. if(i>1){// 和上一个加入点的vec之间的夹角如果过大就加入
  293. let reachNextUToT //找出新点中对应原先控制点的index,这些点必须加入拐点,否则会出现控制点偏移path(当它所在部分接近直线时)
  294. while(UtoTMapArr[i] > nextUtoTIndex / (oldCount-1)){//可能多个控制点对应一个点,当控制点很近时
  295. reachNextUToT = true
  296. nextUtoTIndex ++
  297. }
  298. if(/* pointIndexs.includes(i) || */ reachNextUToT || curVec.angleTo(lastVec) > minRad){//最小角度 (注意原始点不能太稀疏)
  299. newPoints.push(point)
  300. UtoTMapArr && newUtoTMapArr.push(UtoTMapArr[i])
  301. lastVec = curVec
  302. }
  303. }
  304. }
  305. }
  306. return {newUtoTMapArr, newPoints}
  307. },
  308. getExtrudeGeo: function(shapes, holes, options={openEnded:false, shapeDontClose:false}){//获得挤出棱柱,可以选择传递height,或者extrudePath
  309. var shape = this.getShape(shapes, holes) //points是横截面 [vector2,...]
  310. if(options.extrudePath ){// 路径 :[vector3,...]
  311. var length = options.extrudePath.reduce((total, currentValue, currentIndex, arr)=>{
  312. if(currentIndex == 0)return 0
  313. return total + currentValue.distanceTo(arr[currentIndex-1]);
  314. },0)
  315. //options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath)
  316. if(options.extrudePath.length == 2){
  317. options.tension = 0 ;//否则一端扭曲
  318. options.steps = 1
  319. }
  320. {//去掉重复的点
  321. let path = []
  322. const minDis = options.dontSmooth ? 0 : 0.2 //CatmullRomCurve3 经常扭曲,如果两个点靠得很近可能会扭曲,这里去除靠的太近的点。但去除后依旧会出现一定扭曲.
  323. options.extrudePath.forEach((p,i)=>{
  324. if(i==0 || i== options.extrudePath.length-1)return path.push(p) //首尾直接加入
  325. let last = path[path.length-1]//和上一个比
  326. let dis = last.distanceTo(p)
  327. if(dis <= minDis){
  328. console.log(`第${i}个点(${p.toArray()})因为和上一个数据(${last.toArray()})太接近(dis:${dis})所以删除`)
  329. }else if(i == options.extrudePath.length - 2){//因为最后一个必定加入,所以倒数第二个还也不能太靠近最后一个
  330. last = options.extrudePath[options.extrudePath.length-1] //和下一个(最后一个比)
  331. if(dis <= minDis){
  332. console.log(`第${i}个点(${p.toArray()})因为和下一个数据(${last.toArray()})太接近(dis:${dis})所以删除`)
  333. }else{
  334. path.push(p)
  335. }
  336. }else{
  337. path.push(p)
  338. }
  339. })
  340. options.extrudePath = path
  341. }
  342. if(!options.dontSmooth){
  343. //平滑连续的曲线(但经常会有扭曲的问题,tension:0能缓解, 另外shape和path都最好在原点附近,也就是点需减去bound.min )
  344. options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath, options.closed , 'catmullrom' /* 'centripetal' */ , options.tension)//tension:张力, 越大弯曲越大。 随着长度增长,该值需要减小,否则会扭曲
  345. if(options.lessPoints !== false ){//曲线但压缩直线部分点数量
  346. options.extrudePath.UtoTMapArr = [] //用于存储 getSpacedPoints得到的点对应points的百分比对应
  347. let count = Math.max(2, Math.round(length* (options.lessSpace || 200) )) //为了防止有大拐弯才设置这么高
  348. let points = options.extrudePath.getSpacedPoints(count-1) //拆分为更密集的点
  349. let result = this.lessCurvePoints(points, options.extrudePath.points.length, options.minRad, options.extrudePath.UtoTMapArr ) //传UtoTMapArr的话点太多了卡住了
  350. //options.extrudePath = points
  351. options.extrudePath = result.newPoints
  352. options.dontSmooth = true
  353. }
  354. }
  355. if(options.dontSmooth){
  356. let curvePath = new THREE.CurvePath()//通用的曲线路径对象,它可以包含直线段和曲线段。在这里只做折线
  357. curvePath.points = options.extrudePath//add
  358. for (let i = 0; i < options.extrudePath.length - 1; i++){
  359. let curve3 = new THREE.LineCurve3(options.extrudePath[i], options.extrudePath[i + 1]);//添加线段
  360. curvePath.add(curve3);
  361. }
  362. options.steps = options.extrudePath.length - 1
  363. options.extrudePath = curvePath
  364. options.tension = 0
  365. //已修改过three,原本会平分细分,现在dontSmooth时会直接按照控制点来分段
  366. }
  367. }
  368. var extrudeSettings = $.extend(options,{
  369. steps: options.steps != void 0 ? options.steps : ( options.extrudePath ? Math.round(length/(options.spaceDis || 0.2)) : 1), //分成几段 spaceDis每段长度
  370. bevelEnabled: false, //不加的话,height为0时会有圆弧高度
  371. //openEnded默认false
  372. })
  373. var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings ); //修改了three.js文件, buildLidFaces处,创建顶底面加了选项,可以选择开口。
  374. return geometry;
  375. /* tension = 0:曲线会变成一条直线,没有弯曲。
  376. tension = 0.5:曲线会经过所有控制点,并保持自然的弯曲。
  377. tension > 0.5:曲线会更平滑,远离控制点之间的路径。
  378. tension < 0.5:曲线会更贴近控制点之间的路径,弯曲更明显。 */
  379. },
  380. getUnPosPlaneGeo : function(){//获取还没有赋值位置的plane geometry
  381. var e = new Uint16Array([0, 1, 2, 0, 2, 3])
  382. // , t = new Float32Array([-.5, -.5, 0, .5, -.5, 0, .5, .5, 0, -.5, .5, 0])
  383. , i = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1])
  384. , g = new THREE.BufferGeometry;
  385. g.setIndex(new THREE.BufferAttribute(e, 1)),
  386. //g.addAttribute("position", new n.BufferAttribute(t, 3)),
  387. g.setAttribute("uv", new THREE.BufferAttribute(i, 2))
  388. return function(){
  389. return g
  390. }
  391. }(),
  392. getPlaneGeo : function(A,B,C,D){
  393. var geo = this.getUnPosPlaneGeo().clone();
  394. var pos = [
  395. A.x, A.y, A.z,
  396. B.x, B.y, B.z,
  397. C.x, C.y, C.z,
  398. D.x, D.y, D.z
  399. ]
  400. //geo.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  401. geo.setAttribute('position', new THREE.Float32BufferAttribute(pos, 3));
  402. geo.computeVertexNormals()
  403. geo.computeBoundingSphere() //for raycaster
  404. return geo;
  405. },
  406. drawPlane : function(A,B,C,D, material){
  407. var wall = new THREE.Mesh(this.getPlaneGeo(A,B,C,D), material);
  408. return wall;
  409. },
  410. movePlane: function(mesh, A,B,C,D){
  411. var pos = new Float32Array([
  412. A.x, A.y, A.z,
  413. B.x, B.y, B.z,
  414. C.x, C.y, C.z,
  415. D.x, D.y, D.z
  416. ])
  417. mesh.geometry.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  418. mesh.geometry.computeBoundingSphere()//for checkIntersect
  419. }
  420. ,
  421. createGeometry:function(posArr, faceArr, uvArr, normalArr ){//创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  422. let geo = new THREE.BufferGeometry;
  423. let positions = [];
  424. posArr.forEach(p=>positions.push(p.x,p.y,p.z));
  425. geo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
  426. if(faceArr){
  427. let indice = []
  428. faceArr.forEach(f=>indice.push(...f));
  429. geo.setIndex(indice) // auto set Uint16BufferAttribute or Uint32BufferAttribute
  430. }
  431. if(uvArr){
  432. let uvs = []
  433. uvArr.forEach(uv=>uvs.push(uv.x,uv.y));
  434. geo.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2))
  435. }
  436. if(normalArr){
  437. let normals = []
  438. normalArr.forEach(n=>normals.push(n.x,n.y,n.z));
  439. geo.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3))
  440. }
  441. /*
  442. geo.computeVertexNormals()
  443. geo.computeBoundingSphere() //for raycaster
  444. */
  445. return geo
  446. },
  447. updateGeometry:function(geo, posArr, faceArr, uvArr, normalArr ){//创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  448. let positions = [];
  449. posArr.forEach(p=>positions.push(p.x,p.y,p.z));
  450. geo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
  451. geo.attributes.position.needsUpdate = true;
  452. if(faceArr){
  453. let indice = []
  454. faceArr.forEach(f=>indice.push(...f));
  455. geo.setIndex(indice) // auto set Uint16BufferAttribute or Uint32BufferAttribute
  456. }
  457. if(uvArr){
  458. let uvs = []
  459. uvArr.forEach(uv=>uvs.push(uv.x,uv.y));
  460. geo.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2))
  461. }
  462. if(normalArr){
  463. let normals = []
  464. normalArr.forEach(n=>normals.push(n.x,n.y,n.z));
  465. geo.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3))
  466. }
  467. /*
  468. geo.computeVertexNormals()
  469. */
  470. geo.computeBoundingSphere() //for raycaster and visi
  471. return geo
  472. }
  473. }
  474. export {LineDraw, MeshDraw} ;