javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)

1 完整代码下载

  https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ  

  提取码 3fzt (压缩包名: 2020-3-24-demo.zip)

  由于是初探3D,对3d对象的构建不太了解, 用此应用试着做了一个马车几何体。。。结果不敢看

  不在更新此应用 。  结束时间 2020-4-1

2 图片展示

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第1张图片

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第2张图片

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第3张图片

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第4张图片

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第5张图片

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第6张图片

 

 

javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第7张图片javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第8张图片javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六)_第9张图片

3 主要代码

  布尔运算后的物体的几何体会自动 导入到 几何体列表选项中, 可自由选配材质 纹理

  挺简单, 都是中文

 

  1 "use strict"
  2 
  3 var View = (function (){
  4     
  5     var _View = function (){
  6         
  7         if(this.__proto__.size === undefined){this.__proto__.size = this.getSize();}
  8         
  9     }
 10     
 11     _View.prototype = {
 12         
 13         constructor: _View, 
 14         
 15         //创建html元素
 16         add: function (fel, elemName, id, cls){
 17             let el = document.createElement(elemName);
 18             if(id){el.setAttribute('id',id);}
 19             if(cls){el.className = cls;}
 20             if(fel){fel.appendChild(el);}
 21             return el;
 22         }, 
 23         
 24         //删除html元素
 25         remove: function (){
 26             let k, arg = arguments, err = [];
 27             for(k = 0; k < arg.length; k++){
 28                 if(this.isEl(arg[k]) === false){err.push(arg[k]); continue;}
 29                 arg[k].parentNode.removeChild(arg[k]);
 30             }
 31             if(err.length > 0){return {err:'这里有一些删除失败的元素', arr:err};}
 32             return true;
 33         }, 
 34 
 35         //id获取html元素
 36         get: function (id){
 37             return document.getElementById(id);
 38         }, 
 39         
 40         //获取可视宽高
 41         getSize: function (){
 42             let w = window.innerWidth ||  document.body.clientWidth || document.documentElement.clientWidth;
 43             let h = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
 44             return {w:w, h:h};
 45         }, 
 46          
 47         //通过parentNode检查元素是否存在于页面中
 48         isEl: function (el){
 49             if(typeof(el) !== 'object'){return false;}
 50             //被删除之后的html元素object的 parentNode等于null
 51             if(!el.parentNode){return false;}
 52             return true;
 53          }, 
 54          
 55         //元素绑定事件
 56         addEvent: function (target, ev, callback){
 57             target.addEventListener(ev, function(e){/* e.preventDefault(); */ if(callback){callback(e);}}, false);
 58             return callback;
 59         }, 
 60         
 61         removeEvent: function (target, ev, func){
 62             target.removeEventListener(ev, func);
 63         }, 
 64         
 65         initBody: function (){
 66             document.body.style.width = this.size.w + "px";
 67             document.body.style.height = this.size.h + "px";
 68             document.body.style.overflow = "hidden";
 69             return this;
 70         }
 71         
 72     }
 73     
 74     return _View;
 75     
 76 })()
 77 
 78 
 79 
 80 /**
 81     限 谷歌 或 火狐 浏览器
 82     依赖 View 类
 83 */
 84 var Gui = (function (){
 85     
 86     //申明新的gui
 87     var _Gui = function (obj, a, b, c, d){
 88         this.timer = 0;
 89         this.info = new Map();
 90         //this.info.set(this.timer, this);
 91         if(this.__proto__.timerAll_old.length !== 0){
 92             this.timerAll = this.__proto__.timerAll_old[0];
 93             this.__proto__.timerAll_old.splice(0, 1);
 94         }else{
 95             this.__proto__.timerAll++;
 96             this.timerAll = this.__proto__.timerAll;
 97         }
 98         this.elem = addBindMove(document.body, 'div', null, 'Gui box-shadown box-scroll-block');
 99         this.__proto__.objAll.set(this.timerAll, this);
100         let dis = this.autoChangeStartPosition === false ? 1 : this.timerAll;
101         this.setPos(15 * dis, 5 * dis, "right");
102         if(typeof(obj) === "object" && Array.isArray(obj) === false){this.create(obj, a, b, c, d);}
103         else{/* console.warn("_Gui: 参数中的对象 格式错误"); */}
104     }
105 
106     _Gui.prototype.objAll = new Map();
107     
108     _Gui.prototype.timerAll = 0;
109     
110     _Gui.prototype.timerAll_old = [];
111     
112     _Gui.prototype.autoChangeStartPosition = true; //自动改变初始位置
113     
114     //创建新的块
115     _Gui.prototype.create = function (obj, a, b, c, d){
116         this.timer++;
117         _start(obj, a, b, c, d, this.timer, this.elem, this.info, this.timerAll, this.objAll);
118         return this;
119     }
120     
121     //往块里添加新的控件
122     _Gui.prototype.add = function (obj, a, b, c, d){
123         _start(obj, a, b, c, d, this.timer, this.elem, this.info, this.timerAll, this.objAll);
124         return this;
125     }
126     
127     //添加 内容变动 回调(change 事件)
128     _Gui.prototype.change = function (){//arr.concat(arr_a, arr_b)
129         var arg = arguments, o = this.info.get(this.timer), tar = o.par.target;
130         var arr = tar.bs.concat(tar.fs, tar.ns, tar.ss, tar.ts, tar.cs), len = arr.length;
131         var arg_t_0 = typeof(arg[0]), call = o.objs.get(o.obj).callback;
132         if(arg_t_0 === "function" && len === 1){
133             call[arr[0]] = arg[0];
134         }else if(arg_t_0 === "string" && typeof(arg[1]) === "function"){
135             call[arg[0]] = arg[1];
136         }else if(arg_t_0 === "function" && len > 1){
137             for(let k = 0; k < len; k++){
138                 call[arr[k]] = arg[0];
139             }
140         }else if(arg_t_0 === "object" && Array.isArray(arg[0]) === false){
141             for(let k in arg[0]){
142                 call[k] = arg[0][k];
143             }
144         }else{
145             console.log("change方法参数错误,添加失败");
146         }
147         //console.log(this.info.get(this.timer).obj);
148         return this;
149     }
150     
151     //修改title
152     _Gui.prototype.title = function (value){
153         if(!this.info.get(this.timer)){console.log("找不到title"); return;}
154         this.info.get(this.timer).title.innerHTML = ""+this.timerAll+""+"."+""+this.timer+""+" "+(value || "");
155         return this;
156     }
157     
158     //修改name
159     _Gui.prototype.name = function (){
160         let o = this.info.get(this.timer), objs;
161         let arg = arguments, typ0 = typeof(arg[0]), typ1 = typeof(arg[1]);
162         if(typeof(arg[2]) === "object" && Array.isArray(arg[2]) === false){objs = o.objs.get(arg[2]);}else{objs = o.objs.get(o.obj);}
163         var tar = objs.parameter.target, nameEl = objs.nameEl;
164         var arr = tar.bs.concat(tar.fs, tar.ns, tar.ss, tar.ts, tar.cs), len = arr.length;
165         
166         var setVal = (el, val)=>{if(!el){console.warn("_Gui.name: 属性不存在");} if(el.value !== undefined){el.value = val;}else if(el.innerHTML !== undefined){el.innerHTML = val;}else{console.log("name修改失败");}}
167         
168         if(typ0 === "string" && typ1 === "undefined" && len === 1){//string
169             setVal(nameEl[arr[0]], arg[0]);
170 
171         }else if(typ0 === "object" && Array.isArray(typ0) === false){//object
172             let k;
173             for(k in arg[0]){
174                 setVal(nameEl[k], arg[0][k]);
175             }
176                 
177         }else if(typ0 === "string" && typ1 === "string" && arg[1] !== "_Gui_func_showStop"){//string, string
178             if(arr.indexOf(arg[0]) === -1 || !nameEl[arg[0]]){console.log("name修改失败,视图结构发生错误,请修复"); return;}
179             setVal(nameEl[arg[0]], arg[1]);
180             
181         }else if(typ0 === "string" && arg[1] === "_Gui_func_showStop" && typeof(arg[2]) === "object"){
182             if(nameEl[arg[0]] === undefined){console.log("showStop_name: 错误"); return;}
183             if(arg[3] === false){
184                 nameEl[arg[0]].style.color = "#2F4F4F";
185             }else{
186                 nameEl[arg[0]].style.color = "red";
187             }
188             
189             
190         }else{
191             console.log("name方法参数错误,添加失败");
192         }
193             
194         return this;
195     }
196     
197     //获取当前view对象
198     _Gui.prototype.getView = function (){
199         return tar;
200     }
201     
202     //设置 gui视图位置
203     _Gui.prototype.setPos = function (x, y, dirX, dirY){
204         
205         let dirx = dirX || "left", diry = dirY || "top";
206 
207         if(dirx === "left" && this.elem.bindMove.style.right !== ""){
208             this.elem.bindMove.style.right = "";
209         }
210         else if(dirx === "right" && this.elem.bindMove.style.left !== ""){
211             this.elem.bindMove.style.left = "";
212         }
213         
214         if(diry === "top" && this.elem.bindMove.style.bottom !== ""){
215             this.elem.bindMove.style.bottom = "";
216         }
217         else if(diry === "bottom" && this.elem.bindMove.style.top !== ""){
218             this.elem.bindMove.style.top = "";
219         }
220         
221         if(x !== undefined) this.elem.bindMove.style[dirx] = x+"px";
222         if(y !== undefined) this.elem.bindMove.style[diry] = y+"px";
223         _setElemPos(this.elem);
224         
225         return this;
226         
227     }
228     
229     //隐藏gui
230     _Gui.prototype.display = function (val){
231         if(!this.elem){console.log("display, elem不存在"); return this;}
232         if(val !== "block" && val !== "none"){console.log("display 参数错误"); return this;}
233         this.elem.bindMove.style.display = val;
234         this.elem.style.display = val;
235         return this;
236     }
237     
238     //关闭gui(默认关闭整个Gui)
239     _Gui.prototype.close = function (object){
240         var o;
241         if(!object){
242             let k;
243             for(k = 1; k <= this.timer; k++){
244                 o = this.info.get(k);
245                 o.hide = true;
246                 hide(o.line, o.fel, this.elem, this.info, true);
247             }
248         }else{
249             o = this.info.get(object.timer);
250             o.hide = true;
251             hide(o.line, o.fel, this.elem, this.info, true);
252         }
253         return this;
254     }
255     
256     //标记不可用项
257     _Gui.prototype.showStop = function (){
258         
259         this.name(arguments[0], "_Gui_func_showStop", arguments[1], arguments[2]);
260         
261         return this;
262         
263     }
264     
265     //移除gui
266     _Gui.prototype.remove = function (object){
267         var o = object ? object : this;
268         this.__proto__.timerAll_old.push(o.timerAll);
269         this.__proto__.objAll.delete(o.timerAll);
270         o.objAll.delete(o.timerAll);
271         tar.remove(o.elem.bindMove, o.elem);
272         delete(o.timerAll);
273         delete(o.elem);
274         delete(o.info);
275         delete(o.timer);
276         return;
277     }
278     
279     //使某个gui获得焦点(层级变为最上层)
280     _Gui.prototype.focus = function (object){
281         let o = object || this;
282         if(!o.elem || !o.elem.bindMove){console.warn("_Gui: 获取焦点失败");}
283         _zIndex(o.elem);
284         return this;
285     }
286     
287     
288     var tar = new View(), tar_zIndex = {}, _osTitle = null;
289 
290     //创建视图
291     var _start = function (obj, a, b, c, d, id, felem, map, timerAll, objAll){
292             
293             var fel, line, title, m = map.get(id), k, len, _name, isNewObj = false;
294             
295             //确认追加 obj
296             if(m){
297                 fel = m.fel;
298                 if(!obj){
299                     obj = m.obj;
300                 }else{
301                     if(m.objs.has(obj) === false) isNewObj = true;
302                     m.obj = obj;
303                 }
304             }
305 
306             if(typeof(obj) !== "object" || !obj){console.log("引用对象错误, 新建块对象为必须"); return;}
307             
308             //确认参数 (target, title, isBind, range || select) || a = {target, title, isBind, range || select}
309             var os = {}, nos = [];
310             if(a !== undefined){nos.push(_getispro(obj, a, nos));}
311             if(b !== undefined){nos.push(_getispro(obj, b, nos));}
312             if(c !== undefined){nos.push(_getispro(obj, c, nos));}
313             if(d !== undefined){nos.push(_getispro(obj, d, nos));}
314             len = nos.length;
315             for(k = 0; k < len; k++){
316                 if(nos[k] === undefined){
317                     if(typeof(a) === "object" && Array.isArray(a) === false){os = a;}
318                 }else{
319                     let val;
320                     switch(k){
321                         case 0 : val = a; break;
322                         case 1 : val = b; break;
323                         case 2 : val = c; break;
324                         case 3 : val = d; break;
325                         default : break;
326                     }
327                     if(val !== undefined){os[nos[k]] = val;}
328                 }
329             }
330             //console.log(Object.getOwnPropertyDescriptor(obj, "x"));
331             //确认对象属性 os.target (target 如果为obj 则表示 只设置gui, 不添加控件)
332             var arr = [], T = typeof(os.target), A = Array.isArray(os.target);
333             if(!os.target){for(k in obj){arr.push(k);}}
334             else if(A === true){arr = os.target;}
335             else if(T !== "object"){arr.push(os.target);}
336             else{return;}
337             //boolean, function, number, text, select, color
338             var bs = [], fs = [], ns = [], ts = [], cs = [], ss = [];
339             if(Array.isArray(os.select) == true && arr.length === 1){
340                 ss.push(arr[0]);
341             }else if(typeof(os.select) === "object" && Array.isArray(os.select) == false){
342                 let ks;
343                 for(ks in os.select){
344                     len = arr.length;
345                     for(k = 0; k < len; k++){
346                         if(ks === arr[k]){ss.push(arr[k]); arr.splice(k, 1);}
347                     }
348                 }
349             }
350             len = arr.length;
351             for(k = 0; k < len; k++){
352                 T = typeof(obj[arr[k]]);
353                 if(T === "boolean"){bs.push(arr[k]);}
354                 else if(T === "function"){fs.push(arr[k]);}
355                 else if(T === "number"){ns.push(arr[k]);}
356                 else if(T === "string"){
357                     if(obj[arr[k]].length === 7 && obj[arr[k]].charAt(0) === "#"){cs.push(arr[k]);}//color
358                     else{ts.push(arr[k]);}//string
359                 }
360             }
361             var bs_len = bs.length, fs_len = fs.length, ns_len = ns.length, ts_len = ts.length, ss_len = ss.length, cs_len = cs.length;
362             var lens = bs_len + fs_len + ns_len + ts_len + ss_len + cs_len;
363             
364             //确认 绑定
365             var isB = false;
366             if(typeof(os.isBind) === "boolean"){isB = os.isBind;}
367             
368             //确认 _name
369             if(os.title && lens === 1){_name = os.title; delete(os.title);}
370             
371             //确认 新的块
372             var par = {target:{bs:bs, fs:fs, ns:ns, ts:ts, cs:cs, ss:ss}, select:os.select, range:os.range, title:os.title, isBind:os.isBind};
373             if(!m){
374                 isNewObj = false;
375                 line = _line(id, felem);
376                 fel = _cons(line, id, felem, map);
377                 title = _title(timerAll, id, _osTitle || os.title, fel);//os.title
378                 _osTitle = null;
379                 map.set(id, {
380                     hide : false,
381                     line : line, 
382                     fel : fel, 
383                     title : title, 
384                     obj : obj, 
385                     par : par,
386                     objs : new Map([[obj, {
387                         parameter : par,
388                         callback : {},
389                         nameEl : {}
390                     }]])
391                 });
392                 m = map.get(id);
393             }
394             
395             //更新 obj
396             if(isNewObj === true){
397                 m.objs.set(obj, {
398                     parameter : par,
399                     callback : {},
400                     nameEl : {}
401                 });
402             }
403             
404             //更新参数
405             m.par = par;
406             var objs_g = m.objs.get(obj), pars = objs_g.parameter;
407             for(k in os){if(k !== "target"){pars[k] = os[k];}}
408             for(k = 0; k < bs_len; k++){if(pars.target.bs.indexOf(bs[k]) === -1){pars.target.bs.push(bs[k]);}}
409             for(k = 0; k < fs_len; k++){if(pars.target.fs.indexOf(fs[k]) === -1){pars.target.fs.push(fs[k]);}}
410             for(k = 0; k < ns_len; k++){if(pars.target.ns.indexOf(ns[k]) === -1){pars.target.ns.push(ns[k]);}}
411             for(k = 0; k < ts_len; k++){if(pars.target.ts.indexOf(ts[k]) === -1){pars.target.ts.push(ts[k]);}}
412             for(k = 0; k < ss_len; k++){if(pars.target.ss.indexOf(ss[k]) === -1){pars.target.ss.push(ss[k]);}}
413             for(k = 0; k < cs_len; k++){if(pars.target.cs.indexOf(cs[k]) === -1){pars.target.cs.push(cs[k]);}}
414 
415             //console.log(objs_g.callback);
416             //创建视图//os.select os.range os.isBind
417             let che, cli, ran, tex, col, sel;
418             if(bs_len > 0){ che = _check(obj, bs, fel, isB, objs_g.callback, _name); for(k in che.nameEl){objs_g.nameEl[k] = che.nameEl[k];} }
419             if(ts_len > 0){ tex = _text(obj, ts, fel, isB, objs_g.callback, _name); for(k in tex.nameEl){objs_g.nameEl[k] = tex.nameEl[k];} }
420             if(cs_len > 0){ col = _color(obj, cs, fel, isB, objs_g.callback, _name); for(k in col.nameEl){objs_g.nameEl[k] = col.nameEl[k];} }
421             if(ss_len > 0){ sel = _select(obj, ss, os.select, fel, isB, objs_g.callback, _name); for(k in sel.nameEl){objs_g.nameEl[k] = sel.nameEl[k];} }
422             if(ns_len > 0){ ran = _range(obj, ns, os.range || {}, fel, isB, objs_g.callback, timerAll, id, _name); for(k in ran.nameEl){objs_g.nameEl[k] = ran.nameEl[k];} }
423             if(fs_len > 0){ cli = _click(obj, fs, fel, objs_g.callback, _name); for(k in cli.nameEl){objs_g.nameEl[k] = cli.nameEl[k];} }
424             return {nowObject:obj};
425     }
426         
427         //验证 并 获取 _start 参数
428         var _getispro = function (obj, cons, nos){
429             var o_t = typeof(cons), o_a = Array.isArray(cons), r;
430             if(o_t === "string"){
431                 if(obj[cons] !== undefined){
432                     r = "target";
433                 }else{
434                     r = "title";
435                 }
436                 
437             }else if(o_t === "boolean"){
438                 r = "isBind";
439                 
440             }else if(o_t === "object"){
441                 let k, len, isT = (arr, type)=>{
442                     let ct = true;
443                     len = cons.length;
444                     for(k = 0; k < len; k++){if(typeof(cons[k]) !== type){ct = false; break;}}
445                     return ct;
446                 }
447                 if(o_a === true){
448                     if(isT(cons, "string") === true){r = "target";}
449                     else if(isT(cons, "number") === true && (cons.length === 3 || cons.length === 0) && cons[0] < cons[1] && /* cons[2] < cons[1] &&  */cons[2] > 0){r = "range";}
450                     else{console.log("忽略了参数");}
451                 }else{
452                     let isArr = true;
453                     for(k in cons){if(Array.isArray(cons[k]) === false){isArr = false; break;}}
454                     if(isArr === true){
455                         let ka, isN; 
456                         for(k in cons){
457                             len = cons[k].length;
458                             if(len === 0 || len === 3){
459                                 for(ka = 0; ka < len; ka++){
460                                     if(typeof(cons[k][ka]) !== "number" || isNaN(cons[k][ka]) === true){isN = false; break;}
461                                 }
462                                 if(typeof(obj[k]) !== "number"){isN = false;}
463                                 
464                                 if(isN !== false && len === 3 && (obj[k] < cons[k][0] || obj[k] > cons[k][1] || cons[k][0] > cons[k][1] || cons[k][2] > cons[k][1] || cons[k][2] < 0)){isN = false;}
465                             }else{
466                                 isN = false;
467                                 break;
468                             }
469                         }
470                         if(isN === false){r = "select";}else{r = "range";}//数组长度为空也判定为 range, 因为range 有默认值
471                     }else{
472                         let isSel = true;
473                         for(k in cons){if(obj[k] === undefined){isSel = false; break;}}
474                         if(isSel === true){r = "select";}else{console.log("忽略了参数");}
475                     }
476                 }
477             }
478             
479             if(nos.indexOf(r) !== -1){console.log("重复了参数"); return;}
480             
481             return r;
482         }
483         
484         //隐藏视图
485         var hide = function (l, f, elem, map, isHide){
486             elem.bindMoveIsHideAll = false;
487             if(isHide === false){
488                 l.className = "line-block"; 
489                 f.style.display = "block";
490                 elem.className = "Gui box-shadown box-scroll-block";
491                 elem.bindMove.className = "bindMove_elemCla-up";
492             }else{
493                 l.className = "line-none"; 
494                 f.style.display = "none"; 
495                 let isAll = true, con, k, len = map.size;
496                 for(k = 1; k <= len; k++){
497                     con = map.get(k).fel.style.display;
498                     if(con === "" || con === "block"){isAll = false; break;}
499                 }
500                 if(isAll === true){
501                     elem.bindMoveIsHideAll = true;
502                     elem.className = "Gui-none box-shadown box-scroll-block";
503                     elem.bindMove.className = "bindMove_elemCla-hidden";
504                 }
505             }
506             _setElemPos(elem);
507         }
508         
509         //调整 son(this.elem)的位置
510         var _setElemPos = function (son, father){
511             if(!father){father = son.bindMove;}
512             let s = 0;
513             if(son.bindMoveIsHideAll === true) s = 10;
514             //son.style.zIndex = "2"; father.style.zIndex = "1"; 
515             son.style.left = father.offsetLeft-(son.clientWidth || son.offsetWidth)+(father.clientWidth || father.offsetWidth) +"px";
516             son.style.top = father.offsetTop+(father.clientHeight || father.clientHeight)+ s -1 +"px";
517         }
518         
519         //添加 内容 容器
520         var _cons = function (line, id, fel, map){
521             var f = tar.add(fel, "div", null, "Gui-content"), di;
522             tar.addEvent(line, 'click', (e)=>{
523                 di = map.get(id);
524                 di.hide = !di.hide;
525                 hide(line, f, fel, map, di.hide);
526             });
527             return f;
528         }
529         
530         //添加 标题 ← ↑ → ↓ ↖ ↙ ↗ ↘ ↕
531         var _title = function (timerAll, id, title, fel){
532             var tf = tar.add(fel, "div");
533             var t = tar.add(tf, "p");
534             //var ts = tar.add(tf, "p");
535             t.innerHTML = ""+timerAll+""+"."+""+id+""+" "+(title || "");
536             //ts.style = "height:5px;";
537             return t;
538         }
539         
540         //添加 分块线
541         var _line = function (id, fel){
542             var toper = id === 1 ? 0 : 10;
543             var l = tar.add(fel, 'p', null, "line-block");
544             l.style= "cursor:pointer; margin-top:" + toper + "px";
545             return l;
546         }
547         
548         var _zIndex = function (son, father){
549             let f = father || son.bindMove;
550             if(tar_zIndex.move && tar_zIndex.elem){tar_zIndex.move.style.zIndex = "1"; tar_zIndex.elem.style.zIndex = "1";}
551             tar_zIndex.move = f; tar_zIndex.elem = son;
552             tar_zIndex.move.style.zIndex = "2"; tar_zIndex.elem.style.zIndex = "2";
553         }
554         
555         //创建 绑定 可移动 的html元素
556         var addBindMove = function (fel, elemName, id, cls){
557             var father = tar.add(fel, "div", null, "bindMove_elemCla-up");
558             var son = tar.add(fel, elemName, id, cls);
559 
560             var isMove = false, sx, sy, tar_input, k, len, path;
561             
562             //初始化 father 位置
563             var getFatherPosition = function (){
564                 if(!son.offsetLeft || !(son.clientWidth || son.offsetWidth) || !(father.clientWidth || father.offsetWidth)){
565                     setTimeout(()=>{getFatherPosition(); _setElemPos(son);}, 500);
566                     console.log("调整father位置");
567                     return;
568                 }
569                 father.style.left = son.offsetLeft + (son.clientWidth || son.offsetWidth) - (father.clientWidth || father.offsetWidth) +"px";
570             }
571             
572             //更新 zIndex
573             var setzIndex = function (e){
574                 path = e.path || (e.composedPath && e.composedPath());
575                 len = path.length;
576                 for(k = 0; k < len; k++){
577                     if(path[k].className === "bindMove_elemCla-up" || path[k].className === "bindMove_elemCla-down" || path[k].className === "bindMove_elemCla-hidden" || path[k].className === "Gui box-shadown box-scroll-block" || path[k].className === "Gui-none box-shadown box-scroll-block"){
578                         _zIndex(son, father);
579                         break;
580                     }
581                 }
582             }
583             tar.addEvent(son, 'click', (e)=>{
584                 setzIndex(e);
585                 //if(e.target.type !== undefined){tar_input = e.target; e.target.focus();}else if(tar_input){tar_input.blur();}
586             });
587             
588             //移动
589             var down = tar.addEvent(father, 'mousedown', (e)=>{
590                 setzIndex(e);
591                 if(e.target.className === "bindMove_elemCla-up" || e.target.className === "bindMove_elemCla-hidden"){
592                     sx = e.offsetX; sy = e.offsetY;
593                     if(father.className === "bindMove_elemCla-up") father.className = "bindMove_elemCla-down";
594                     isMove = true;
595                 }
596             });
597             var up = tar.addEvent(father, 'mouseup', (e)=>{
598                 isMove = false;
599                 if(father.className === "bindMove_elemCla-down") father.className = "bindMove_elemCla-up";
600                 tar.removeEvent(father, 'mousedown', down);
601                 tar.removeEvent(document.body, 'mousemove', move);
602                 tar.removeEvent(father, 'mouseup', up);
603             });
604             var move = tar.addEvent(document.body, 'mousemove', (e)=>{
605                 if(isMove === true){
606                     father.style.left = e.clientX - sx +"px";
607                     father.style.top = e.clientY - sy +"px";
608                     _setElemPos(son, father);
609                 }
610             });
611             
612             son.bindMove = father;
613             son.bindMoveIsHideAll = false;
614             //getFatherPosition();
615             return son;
616         }
617         
618         var _view = function (obj, arr, fel, isBind, type, name, clas, event_fun, bind_fun){
619             
620             var p = tar.add(fel, 'p'), info = {p:p, nameEl:{}}, k, len = arr.length, vn = "value", cla = clas || "p-float-"+type;
621             var nameer;
622             if(type === "checkbox"){vn = "checked";}
623             
624             var create = (val)=>{
625                 let _val = obj[val];
626                 let f = tar.add(p, 'p', null, cla);
627                 let i = tar.add(f, 'input');
628                 let fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";
629                 let s = tar.add(f, 'span');
630                 fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";
631                 nameer = val;
632                 if(type === "color"){nameer = _val;}
633                 i.type = type;
634                 i[vn] = _val;
635 
636                 s.innerHTML = name || nameer+"";
637                 
638                 tar.addEvent(i, 'change', (e)=>{
639                     _val = e.target[vn];
640                     if(!isBind) obj[val] = _val;
641                     if(type === "color") s.innerHTML = _val;
642                     if(typeof(event_fun[val]) === "function") event_fun[val](e);
643                 });
644 
645                 //bind(obj, arr[k], _val, (now)=>{el_f.i.checked = now;});
646                 if(isBind === true){
647                     Object.defineProperty(obj, val, {
648                         get(){return _val;},
649                         set(v){
650                             _val = v;
651                             i[vn] = v;
652                             if(typeof(bind_fun) === "function"){bind_fun(v);}
653                         }
654                     });
655                 }
656                 
657                 info.nameEl[val] = s;
658             }
659 
660             for(k = 0; k < len; k++){create(arr[k]);}
661             
662             return info;
663         }
664         
665         //添加 text输入框(string)
666         var _text = function (obj, arr, fel, isBind, callbacks, name){
667             return _view(obj, arr, fel, isBind, "text", name, "p-text", callbacks);
668         }
669         
670         //添加 复选框(boolean)
671         var _check = function (obj, arr, fel, isBind, callbacks, name){
672             return _view(obj, arr, fel, isBind, "checkbox", name, null, callbacks);
673         }
674         
675         //添加 下拉选项框()
676         var _select = function (obj, arr, info, fel, isBind, callbacks, name){
677             //
678             var infos = {nameEl:{}}, k, len = arr.length;
679             
680             var create = (val, cons)=>{
681                 let _val = obj[val];
682                 let p = tar.add(fel, 'p');
683                 let f = tar.add(p, 'p', null, "p-float-select");
684                 let i = tar.add(f, "select");
685                 let fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";
686                 let s = tar.add(f, 'span'); s.innerHTML = name || val;
687                 fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";
688                 let ka, lena, T = typeof(cons), A = Array.isArray(cons);
689                 if(T === "object" && A === false){
690                     for(ka in cons){
691                         let opt = tar.add(i, "option");
692                         opt.value = cons[ka];
693                         opt.innerHTML = ka;
694                     }
695                 }else if(A === true){
696                     lena = cons.length;
697                     for(ka = 0; ka <  lena; ka++){
698                         if(Array.isArray(cons[ka]) === true && cons[ka].length === 2){
699                             let opt = tar.add(i, "option");
700                             opt.value = cons[ka][1];
701                             opt.innerHTML = cons[ka][0];
702                             continue;
703                         }
704                         let opt = tar.add(i, "option");
705                         opt.value = cons[ka];
706                         opt.innerHTML = cons[ka];
707                     }
708                 }
709                 tar.addEvent(i, 'change', (e)=>{
710                     if(typeof(callbacks[val]) === "function") callbacks[val](e);
711                 });
712                 
713                 infos.nameEl[val] = s;
714             }
715             
716             if(len === 1){
717                 if(typeof(info) === "object"){
718                     create(arr[0], info[arr[0]]);
719                 }else{
720                     create(arr[0], info);
721                 }
722             }else{
723                 for(k = 0; k < len; k++){
724                     create(arr[k], info[arr[k]]);
725                 }
726             }
727             
728             return infos;
729         }
730         
731         //添加 颜色选择器
732         var _color = function (obj, arr, fel, isBind, callbacks, name){
733             return _view(obj, arr, fel, isBind, "color", name, null, callbacks);
734         }
735         
736         //添加 按钮(function)
737         var _click = function (obj, arr, fel, callbacks, name){
738             var p = tar.add(fel, 'p'), info = {p:p, nameEl:{}}, k, len = arr.length, ends = [];
739             var create = (val)=>{
740                 let f = tar.add(p, 'p', null, "p-float-button");
741                 let i = tar.add(f, 'input');
742                 i.type = "button";
743                 i.value = name || val;
744                 tar.addEvent(i, 'click', ()=>{
745                     obj[val]();
746                     if(typeof(callbacks[val]) === "function"){callbacks[val](e);}
747                 });
748                 info.nameEl[val] = i;
749             }
750             for(k = 0; k < len; k++){create(arr[k]);}
751             return info;
752         }
753         
754         //添加 计量控制器(number) info: object 可选 默认[min, max, step]
755         //注意: number属性的初始值不能 小于min 和 大于max; step不能大于max-min 否则会被判定为 下拉选项框 的参数
756         var _range = function (obj, arr, info, fel, isBind, callbacks, timerAll, id, name){
757             var create = (val)=>{
758                 let c = info[val] || di;
759                 if(obj[val] < c[0] || obj[val] > c[1] || typeof(obj[val]) !== "number" || isNaN(obj[val]) === true){return;}
760                 let p = tar.add(fel, 'p'), i = tar.add(p, 'input');
761                 i.type = "range"; i.value = obj[val]; i.min = c[0]; i.max = c[1]; i.step = c[2];
762                 let nul = tar.add(p, 'span'); nul.innerHTML = " ";
763                 let is = tar.add(p, 'input'); is.type = "tel"; is.value = obj[val];
764                 let key = false, x, xs, spva = name || val, s = tar.add(p, 'span'); s.innerHTML = "" + spva;
765                 let _val = obj[arr[k]];
766                 
767                 let getNum = (num)=>{
768                     //if(num === _val){return _val;}
769                     if(typeof(num) !== "number" || isNaN(num) === true){
770                         return _val;
771                     }
772                     if(num > c[0] && num < c[1]){
773                         return num;
774                     }else if(num > c[0]){
775                         return c[1];
776                     }else if(num < c[1]){
777                         return c[0];
778                     }
779                     return _val;
780                 }
781                 
782                 let setNum = (num, e)=>{
783                     if(num !== undefined){
784                         i.value = num;
785                         is.value = num;
786                         _val = num;
787                         if(!isBind){obj[val] = _val;}
788                         if(typeof(callbacks[val]) === "function"){callbacks[val](_val);}
789                     }
790                 }
791                 
792                 tar.addEvent(is, 'blur', (e)=>{setNum(getNum(Math.round(Number(e.target.value)/c[2])*c[2]), e);});
793                 tar.addEvent(i, 'change', (e)=>{
794                     setNum(getNum(e.target.valueAsNumber), e);
795                 });
796 
797                 if(isBind === true){
798                     Object.defineProperty(obj, arr[k], {
799                         get() {return _val;},
800                         set(v) {
801                             _val = getNum(Math.round(Number(v)/c[2])*c[2]);
802                             i.value = _val;
803                             is.value = _val;
804                         }
805                     });
806                 }
807                 infos.nameEl[val] = s;
808             }
809             var di = [0, 100, 1], k, len = arr.length, infos = {p:null, nameEl:{}};
810             if(Array.isArray(info) === true){di = info;}
811             for(k = 0; k < len; k++){create(arr[k]);}
812             return infos;
813         }
814 
815     return _Gui;
816 
817 })()
View.js
   1 "use strict"
   2 
   3 ;(function (){
   4     
   5     //是否支持WebGL
   6     if(WEBGL.isWebGLAvailable() === false){
   7         document.body.appendChild(WEBGL.getWebGLErrorMessage());
   8         return;
   9     }
  10     
  11     THREE.Cache.enabled = true;//加载器启用缓存
  12     
  13     Gui.prototype.autoChangeStartPosition = false; //不自动改变初始位置
  14     
  15     var _view = new View().initBody();
  16     var _width = _view.size.w;
  17     var _height = _view.size.h;
  18     var _minDistance = 0.1;
  19     var _maxDistance = 5000;
  20     
  21     
  22     //three
  23     var _Three = function (){}
  24     
  25     Object.assign(_Three.prototype, {
  26         
  27         constructor: _Three,
  28         
  29         depthMaterial: new THREE.MeshDepthMaterial({depthPacking: THREE.RGBADepthPacking}),
  30         
  31         createScene: function (bg, fog){//场景
  32             let scene = new THREE.Scene();
  33             if(typeof(bg) === "number"){scene.background = bg;}
  34             else if(Array.isArray(bg) === true){
  35                 scene.background = new THREE.CubeTextureLoader()
  36                 .setPath('img/cube/skyboxsun25deg/')
  37                 .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
  38             }
  39             if(fog) scene.fog = new THREE.Fog(fog.color, fog.near, fog.far);
  40             return scene;
  41         },
  42         
  43         createCamera: function (fov, width, height, near, far){//相机
  44             let w = width === undefined ? _width : width;
  45             let h = height === undefined ? _height : height;
  46             let camera = new THREE.PerspectiveCamera(fov || 45, w / h, near || _minDistance, far || _minDistance * 1000);
  47             camera.position.set(0, 0, _maxDistance * 0.001);
  48             camera.lookAt( 0, 0, 0 );
  49             return camera;
  50         },
  51         
  52         createRenderer: function (felem, width, height, antialias, lights, shadow, checkShaderErrors){//渲染器
  53             let fel = felem || document.body;
  54             let renderer = new THREE.WebGLRenderer({
  55                 antialias : antialias || false, //抗割齿
  56                 powerPreference:"high-performance" //选择高性能GPU渲染
  57             });
  58             renderer.setSize(width || _width, height || _height);
  59             renderer.setPixelRatio(window.devicePixelRatio);
  60             renderer.gammaFactor = 2.2; //着色校正
  61             renderer.physicallyCorrectLights = lights || false; //使其精确照明
  62             renderer.shadowMap.enabled = shadow || false; //渲染阴影
  63             renderer.debug.checkShaderErrors = checkShaderErrors || false; //
  64             if(!renderer.extensions.get('WEBGL_depth_texture')){console.log("深度纹理扩展获取失败:WEBGL_depth_texture");}
  65             fel.appendChild(renderer.domElement);
  66             return renderer;
  67         },
  68         
  69         addLinghts: function (scene, hc){//灯光
  70             let a = new THREE.AmbientLight(0x696969);//环境光(无处不在的光,太阳光)
  71             
  72             let b = new THREE.DirectionalLight(0xFFFFFF, 1);//平行光(产生阴影的光)
  73             b.position.set(0, 50, 50);//位置
  74             b.castShadow = true;// 产生动态阴影
  75             //b.target = Object3D; //平行光的方向是从它的位置到目标位置。默认的目标位置为原点 (0,0,0)。
  76             b.shadow.radius = 1;//使阴影边缘变模糊
  77             b.shadow.bias = 0.0001;
  78             b.shadow.mapSize.width = 1024;//阴影质量w
  79             b.shadow.mapSize.height = 1024;//阴影质量h
  80             
  81             //下面属性默认不自动更新
  82         /*     let l_d = 20; //光照区域的大小 100 * 100
  83             b.shadow.camera.left = -l_d;
  84             b.shadow.camera.right = l_d;
  85             b.shadow.camera.top = l_d;
  86             b.shadow.camera.bottom = -l_d; */
  87             b.shadow.camera.near = 0.1;//最近
  88             b.shadow.camera.far = 100;//最远
  89             
  90             
  91             /* var helperShadow = new THREE.CameraHelper(b.shadow.camera);
  92             scene.add(a, b, helperShadow);
  93             var c = ()=>{()=>{helperShadow.update(); hc.update(); }}
  94             new Gui(b.position, ["x", "y", "z"], [-2500, 2500, 1]).change(c)
  95             .add(b.shadow, "radius", [-1, 1, 0.1]).change(c)
  96             .add(b.shadow.mapSize, ["width", "height"], [0, 2048, 1]).change(c)
  97             .title("调试灯光"); */
  98             scene.add(a, b);
  99             return [a, b];
 100         },
 101         
 102         addControls: function (scene, camera, renderer, children, hc){//控件
 103 
 104             //拖放控件
 105             let drag = new THREE.DragControls(children, camera, renderer.domElement);
 106             //drag.addEventListener('hoveron', (e)=>{this.addTarget(e.object);});
 107             drag.enabled = false;
 108             //this.dragcontrols = dc;
 109             
 110             //轨道控件
 111             let orbit = new THREE.OrbitControls(camera, renderer.domElement);
 112             orbit.target = new THREE.Vector3(0, 0, 0);//控件焦点
 113             //orbit.minPolarAngle = Math.PI * 0.3;//向上最大角度
 114             //orbit.maxPolarAngle = Math.PI * 0.4;//向下最大角度
 115             orbit.minDistance = _minDistance;//最小距离
 116             orbit.maxDistance = _maxDistance;//最大距离
 117             orbit.autoRotateSpeed = 10;//自动旋转速度
 118             //orbit.panSpeed = 100;//鼠标旋转速度
 119             orbit.enableZoom = true;//是否启用缩放
 120             orbit.enableKeys = true;//是否启用键盘
 121             orbit.panSpeed = 1;//鼠标平移速度
 122             orbit.keyPanSpeed = 100;//按键平移的速度
 123             orbit.keys.LEFT = 65;//key a左
 124             orbit.keys.UP = 87;//key w前
 125             orbit.keys.RIGHT = 68;//key d右
 126             orbit.keys.BOTTOM = 83;//key s后
 127             orbit.addEventListener("change", ()=>{this.render(scene, camera, renderer);});
 128             
 129             
 130             //平移控件
 131             var transform = new THREE.TransformControls(camera, renderer.domElement);
 132             transform.addEventListener( 'dragging-changed', (e)=>{orbit.enabled = !e.value;});
 133             transform.size = 1;
 134             scene.add(transform);
 135             
 136             return {drag: drag, orbit: orbit, transform: transform};
 137         },
 138         
 139         updateGeometry: function (mesh, geometry){//更换几何体
 140             if(!mesh || !geometry){
 141                 console.log("_Three: 几何体更换失败"); 
 142                 return;
 143             }
 144             if(mesh.HandCreate.wireframe){
 145                 mesh.HandCreate.wireframe.geometry.dispose();
 146                 mesh.HandCreate.wireframe.geometry = new THREE.WireframeGeometry(geometry);
 147             }
 148             mesh.geometry.dispose();
 149             mesh.geometry = geometry;
 150         },
 151         
 152         updateMaterial: function (mesh, material){//更换材质
 153             if(!mesh || !material){
 154                 console.log("_Three: 材质更换失败"); 
 155                 return;
 156             }
 157             let newMat = material.clone(true);
 158             //newMat.color.copy(mesh.material.color);
 159             newMat.transparent = true;
 160             if(mesh.material.map !== null){this.updateTexture(newMat, mesh.material.map);}
 161             mesh.material.dispose();
 162             mesh.material = newMat;
 163         },
 164         
 165         updateTexture: function (material, texture){//更换纹理
 166             if(!material || !texture){
 167                 console.log("_Three: 纹理更换失败"); 
 168                 return;
 169             }
 170             let map = new THREE.Texture(texture.image);
 171             map.wrapS = THREE.RepeatWrapping;
 172             map.wrapT = THREE.RepeatWrapping;
 173             map.repeat.set(1, 1);
 174             map.minFilter = THREE.NearestFilter;
 175             map.magFilter = THREE.NearestFilter;
 176             if(material.map !== null){
 177                 map.wrapS = material.map.wrapS;
 178                 map.wrapT = material.map.wrapT;
 179                 map.repeat.copy(material.map.repeat);
 180                 map.anisotropy = material.map.anisotropy;
 181                 material.map.dispose();
 182             }
 183             material.map = map;
 184             material.map.needsUpdate = true;
 185             material.needsUpdate = true;
 186         },
 187         
 188         getBox3: function (mesh){//获取Box3
 189             mesh.geometry.computeBoundingBox();//计算mesh获取box3对象
 190             return mesh.geometry.boundingBox.applyMatrix4(mesh.matrixWorld);
 191         },
 192         
 193         render: function (scene, camera, renderer){//渲染
 194             renderer.render(scene, camera);
 195         },
 196 
 197         getBSP: function (meshA, meshB, type){//剪裁 添加 重合
 198             if(!meshA || !meshB || !type || meshA === meshB){console.log("getBSP:参数错误, 请选择1至2个物体进行运算"); return;}
 199             if(!meshA.geometry || !meshB.geometry) return;
 200             if(meshA.geometry.isGeometry !== true || meshB.geometry.isGeometry !== true) return;
 201             let bsp_a = new ThreeBSP(meshA);//生成ThreeBSP对象
 202             let bsp_b = new ThreeBSP(meshB);//生成ThreeBSP对象
 203             let bsp = bsp_a[type](bsp_b);//进行 type 计算
 204             let geo = bsp.toGeometry();//console.log(bsp);
 205             geo.computeFaceNormals();//更新geo的面
 206             geo.computeVertexNormals();//更新geo的顶点
 207             return geo;
 208         },
 209         
 210         toBuffer: function (geometry){//几何体 转为缓存几何体
 211             if(geometry.isGeometry !== true) return;
 212             return new THREE.BufferGeometry().fromGeometry(geometry);
 213         },
 214         
 215         loadingGLTF: function (url, scene){//导入
 216             if(!this.loadGLTF){this.__proto__.loadGLTF = new THREE.GLTFLoader();}
 217             if(!scene) return;
 218             this.loadGLTF.load(url, (gltf)=>{
 219                 scene.add(gltf.scene);
 220             });
 221         },
 222         
 223         exporterGLTF: function (mesh, fileType){//导出物体(限谷歌浏览器)
 224             if(!this.exportGLTF){this.__proto__.exportGLTF = new THREE.GLTFExporter();}
 225             if(!mesh){console.log("mesh 错误"); return;}
 226             // 使用MeshBasicMaterial 或 MeshStandardMaterial 材质 效果会更好
 227             //使用 BufferGeometry 缓存几何体 文件体积会更小
 228             //if(mesh.geometry.isGeometry === true){mesh.geometry = new THREE.BufferGeometry().fromGeometry(mesh.geometry);}
 229             var opt = {
 230                 binary: fileType || this.exportGLTFFileType || false,
 231                 embedImages: true,
 232                 onlyVisible: true,
 233                 truncateDrawRange: true,
 234                 trs: false
 235             };
 236             var download = ( blob, filename )=>{
 237                 let link = _view.add(document.body, "a");
 238                 link.style.display = 'none';
 239                 link.href = URL.createObjectURL( blob ); console.log(link.href);
 240                 link.download = filename;
 241                 link.click();
 242                 _view.remove(link); 
 243             }
 244             
 245             this.exportGLTF.parse(mesh, function ( result ){
 246                 if(result instanceof ArrayBuffer){
 247                     download(new Blob([result], {type: 'application/octet-stream'}), 'scene.glb');
 248                 }else{
 249                     download(new Blob([JSON.stringify( result, null, 2 )], {type: 'text/plain'}), 'scene.gltf');
 250                 }
 251             }, opt);
 252         },
 253         
 254         runRaycaster: function (o, w, h){//光线投射
 255             o.result.length = 0;
 256             o.vector2.set((o.x / w || _width) * 2 - 1, -(o.y / h || _height) * 2 + 1);
 257             o.raycaster.setFromCamera(o.vector2, o.camera);
 258             o.raycaster.intersectObjects(o.children, o.recursive, o.result);
 259         },
 260         
 261         createClipPlane: function (handCreate){//添加 面 和 点 剪裁面
 262             let pa = new THREE.Plane(new THREE.Vector3( 1, 0, 0 ), 1);
 263             let pb = new THREE.Plane(new THREE.Vector3( 0, -1, 0 ), 1);
 264             let pc = new THREE.Plane(new THREE.Vector3( 0, 0, -1), 1);
 265             let pd = new THREE.Plane(new THREE.Vector3( 0, 1, 1), 1);
 266             
 267             let hg = new THREE.Group();
 268             hg.add(new THREE.PlaneHelper(pa, 2, 0xff0000), new THREE.PlaneHelper(pb, 2, 0x00ff00), new THREE.PlaneHelper(pc, 2, 0x0000ff), new THREE.PlaneHelper(pd, 2, 0x0000ff));
 269             return {
 270                 planes: [pa, pb, pc, pd],
 271                 helpers: hg
 272             };
 273             var geometry = new THREE.SphereGeometry(1, 48, 24);
 274             var material = new THREE.MeshLambertMaterial({
 275                 color: new THREE.Color("#666666"),
 276                 side: THREE.DoubleSide,
 277                 clippingPlanes: clipPlane,
 278                 clipIntersection: true
 279             });
 280             //console.log(helper0); console.log(material);
 281             handCreate.add(new THREE.Mesh(geometry, material), helperGroup);
 282             
 283             handCreate.renderer.localClippingEnabled = true;
 284             
 285             //clipPlane.constant = 0.1;
 286             new Gui({constant:0}, [-1, 1, 0.01])
 287             .change((val)=>{
 288                 for(let k = 0; k < clipPlane.length; k++){
 289                     clipPlane[k].constant = val;
 290                 }
 291                 handCreate.update();
 292             })
 293             .add(material, "clipIntersection")
 294             .add(helper0, "size", [0, 10, 0.1])
 295             .change(()=>{handCreate.update();})
 296         }
 297         
 298     });
 299     
 300     
 301     
 302     //几何体
 303     var _Geometry = function (){
 304         _Three.call(this);
 305         //this.width = 100; _width
 306         this.height = 100;
 307         this.y = this.campos.y;
 308         this.dis = 0.5;
 309         this.backMesh = {distance: 0, nowDistance: 0};
 310         this.targetChange = null;
 311         this.objects = [];
 312     }
 313     
 314     _Geometry.prototype = Object.assign(Object.create(_Three.prototype), {
 315         
 316         constructor: _Geometry,
 317         
 318         config: [
 319             new THREE.BoxGeometry(1, 1, 1, 1, 1, 1), 
 320             new THREE.SphereGeometry(0.5, 8 , 6, 0, Math.PI * 2, 0, Math.PI),
 321             new THREE.PlaneGeometry(1, 1, 1, 1),
 322             new THREE.CircleGeometry(0.5, 16, 0, Math.PI * 2),
 323             new THREE.CylinderGeometry(0.5, 0.5, 1, 8, 1, false, 0, Math.PI * 2)
 324         ],
 325 
 326         campos: {x: _width/110, y: 0, z: 1.5},
 327         
 328         isGoToPosition: true,
 329 
 330         defaultMaterial: new THREE.MeshBasicMaterial({wireframe: true}),
 331         
 332         init: function (){//初始化
 333             if(this.scene === undefined)  this.addScene();
 334             if(this.show === undefined)  this.setShow();
 335             if(this.target === undefined) this.setTarget();
 336             this.renderView(this.config);
 337             return this;
 338         },
 339         
 340         addScene: function (){//添加 场景
 341             let elem = _view.add(document.body, "div", null, "ShowObject box-scroll-block");
 342             _view.addEvent(elem, 'click', (e)=>{this.addTarget(e);});
 343             
 344             let scene = this.createScene(0x000000, false);
 345             var camera = new THREE.OrthographicCamera(_width/-100, _width/100, this.height/100, this.height/-100, 0.1, 10);
 346             camera.lookAt(0, 0, 0);
 347             let renderer = this.createRenderer(elem, _width, this.height, true, true, true, true);
 348             let linghts = this.addLinghts(scene);
 349             let drag = new THREE.DragControls(scene.children, camera, renderer.domElement);
 350             drag.enabled = false;
 351             this.__proto__.scene = {e: elem, s:scene, c: camera, r: renderer, l: linghts, drag: drag, target: null}
 352             drag.enabled = false;
 353             drag.addEventListener('drag', (e)=>{
 354                 this.update();
 355             });
 356             drag.addEventListener('hoveron', (e)=>{
 357                 if(drag.enabled === true) return;
 358                 this.scene.target = e.object;
 359             });
 360             drag.addEventListener('hoveroff', ()=>{
 361                 this.scene.target = null;
 362             });
 363             
 364             this.goToPosition();
 365         },
 366         
 367         addLinghts: function (scene){//重写添加灯光
 368             let a = new THREE.AmbientLight(0x696969);
 369             let b = new THREE.DirectionalLight(0xFFFFFF, 1);
 370             b.position.set(0, 5, 5);
 371             scene.add(a, b);
 372             return [a, b];
 373         },
 374         
 375         goToPosition: function (){//跳转到 geometry 坐标
 376             if(this.isGoToPosition === false) return;
 377             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 378             this.update();
 379         },
 380         
 381         setPos: function (mesh, k){//renderView-> 设置物体之间的距离
 382             mesh.position.set(this.backMesh.distance, this.y, 0);
 383             //let size = box3.getSize(new THREE.Vector3());
 384             let box3 = this.getBox3(mesh);
 385             let width = box3.getSize(new THREE.Vector3()).x;
 386             let center = box3.getCenter(new THREE.Vector3()).x;
 387             
 388             //let dtp = box3.distanceToPoint(new THREE.Vector3(this.backMesh.distance, this.y, 0));
 389             //console.log(width);
 390             this.backMesh.distance += width + this.dis;
 391             
 392             //this.backMesh.left = this.backMesh.distance - width + center;
 393             
 394             //this.backMesh.nowDistance = width / 2 - center + this.backMesh.distance;
 395             //var helper = new THREE.Box3Helper(box3, 0xffff00);
 396             //helper.position.copy(mesh.position);
 397             //this.scene.s.add(helper);
 398             
 399             //console.log(this.backMesh)
 400             //console.log(width, center);
 401         },
 402         
 403         addMesh: function (object, key){//renderView-> 添加物体
 404             let mesh = new THREE.Mesh(object, this.defaultMaterial);
 405             mesh.HandCreate = {type: "_Geometry", index: key, MatIndex: 0}
 406             this.scene.s.add(mesh);
 407             return mesh;
 408         },
 409 
 410         renderView: function (arr){//渲染场景视图
 411             for(let k = 0; k < arr.length; k++){
 412                 let mesh = this.addMesh(arr[k], k);
 413                 this.setPos(mesh, k);
 414                 this.objects.push(mesh);
 415             }
 416             this.update();
 417         },
 418         
 419         setShow: function (){//是否显示场景的html元素
 420             let _show = false;
 421             Object.defineProperties(this.__proto__, {
 422                 show: {
 423                     get:()=>{return _show;},
 424                     set:(v)=>{
 425                         if(v === true){
 426                             this.scene.e.style.display = "block";
 427                         }else{
 428                             this.scene.e.style.display = "none";
 429                         }
 430                         _show = v;
 431                     }
 432                 }
 433             });
 434         },
 435         
 436         addTarget: function (e){//addScene event->场景html元素的事件回调函数
 437             if(!this.scene.target) return;
 438             this.target = this.scene.target;
 439         },
 440         
 441         setTarget: function (){//配置 target
 442             let _target = null;
 443             Object.defineProperties(this.__proto__, {
 444                 target: {
 445                     get:()=>{return _target;},
 446                     set:(v)=>{
 447                         if(typeof(this.targetChange) === "function") this.targetChange(v);
 448                         _target = v;
 449                     }
 450                 }
 451             });
 452         },
 453         
 454         exportObject: function (){//导出 几何体
 455             
 456         },
 457         
 458         importObject: function (object){//导入 几何体
 459             if(object.isGeometry !== true) return;
 460             let nowKey = this.config.length;
 461             let mesh = this.addMesh(object, nowKey);
 462             this.setPos(mesh, nowKey);
 463             this.config.push(object);
 464             this.objects.push(mesh);
 465             this.update();
 466         },
 467         
 468         update: function (){//更新场景
 469             this.render(this.scene.s, this.scene.c, this.scene.r);
 470         },
 471         
 472         updateObjectColors: function (color){
 473             for(let k = 0; k < this.objects.length; k++){
 474                 this.objects[k].material.color.set(color);
 475             }
 476             this.update();
 477         },
 478         
 479         debugCamera: function (){//gui调试 正交相机
 480             let c = this.scene.c;
 481             let pos = {x: _width/110, y: 0, lookAt: true, position: false};
 482             let upd = ()=>{
 483                 if(pos.lookAt) c.lookAt(pos.x, pos.y, 0); 
 484                 if(pos.position) c.position.set(pos.x, pos.y, 5);
 485                 this.update();
 486             }
 487 
 488             new Gui(pos, [0, 10, 0.1], "调试正交相机")
 489             .change({
 490                 x: (v)=>{pos.x = v; upd();},
 491                 y: (v)=>{pos.y = v;  upd();}
 492             })
 493 
 494         }
 495         
 496     });
 497     
 498     
 499     
 500     //材质
 501     var _Material = function (){
 502         _Geometry.call(this);
 503     }
 504     
 505     _Material.prototype = Object.assign(Object.create(_Geometry.prototype), {
 506         
 507         constructor: _Material,
 508         
 509         config:[
 510             new THREE.MeshBasicMaterial(),
 511             new THREE.MeshLambertMaterial(),
 512             new THREE.MeshStandardMaterial()
 513         ],
 514         
 515         defaultGeometry: new THREE.BoxGeometry(1, 1, 1, 1, 1, 1),
 516         
 517         campos: {x: _width/110, y: 1.5, z: 1.5},
 518         
 519         addMesh: function (object, key){
 520             let mesh = new THREE.Mesh(this.defaultGeometry, object);
 521             mesh.HandCreate = {type: "_Material", index: key};
 522             this.scene.s.add(mesh);
 523             return mesh;
 524         },
 525         
 526         goToPosition: function (mesh){
 527             if(!mesh || this.isGoToPosition === false) return; this.mesh = mesh;
 528             let geometry = _Geometry.prototype.config[mesh.HandCreate.GeoCI].clone();
 529             for(let k = 0; k < this.objects.length; k++){
 530                 this.updateGeometry(this.objects[k], geometry);
 531             }
 532             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 533             this.update();
 534         }
 535         
 536     });
 537     
 538     
 539     
 540     //纹理 map
 541     var _Texture = function (){
 542         _Material.call(this);
 543         this.textureLen = 12;
 544         this.setTexture();
 545     }
 546     
 547     _Texture.prototype = Object.assign(Object.create(_Material.prototype), {
 548         
 549         constructor: _Texture,
 550         
 551         config: [],
 552         
 553         campos: {x: _width/110, y: 3, z: 1.5},
 554         
 555         defaultMaterial: new THREE.MeshBasicMaterial(),
 556         
 557         load: new THREE.TextureLoader(),
 558         
 559         loaded: 0,
 560         
 561         setTexture: function (){
 562             let k, texture;
 563             for(k = 0; k < this.textureLen; k++){
 564                 texture = this.load.load("img/texture/"+k+".jpg", ()=>{this.__proto__.loaded++;});
 565                 texture.wrapS = THREE.RepeatWrapping;
 566                 texture.wrapT = THREE.RepeatWrapping;
 567                 texture.repeat.set(1, 1);
 568                 this.__proto__.config.push(texture);
 569             }
 570             if(this.loaded !== this.textureLen){this.awaitLoad();}
 571         },
 572         
 573         awaitLoad: function (){
 574             let interval = setInterval(()=>{
 575                 if(this.loaded === this.textureLen){
 576                     this.update();
 577                     clearInterval(interval);
 578                     console.log("load texture: "+this.loaded+"/"+this.textureLen);
 579                 }else{
 580                     console.log("load texture: "+this.loaded+"/"+this.textureLen);
 581                 }
 582             }, 300);
 583         },
 584 
 585         addMesh: function (object, key){
 586             let mesh = new THREE.Mesh(this.defaultGeometry, new THREE.MeshBasicMaterial({map: object}));
 587             //let mesh = new THREE.Mesh(this.defaultGeometry, this.defaultMaterial);
 588             //this.updateTexture(mesh, object);
 589             mesh.HandCreate = {type: "_Texture", index: key};
 590             this.scene.s.add(mesh);
 591             return mesh;
 592         },
 593         
 594         goToPosition: function (mesh){
 595             if(!mesh || this.isGoToPosition === false) return; this.mesh = mesh;
 596             let geometry = _Geometry.prototype.config[mesh.HandCreate.GeoCI].clone();
 597             let material = _Material.prototype.config[mesh.HandCreate.MatCI].clone();
 598             for(let k = 0; k < this.objects.length; k++){
 599                 this.updateGeometry(this.objects[k], geometry);
 600                 this.updateMaterial(this.objects[k], material);
 601             }
 602             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 603             this.update();
 604         }
 605         
 606     });
 607     
 608     //物体
 609     var _Mesh = function (){}
 610     
 611     //gui
 612     var SetView = function (HC, newMesh, oldMesh){
 613         this.HC = HC;
 614         this.newMesh = newMesh;
 615         this.oldMesh = oldMesh;
 616         return this.init();
 617     }
 618     
 619     Object.assign(SetView.prototype, {
 620         
 621         constructor: SetView,
 622         
 623         init: function (){
 624             if(this.globalGui === undefined) this.createGlobal();
 625             if(this.SOG === undefined) this.createSelectObjectGui();
 626 
 627             this.createMesh();
 628             this.createGeometry();
 629             this.createMaterial();
 630             return this;
 631         },
 632         
 633         createMesh: function (){
 634             let u = (a, v)=>{
 635                 if(this.newMesh[a] === undefined) return;
 636                 this.newMesh[a] = v; 
 637                 this.HC.update();
 638             }
 639             let upd = (a, b, v)=>{
 640                 this.newMesh[a][b] = v; 
 641                 if(this.newMesh.HandCreate.wireframe) this.newMesh.HandCreate.wireframe[a][b] = v; 
 642                 this.HC.update();
 643             }
 644             let m = {
 645                 visible: this.newMesh.visible,
 646                 frustumCulled: this.newMesh.frustumCulled,
 647                 castShadow: this.newMesh.castShadow,
 648                 receiveShadow: this.newMesh.receiveShadow,
 649             }
 650             let o = {
 651                 exportGltf: ()=>{this.HC.Three.exporterGLTF(this.newMesh);},
 652                 removeMesh: ()=>{
 653                     if(this.newMesh.HandCreate.wireframe){this.HC.remove(this.newMesh.HandCreate.wireframe, this.HC.group);}
 654                     this.HC.remove(this.newMesh);
 655                 },
 656                 addWireframe: true
 657             }
 658             
 659             this.gui = new Gui(m, true).name({visible: "显示物体", castShadow: "投射阴影", receiveShadow: "接收阴影"})
 660             .change({
 661                 visible: ()=>{u("visible", m.visible);},
 662                 frustumCulled: ()=>{u("frustumCulled", m.frustumCulled);},
 663                 castShadow: ()=>{u("castShadow", m.castShadow);},
 664                 receiveShadow: ()=>{u("receiveShadow", m.receiveShadow);}
 665             })
 666             
 667             .add(o, true)
 668             .name({addWireframe: "辅助网格", exportGltf: "导出物体", removeMesh: "移除物体"})
 669             .change({
 670                 addWireframe: (e)=>{
 671                     if(!this.newMesh.HandCreate.wireframe) return;
 672                     this.newMesh.HandCreate.wireframe.visible = o.addWireframe;
 673                     this.HC.update();
 674                 }
 675             })
 676             
 677             
 678             .add(this.newMesh.HandCreate.position, true, [-(_maxDistance/2), _maxDistance/2, _minDistance])
 679             .name({x: "位置X轴", y: "位置Y轴", z: "位置Z轴"})
 680             .change({
 681                 x: (v)=>{upd("position", "x", v);},
 682                 y: (v)=>{upd("position", "y", v);},
 683                 z: (v)=>{upd("position", "z", v);}
 684             })
 685             .add(this.newMesh.HandCreate.rotation, true, [-Math.PI, Math.PI, 0.001])
 686             .name({x: "旋转X轴", y: "旋转Y轴", z: "旋转Z轴"})
 687             .change({
 688                 x: (v)=>{upd("rotation", "x", v);},
 689                 y: (v)=>{upd("rotation", "y", v);},
 690                 z: (v)=>{upd("rotation", "z", v);}
 691             })
 692             .add(this.newMesh.HandCreate.scale, true, [0.1, _maxDistance * 0.5, _minDistance])
 693             .name({x: "缩放X轴", y: "缩放Y轴", z: "缩放Z轴"})
 694             .change({
 695                 x: (v)=>{upd("scale", "x", v);},
 696                 y: (v)=>{upd("scale", "y", v);},
 697                 z: (v)=>{upd("scale", "z", v);}
 698             })
 699             
 700             .add(this.newMesh.HandCreate, true, "isSelect", "是否可选取").change(()=>{this.HC.removeTarget(this.newMesh);})
 701             .display("none")
 702             .title("物体-"+this.newMesh.type+"-"+this.newMesh.id);
 703         },
 704         
 705         createGeometry: function (){
 706             if(this.oldMesh.geometry.parameters === undefined){console.log("SetView: 忽略了geometry"); return;}
 707             let o, p = {}, geo;
 708             for(let k in this.oldMesh.geometry.parameters){p[k] = this.oldMesh.geometry.parameters[k];}
 709             switch(this.oldMesh.geometry.type){
 710             
 711                 case "BoxGeometry": 
 712                     o = {
 713                         width:[0.1, 10, 0.1], 
 714                         height:[0.1, 10, 0.1], 
 715                         depth:[0.1, 10, 0.1], 
 716                         widthSegments:[1, 30, 1], 
 717                         heightSegments:[1, 30, 1], 
 718                         depthSegments:[1, 30, 1]
 719                     }
 720                     this.gui.create(p, o, true)
 721                     .name({width: "宽度", height: "高度", depth: "深度", widthSegments: "宽段数", heightSegments: "高段数", depthSegments: "深段数"})
 722                     .change(()=>{
 723                         geo = new THREE.BoxGeometry(p.width, p.height, p.depth, p.widthSegments, p.heightSegments, p.depthSegments);
 724                         this.HC.Three.updateGeometry(this.newMesh, geo);
 725                         this.HC.update();
 726                     });
 727                     
 728                 break;
 729                 
 730                 case "SphereGeometry": 
 731                     o = {
 732                         radius:[0.1, 10, 0.1], 
 733                         widthSegments:[1, 30, 1], 
 734                         heightSegments:[1, 30, 1], 
 735                         phiStart:[0, Math.PI*2, 0.1], 
 736                         phiLength:[0.1, Math.PI*2, 0.1], 
 737                         thetaStart:[0, Math.PI*2, 0.1], 
 738                         thetaLength:[0.1, Math.PI*2, 0.1]
 739                     }
 740                     this.gui.create(p, o, true)
 741                     .name({radius: "半径", widthSegments: "宽段数", heightSegments: "高段数", phiStart: "经线起始角度", phiLength: "经线起始角度大小", thetaStart: "纬线起始角度", thetaLength: "纬线起始角度大小",})
 742                     .change(()=>{
 743                         geo = new THREE.SphereGeometry(p.radius, p.widthSegments, p.heightSegments, p.phiStart, p.phiLength, p.thetaStart, p.thetaLength);
 744                         this.HC.Three.updateGeometry(this.newMesh, geo);
 745                         this.HC.update();
 746                     });
 747                     
 748                 break;
 749                 
 750                 case "PlaneGeometry": 
 751                     o = {
 752                         width: [1, 100, 0.1],
 753                         height: [1, 100, 0.1],
 754                         widthSegments: [1, 30, 1],
 755                         heightSegments: [1, 30, 1]
 756                     }
 757                     this.gui.create(p, o, true)
 758                     .name({width: "宽度", height: "高度", widthSegments: "宽段数", heightSegments: "高段数"})
 759                     .change(()=>{
 760                         geo = new THREE.PlaneGeometry(p.width, p.height, p.widthSegments, p.heightSegments);
 761                         this.HC.Three.updateGeometry(this.newMesh, geo);
 762                         this.HC.update();
 763                     });
 764                 break;
 765                 
 766                 case "CircleGeometry": 
 767                     o = {
 768                         radius: [0.1, 10, 0.1],
 769                         segments: [1, 30, 1], 
 770                         thetaStart: [0, Math.PI*2, 0.1], 
 771                         thetaLength: [0.1, Math.PI*2, 0.1]
 772                     }
 773                     this.gui.create(p, o, true)
 774                     .name({radius: "半径", segments: "分段数", thetaStart: "纬线起始角度", thetaLength: "纬线起始角度大小"})
 775                     .change(()=>{
 776                         geo = new THREE.CircleGeometry(p.radius, p.segments, p.thetaStart, p.thetaLength);
 777                         this.HC.Three.updateGeometry(this.newMesh, geo);
 778                         this.HC.update();
 779                     });
 780                 break;
 781                 
 782                 case "CylinderGeometry": 
 783 
 784                     o = {
 785                         radiusTop: [0.1, 10, 0.1],
 786                         radiusBottom: [0.1, 10, 0.1],
 787                         height: [0.1, 10, 0.1],
 788                         radialSegments: [1, 30, 1], 
 789                         heightSegments: [1, 30, 1], 
 790                         thetaStart: [0, Math.PI*2, 0.1], 
 791                         thetaLength: [0.1, Math.PI*2, 0.1]
 792                     }
 793                     this.gui.create(p, o, true)
 794                     .name({openEnded: "不封顶", radiusTop: "顶部半径", radiusBottom: "底部半径", height: "高度", radialSegments: "侧面分段数", heightSegments: "高度分段数", thetaStart: "纬线起始角度", thetaLength: "纬线起始角度大小"})
 795                     .change(()=>{
 796                         geo = new THREE.CylinderGeometry(p.radiusTop, p.radiusBottom, p.height, p.radialSegments, p.heightSegments, p.openEnded,  p.thetaStart, p.thetaLength);
 797                         this.HC.Three.updateGeometry(this.newMesh, geo);
 798                         this.HC.update();
 799                     })
 800                 break;
 801                     
 802                 default : break;
 803             }
 804             this.gui.title("几何体-"+this.newMesh.geometry.type+"-"+this.newMesh.id);
 805         },
 806         
 807         createMaterial: function (){
 808             
 809             let mat = this.newMesh.material;
 810             
 811             let o = {
 812                 color: "#" + mat.color.getHexString(),
 813                 emissive: mat.emissive === undefined ? "#000000" : "#" + mat.emissive.getHexString(),
 814                 updateMaterial: ()=>{this.HC.material.goToPosition(this.newMesh);},
 815                 updateTexture: ()=>{this.HC.texture.goToPosition(this.newMesh);}
 816             }
 817             let m = {
 818                 wireframe: mat.wireframe, 
 819                 visible: mat.visible, 
 820                 side: mat.side, 
 821                 fog: mat.fog, 
 822                 aoMapIntensity: mat.aoMapIntensity, 
 823                 colorWrite: mat.colorWrite, 
 824                 transparent: mat.transparent, 
 825                 opacity: mat.opacity, 
 826                 alphaTest: mat.alphaTest, 
 827                 flatShading: mat.flatShading,
 828                 emissiveIntensity: mat.emissiveIntensity === undefined ? 0 : mat.emissiveIntensity,
 829                 repeatU: 1,
 830                 repeatV: 1,
 831                 anisotropy: 1
 832             }
 833             
 834             let num = {
 835                 aoMapIntensity: [0, 1, 0.1], 
 836                 opacity: [0, 1, 0.1], 
 837                 alphaTest: [0, 1, 0.1], 
 838                 emissiveIntensity: [0, 1, 0.1],
 839                 repeatU: [1, 100, 1],
 840                 repeatV: [1, 100, 1],
 841                 anisotropy: [1, this.HC.renderer.capabilities.getMaxAnisotropy() || 2, 1]
 842             };
 843             let sel = {
 844                 side: [["外面", THREE.FrontSide], ["里面", THREE.BackSide], ["双面", THREE.DoubleSide]]
 845             };
 846             let name = {
 847                 wireframe:"网格模式", 
 848                 visible:"显示材质", 
 849                 side: "材质显示那一面", 
 850                 fog: "受雾气影响", 
 851                 aoMapIntensity: "遮挡效果", 
 852                 colorWrite: "渲染颜色", 
 853                 transparent: "渲染透明度", 
 854                 opacity: "透明度", 
 855                 alphaTest: "alpha值", 
 856                 flatShading: "平面着色",
 857                 emissiveIntensity: "放射光强度",
 858                 repeatU: "重复量,纹理U面",
 859                 repeatV: "重复量,纹理V面",
 860                 anisotropy: "纹理清晰度"
 861             };
 862             let c = {
 863                 wireframe: ()=>{if(this.newMesh.material.wireframe === undefined){this.gui.showStop("wireframe", m); return;}else{this.gui.showStop("wireframe", m, false);}  this.newMesh.material.wireframe = m.wireframe; this.HC.update();},
 864                 visible: ()=>{if(this.newMesh.material.visible === undefined){this.gui.showStop("visible", m); return;}else{this.gui.showStop("visible", m, false);}  this.newMesh.material.visible = m.visible; this.HC.update();},
 865                 side: (e)=>{if(this.newMesh.material.side === undefined){this.gui.showStop("side", m); return;}else{this.gui.showStop("side", m, false);}  this.newMesh.material.side = eval(e.target.value); this.HC.update();},
 866                 fog: ()=>{if(this.newMesh.material.fog === undefined){this.gui.showStop("fog", m); return;}else{this.gui.showStop("fog", m, false);}  this.newMesh.material.fog = m.fog; this.HC.update();},
 867                 aoMapIntensity: ()=>{if(this.newMesh.material.aoMapIntensity === undefined){this.gui.showStop("aoMapIntensity", m); return;}else{this.gui.showStop("aoMapIntensity", m, false);}  this.newMesh.material.aoMapIntensity = m.aoMapIntensity; this.HC.update();},
 868                 colorWrite: ()=>{if(this.newMesh.material.colorWrite === undefined){this.gui.showStop("colorWrite", m); return;}else{this.gui.showStop("colorWrite", m, false);}  this.newMesh.material.colorWrite = m.colorWrite; this.HC.update();},
 869                 transparent: ()=>{if(this.newMesh.material.transparent === undefined){this.gui.showStop("transparent", m); return;}else{this.gui.showStop("transparent", m, false);}  this.newMesh.material.transparent = m.transparent; this.HC.update();},
 870                 opacity: ()=>{if(this.newMesh.material.opacity === undefined){this.gui.showStop("opacity", m); return;}else{this.gui.showStop("opacity", m, false);}  this.newMesh.material.opacity = m.opacity; this.HC.update();},
 871                 alphaTest: ()=>{if(this.newMesh.material.alphaTest === undefined){this.gui.showStop("alphaTest", m); return;}else{this.gui.showStop("alphaTest", m, false);}  this.newMesh.material.alphaTest = m.alphaTest; this.HC.update();},
 872                 flatShading: ()=>{if(this.newMesh.material.flatShading === undefined){this.gui.showStop("flatShading", m); return;}else{this.gui.showStop("flatShading", m, false);}  this.newMesh.material.flatShading = m.flatShading; this.HC.update();},
 873                 emissiveIntensity: ()=>{if(this.newMesh.material.emissiveIntensity === undefined){this.gui.showStop("emissiveIntensity", m); return;}else{this.gui.showStop("emissiveIntensity", m, false);}  this.newMesh.material.emissiveIntensity = m.emissiveIntensity; this.HC.update();},
 874                 repeatU: ()=>{if(this.newMesh.material.map === null){this.gui.showStop("repeatU", m); return;}else{this.gui.showStop("repeatU", m, false);} this.newMesh.material.map.repeat.set(m.repeatU, m.repeatV);this.HC.update();},
 875                 repeatV: ()=>{if(this.newMesh.material.map === null){this.gui.showStop("repeatV", m); return;}else{this.gui.showStop("repeatV", m, false);} this.newMesh.material.map.repeat.set(m.repeatU, m.repeatV); this.HC.update();},
 876                 anisotropy: ()=>{if(this.newMesh.material.map === null || (m.anisotropy !== 1 && (m.anisotropy / 2 % 1) !== 0)){this.gui.showStop("anisotropy", m); return;}else{this.gui.showStop("anisotropy", m, false);}this.newMesh.material.map.anisotropy = m.anisotropy;this.HC.update();},
 877                 
 878             };
 879             
 880             
 881             
 882             this.gui.create(m, num, true, sel).name(name).change(c)
 883             
 884             .add(o, true)
 885             .name({color: "材质颜色", emissive: "放射光颜色", updateMaterial: "替换材质", updateTexture: "替换纹理"})
 886             .change({
 887                 color: (e)=>{if(this.newMesh.material.color === undefined){this.gui.showStop("color", o); return;}else{this.gui.showStop("color", o, false);}  this.newMesh.material.color.set(e.target.value); this.HC.update();},
 888                 emissive: (e)=>{if(this.newMesh.material.emissive === undefined){this.gui.showStop("emissive", o); return;}else{this.gui.showStop("emissive", o, false);} this.newMesh.material.emissive.set(e.target.value); this.HC.update();}
 889             })
 890             
 891             .title("材质-"+this.newMesh.material.type+"-"+this.newMesh.id);
 892         },
 893         
 894         createGlobal: function (){
 895             let o = {
 896                 setMode: "translate",
 897                 exportAll: ()=>{this.HC.Three.exporterGLTF(this.HC.intersects.group);},
 898                 updateMaterialAll: ()=>{console.log("替换全部材质")},
 899                 isgltf: true,
 900                 dragEnabled: false,
 901                 addMesh: ()=>{this.HC.geometry.goToPosition();}
 902             }
 903 
 904             let gui = new Gui(this.HC.geometry, "show", "显示选项栏")
 905             
 906             .add(o, true, {dragEnabled: [["创建模式", false], ["编辑模式", true]], isgltf: [[".gltf", false], [".glb", true]], setMode: [["平移", "translate"], ["旋转", "rotate"], ["缩放", "scale"]]})
 907             .name({exportAll: "导出全部物体", updateMaterialAll: "替换全部材质", setMode: "控制模式", isgltf: "导出类型", addMesh: "添加物体", dragEnabled: "底部物体选项栏的状态(创建 或 调整其位置)"})
 908             .change({
 909                 isgltf: (e)=>{this.HC.Three.exportGLTFFileType = eval(e.target.value);},
 910                 setMode: (e)=>{this.HC.control.transform.setMode(e.target.value);},
 911                 dragEnabled: (e)=>{
 912                     let ty = "geometry";
 913                     if(this.HC.geometry.scene.c.position.y === this.HC.material.campos.y){ty = "material";}
 914                     else if(this.HC.geometry.scene.c.position.y === this.HC.texture.campos.y){ty = "texture";}
 915 
 916                     this.HC.geometry.scene.drag.enabled = eval(e.target.value);
 917                     if(this.HC.geometry.scene.drag.enabled === true){
 918                         this.HC.geometry.__proto__.isGoToPosition = false;
 919                         this.HC[ty].updateObjectColors(0xff0000);
 920                     }else{
 921                         this.HC[ty].updateObjectColors(0xffffff);
 922                         this.HC.geometry.__proto__.isGoToPosition = true;
 923                     }
 924                 
 925                 }
 926             })
 927             
 928             .add(this.HC, true, ["lockTarget", "isSelectTargets"])
 929             .name({lockTarget: "禁用选取", isSelectTargets: "标记物体"})
 930             .change({
 931                 isSelectTargets: ()=>{
 932                     if(this.HC.isSelectTargets === false){
 933                         this.HC.removeTargets();
 934                         this.SOG.display("none");
 935                         return;
 936                     }
 937                     this.SOG.focus().display("block");
 938                 },
 939                 lockTarget: ()=>{
 940                     if(this.HC.lockTarget === false){
 941                         this.HC.removeTargets();
 942                     }
 943                 }
 944             })
 945             
 946             .setPos(300, 10)
 947             
 948             .title("global");
 949             
 950             this.__proto__.globalGui = gui;
 951         },
 952         
 953         createSelectObjectGui: function(){
 954             let fhts = (callback)=>{
 955                 for(let k = 0; k < this.HC.targets.length; k++){callback(this.HC.targets, k);}
 956             }
 957             
 958             let bsp = {
 959                 type: "intersect",
 960                 run: ()=>{
 961                     if(this.HC.targets[0] === undefined){console.log("你还没有选择任何物体"); return;}
 962                     if(this.newMesh === this.HC.targets[0].mesh) return;
 963                     this.HC.geometry.importObject(this.HC.Three.getBSP(this.newMesh.clone(true), this.HC.targets[0].mesh.clone(true), bsp.type));
 964                 }
 965             }
 966             let o = {
 967                 deletes: ()=>{
 968                     fhts((o, k)=>{
 969                         if(o[k].mesh.HandCreate.wireframe){this.HC.remove(o[k].mesh.HandCreate.wireframe, this.HC.group);}
 970                         this.HC.remove(o[k].mesh);
 971                     });
 972                     if(!this.HC.target.mesh) return;
 973                     if(this.HC.target.mesh.HandCreate.wireframe){
 974                         this.HC.remove(this.HC.target.mesh.HandCreate.wireframe, this.HC.group);
 975                     }
 976                     this.HC.remove(this.HC.target.mesh);
 977                 },
 978                 exports: ()=>{
 979                     fhts((o, k)=>{
 980                         o[k].mesh.material.color.set(o[k].color);
 981                         this.HC.Three.exporterGLTF(o[k].mesh);
 982                         o[k].mesh.material.color.set("red");
 983                     });
 984                     if(!this.HC.target.mesh) return;
 985                     this.HC.Three.exporterGLTF(this.HC.target.mesh);
 986                 }
 987             }
 988             
 989             this.SOG = new Gui(bsp, true, {type:[["交集", "intersect"], ["并集", "union"], ["差集", "subtract"]]})
 990             .name({run: "开始布尔运算", type: "布尔运算类型"})
 991             .change({type: (e)=>{bsp.type = e.target.value;}})
 992             .title("多物体操作(包含当前目标对象)")
 993             
 994             .create(o).name({deletes: "删除物体", exports: "导出物体"})
 995 
 996             
 997             
 998             .setPos(300, 2)
 999             .display("none")
1000         }
1001         
1002     });
1003     
1004     
1005     
1006     //main
1007     var HandCreate = function (){
1008         this.Three = new _Three();
1009         this.group = new THREE.Group();
1010         this.target = {};
1011         this.isSelectTargets = false;
1012         this.targets = [];
1013         this.backMesh = null;
1014         this.lockTarget = false;
1015         this.scene = this.Three.createScene([], false);
1016         this.renderer = this.Three.createRenderer(document.body, _width, _height, true, true, true, true);
1017         
1018     }
1019     
1020     Object.assign(HandCreate.prototype, {
1021         
1022         constructor: HandCreate,
1023         
1024         init: function (){
1025             this.intersects = {
1026                 raycaster: new THREE.Raycaster(),
1027                 group: new THREE.Group(),
1028                 vector2: new THREE.Vector2(),
1029                 result: [],
1030                 camera: this.camera,
1031                 recursive: true,
1032                 x: 0,
1033                 y: 0,
1034             };
1035             this.renderer.domElement.style = "position:absolute; top:0; left:0";//如果不定位, gui的移动块会不正常显示
1036             //this.renderer.localClippingEnabled = true;//是否渲染 平面剪裁
1037             this.camera = this.Three.createCamera(45, _width, _height, _minDistance, _maxDistance * _minDistance * 0.2);
1038             this.camera.position.set(0, _maxDistance * 0.001, _maxDistance * 0.001);
1039             this.linghts = this.Three.addLinghts(this.scene, this);
1040             this.control = this.Three.addControls(this.scene, this.camera, this.renderer, this.intersects.group.children, this);
1041             this.control.drag.addEventListener('hoveron', (e)=>{this.setTarget(e.object);});
1042             //this.control.drag.transformGroup = true;
1043             this.control.transform.addEventListener('change', ()=>{this.transformChange();});
1044             
1045             this.geometry = new _Geometry().init();
1046             this.geometry.targetChange = (v)=>{this.createObject(v);};
1047             this.geometry.show = true;
1048             
1049             this.material = new _Material().init();
1050             
1051             this.texture = new _Texture().init();
1052             
1053             this.gridHelper = new THREE.GridHelper(_maxDistance, _maxDistance/1);
1054             this.scene.add(this.group, this.intersects.group, this.camera, this.gridHelper);
1055             
1056             
1057             //this.clip = this.Three.createClip();
1058             //this.globalView();
1059             //this.Three.loadingGLTF("img/gltfs/scene.gltf", this.intersects.group);
1060             //this.Three.loadingGLTF("img/gltfs/scene.glb", this.intersects.group);
1061             return this;
1062         },
1063         
1064         add: function (mesh, group){
1065             if(!mesh) return;
1066             let gro = group || this.intersects.group;
1067             if(Array.isArray(mesh) === true){
1068                 let k, len = mesh.length;
1069                 for(k; k < len; k++){
1070                     if(!mesh[k]) continue;
1071                     gro.add(mesh[k]);
1072                 }
1073             }else{
1074                 gro.add(mesh);
1075             }
1076             this.update();
1077         },
1078         
1079         addWireframe: function (mesh, color){
1080             let col = color || 0x696969, gro = this.group;
1081             let wireframe = new THREE.LineSegments(new THREE.WireframeGeometry(mesh.geometry));
1082             wireframe.material.color.set(col);
1083             gro.add(wireframe);
1084             return wireframe;
1085         },
1086         
1087         remove: function (mesh, group){
1088             if(!mesh){console.log("remove: mesh不存在"); return;}
1089             let arr = group || this.intersects.group;
1090             if(!arr.remove){console.log("remove: group错误"); return;}
1091             this.removeTarget(mesh);
1092             //if(mesh.gui) mesh.gui.remove();
1093             if(mesh.HandCreate) mesh.HandCreate.SV.gui.remove();
1094             if(mesh.material.map){mesh.material.map.dispose();}
1095             mesh.material.dispose();
1096             mesh.geometry.dispose();
1097             arr.remove(mesh);
1098             this.update();
1099         },
1100         
1101         update: function (){
1102             this.Three.render(this.scene, this.camera, this.renderer);
1103         },
1104 
1105         setTarget: function (mesh){
1106             if(mesh.HandCreate.isSelect === false) return;
1107             if(this.isSelectTargets === true) this.setTargets(mesh);
1108             if(this.target.mesh === mesh || this.lockTarget === true) return;
1109             if(mesh.HandCreate === undefined || mesh.HandCreate.SV === undefined){
1110                 mesh.HandCreate.isSelect = false;
1111                 this.lockTarget = true; 
1112                 console.log("setTarget: mesh 错误,取消选择"); 
1113                 return;
1114             }
1115 
1116             this.removeTarget(this.target.mesh);
1117             
1118             this.target.mesh = mesh;
1119             this.control.transform.attach(mesh);
1120             mesh.HandCreate.SV.gui.display("block");
1121             this.geometry.goToPosition();
1122             this.update();
1123         },
1124         
1125         removeTarget: function (mesh){
1126             if(!mesh || this.target.mesh !== mesh) return;
1127             this.control.transform.detach(mesh);
1128             mesh.HandCreate.SV.gui.display("none");
1129             delete(this.target.mesh);
1130             this.update();
1131         },
1132         
1133         setTargets: function (mesh){
1134             if(this.target.mesh && mesh && this.target.mesh === mesh) return;
1135             //if(this.targets.indexOf(mesh) !== -1){return;}
1136             for(let k = 0; k < this.targets.length; k ++){if(this.targets[k].mesh === mesh){return;}}
1137             this.isSelectTargets = true;
1138             this.lockTarget = true;
1139             this.targets.push({mesh: mesh, color: mesh.material.color.getHex()}); 
1140             mesh.material.color.set("red");
1141             this.update();
1142         },
1143         
1144         removeTargets: function (){
1145             this.isSelectTargets = false;
1146             this.lockTarget = false;
1147             for(let k = 0; k < this.targets.length; k++){
1148                 this.targets[k].mesh.material.color.set(this.targets[k].color);
1149             }
1150             this.targets.length = 0; 
1151             this.update();
1152         },
1153         
1154         addMeshHandCreate: function (mesh){
1155     
1156             mesh.HandCreate = {};
1157             let _SV = null, _GeoCI = null, _MatCI = null, _TexCI = null;
1158             let _isSelect = true, _wireframe = null;
1159             let _position = {}, _rotation = {}, _scale = {};
1160             Object.defineProperties(mesh.HandCreate, {
1161                 SV: {
1162                     configurable: false,
1163                     enumerable: true,
1164                     get: ()=>{return _SV;},
1165                     set: (v)=>{_SV = v;}
1166                 },
1167                 
1168                 GeoCI: {
1169                     configurable: false,
1170                     enumerable: true,
1171                     get: ()=>{return _GeoCI;},
1172                     set: (v)=>{_GeoCI = v;}
1173                 },
1174                 
1175                 MatCI: {
1176                     configurable: false,
1177                     enumerable: true,
1178                     get: ()=>{return _MatCI;},
1179                     set: (v)=>{_MatCI = v;}
1180                 },
1181                 
1182                 TexCI: {
1183                     configurable: false,
1184                     enumerable: true,
1185                     get: ()=>{return _TexCI;},
1186                     set: (v)=>{_TexCI = v;}
1187                 },
1188                 
1189                 isSelect: {
1190                     configurable: false,
1191                     enumerable: true,
1192                     get: ()=>{return _isSelect;},
1193                     set: (v)=>{_isSelect = v;}
1194                 },
1195                 
1196                 wireframe: {
1197                     configurable: false,
1198                     enumerable: true,
1199                     get: ()=>{return _wireframe;},
1200                     set: (v)=>{_wireframe = v;}
1201                 },
1202                 
1203                 position: {
1204                     configurable: false,
1205                     enumerable: true,
1206                     get: ()=>{return _position;},
1207                     set: (v)=>{_position = v;}
1208                 },
1209                 
1210                 rotation: {
1211                     configurable: false,
1212                     enumerable: true,
1213                     get: ()=>{return _rotation;},
1214                     set: (v)=>{_rotation = v;}
1215                 },
1216                 
1217                 scale: {
1218                     configurable: false,
1219                     enumerable: true,
1220                     get: ()=>{return _scale;},
1221                     set: (v)=>{_scale = v;}
1222                 }
1223                 
1224             });
1225             
1226             let upd = (v, a, b)=>{mesh[a][b] = v; this.update();}
1227             let _px = mesh.position.x, _py = mesh.position.y, _pz = mesh.position.z;
1228             Object.defineProperties(mesh.HandCreate.position, {
1229                 x: {
1230                     configurable: false,
1231                     enumerable: true,
1232                     get: ()=>{return _px;},
1233                     set: (v)=>{upd(v, "position", "x"); _px = v;}
1234                 },
1235                 y: {
1236                     configurable: false,
1237                     enumerable: true,
1238                     get: ()=>{return _py;},
1239                     set: (v)=>{upd(v, "position", "y"); _py = v;}
1240                 },
1241                 z: {
1242                     configurable: false,
1243                     enumerable: true,
1244                     get: ()=>{return _pz;},
1245                     set: (v)=>{upd(v, "position", "z"); _pz = v;}
1246                 }
1247             });
1248             
1249             let _rx = mesh.rotation.x, _ry = mesh.rotation.y, _rz = mesh.rotation.z;
1250             Object.defineProperties(mesh.HandCreate.rotation, {
1251                 x: {
1252                     configurable: false,
1253                     enumerable: true,
1254                     get: ()=>{return _rx;},
1255                     set: (v)=>{_rx = v;}
1256                 },
1257                 y: {
1258                     configurable: false,
1259                     enumerable: true,
1260                     get: ()=>{return _ry;},
1261                     set: (v)=>{_ry = v;}
1262                 },
1263                 z: {
1264                     configurable: false,
1265                     enumerable: true,
1266                     get: ()=>{return _rz;},
1267                     set: (v)=>{_rz = v;}
1268                 }
1269             });
1270             
1271             let _sx = mesh.scale.x, _sy = mesh.scale.y, _sz = mesh.scale.z;
1272             Object.defineProperties(mesh.HandCreate.scale, {
1273                 x: {
1274                     configurable: false,
1275                     enumerable: true,
1276                     get: ()=>{return _sx;},
1277                     set: (v)=>{_sx = v;}
1278                 },
1279                 y: {
1280                     configurable: false,
1281                     enumerable: true,
1282                     get: ()=>{return _sy;},
1283                     set: (v)=>{_sy = v;}
1284                 },
1285                 z: {
1286                     configurable: false,
1287                     enumerable: true,
1288                     get: ()=>{return _sz;},
1289                     set: (v)=>{_sz = v;}
1290                 }
1291             });
1292         
1293         },
1294         
1295         transformChange: function (mesher, typeer){
1296             
1297             if(!this.target || !this.target.mesh || !this.target.mesh.HandCreate){return;}
1298             
1299             let type = typeer || this.control.transform.getMode(), mesh = mesher || this.target.mesh;
1300             let hc = mesh.HandCreate;
1301 
1302             switch(type){
1303                 case "translate": 
1304                     hc.position.x = mesh.position.x;
1305                     hc.position.y = mesh.position.y;
1306                     hc.position.z = mesh.position.z;
1307                     if(hc.wireframe) hc.wireframe.position.set(mesh.position.x, mesh.position.y, mesh.position.z);
1308                 break;
1309                     
1310                 case "rotate": 
1311                     hc.rotation.x = mesh.rotation.x;
1312                     hc.rotation.y = mesh.rotation.y;
1313                     hc.rotation.z = mesh.rotation.z;
1314                     if(hc.wireframe) hc.wireframe.rotation.set(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z);
1315                 break;
1316                     
1317                 case "scale": 
1318                     hc.scale.x = mesh.scale.x;
1319                     hc.scale.y = mesh.scale.y;
1320                     hc.scale.z = mesh.scale.z;
1321                     if(hc.wireframe) hc.wireframe.scale.set(mesh.scale.x, mesh.scale.y, mesh.scale.z);
1322                 break;
1323                     
1324                 default: break;
1325             }
1326 
1327             this.update();
1328         },
1329         
1330         createObject: function (v){
1331             
1332             let geo = ()=>{
1333                 let mesh = new THREE.Mesh(v.geometry.clone(), v.material.clone());
1334                 mesh.material.transparent = true;
1335                 mesh.castShadow = true;
1336                 mesh.receiveShadow = true;
1337                 mesh.customDepthMaterial = new THREE.MeshDepthMaterial({depthPacking: THREE.RGBADepthPacking});
1338                 
1339                 mesh.HandCreate = {
1340                     SV: null, //view
1341                     GeoCI: v.HandCreate.index, //几何体索引
1342                     MatCI: v.HandCreate.MatIndex,//材质索引
1343                     TexCI: null, //纹理索引
1344                     isSelect: true, //是否可被选取
1345                     position: {x: mesh.position.x, y: mesh.position.y, z: mesh.position.z}, //位移
1346                     rotation: {x: mesh.rotation.x, y: mesh.rotation.y, z: mesh.rotation.z}, //旋转
1347                     scale: {x: mesh.scale.x, y: mesh.scale.y, z: mesh.scale.z}, //缩放
1348                     wireframe: this.addWireframe(mesh) //物体辅助网格线
1349                 };
1350                 
1351                 mesh.HandCreate.SV = new SetView(this, mesh, v);
1352                 
1353                 this.backMesh = mesh;
1354                 
1355                 //console.log(this.intersects.group.children.flat(Infinity));
1356                 //if(this.intersects.group.children.length > 0){this.intersects.group.children[0].add(mesh); return;}
1357                 
1358                 this.add(mesh);
1359                 this.setTarget(mesh);
1360             }
1361             
1362             let mat = ()=>{
1363                 this.Three.updateMaterial(this.material.mesh, v.material);
1364                 this.material.mesh.HandCreate.MatCI = v.HandCreate.index;
1365                 this.update();
1366             }
1367             
1368             let tex = ()=>{
1369                 this.Three.updateTexture(this.texture.mesh.material, v.material.map);
1370                 this.texture.mesh.HandCreate.TexCI = v.HandCreate.index;
1371                 this.update();
1372             }
1373             
1374             switch(v.HandCreate.type){
1375                 case "_Geometry": geo(); break;
1376                 case "_Material": mat(); break;
1377                 case "_Texture": tex(); break;
1378                 default: break;
1379             }
1380             
1381         }
1382         
1383     });
1384     
1385     //代理
1386     /* this.ForCreate = new Proxy(new HandCreate().init(), {
1387         get(o, k){
1388             return o[k];
1389         },
1390         set(o, k, v){
1391             o[k] = v;
1392         }
1393     }); */
1394     
1395     this.ForCreate = new HandCreate().init();
1396     
1397 }).call(this)
Main.js

 

你可能感兴趣的:(javascript 简单的3d网页应用(3d网页可视化编辑器), 搭建几何体 选配材质 纹理 , 导入 导出 示例 ( three.js 初探 六))