1 完整代码下载
https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ
提取码 3fzt (压缩包名: 2020-3-24-demo.zip)
2 图片展示
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 //修改title152 _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 //修改name159 _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.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){//string169 setVal(nameEl[arr[0]], arg[0]);170 171 }else if(typ0 === "object" && Array.isArray(typ0) === false){//object172 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, string178 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 //隐藏gui230 _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 timer number, 可选, 关闭那个 timer块(默认关闭整个Gui)239 _Gui.prototype.close = function (timer){240 if(timer === "auto"){241 242 return this;243 }244 var o = this.info.get(timer);245 if(o === undefined){246 let k;247 for(k = 1; k <= this.timer; k++){248 o = this.info.get(k);249 o.hide = true;250 hide(o.line, o.fel, this.elem, this.info, true);251 }252 }else{253 o.hide = true;254 hide(o.line, o.fel, this.elem, this.info, true);255 }256 return this;257 }258 259 //标记不可用项260 _Gui.prototype.showStop = function (){261 262 this.name(arguments[0], "_Gui_func_showStop", arguments[1], arguments[2]);263 264 return this;265 266 }267 268 //移除gui269 _Gui.prototype.remove = function(object){270 var o = object ? object : this;271 this.__proto__.timerAll_old.push(o.timerAll);272 this.__proto__.objAll.delete(o.timerAll);273 o.objAll.delete(o.timerAll);274 tar.remove(o.elem.bindMove, o.elem);275 delete(o.timerAll);276 delete(o.elem);277 delete(o.info);278 delete(o.timer);279 return;280 }281 282 283 284 285 var tar = new View(), tar_zIndex = {}, _osTitle = null;286 287 //创建视图288 var _start = function (obj, a, b, c, d, id, felem, map, timerAll, objAll){289 290 var fel, line, title, m = map.get(id), k, len, _name, isNewObj = false;291 292 //确认追加 obj293 if(m){294 fel = m.fel;295 if(!obj){296 obj = m.obj;297 }else{298 if(m.objs.has(obj) === false) isNewObj = true;299 m.obj = obj;300 }301 }302 303 if(typeof(obj) !== "object" || !obj){console.log("引用对象错误, 新建块对象为必须"); return;}304 305 //确认参数 (target, title, isBind, range || select) || a = {target, title, isBind, range || select}306 var os = {}, nos = [];307 if(a !== undefined){nos.push(_getispro(obj, a, nos));}308 if(b !== undefined){nos.push(_getispro(obj, b, nos));}309 if(c !== undefined){nos.push(_getispro(obj, c, nos));}310 if(d !== undefined){nos.push(_getispro(obj, d, nos));}311 len = nos.length;312 for(k = 0; k < len; k++){313 if(nos[k] === undefined){314 if(typeof(a) === "object" && Array.isArray(a) === false){os = a;}315 }else{316 let val;317 switch(k){318 case 0 : val = a; break;319 case 1 : val = b; break;320 case 2 : val = c; break;321 case 3 : val = d; break;322 default : break;323 }324 if(val !== undefined){os[nos[k]] = val;}325 }326 }327 328 //确认对象属性 os.target (target 如果为obj 则表示 只设置gui, 不添加控件)329 var arr = [], T = typeof(os.target), A = Array.isArray(os.target);330 if(!os.target){for(k in obj){arr.push(k);}}331 else if(A === true){arr = os.target;}332 else if(T !== "object"){arr.push(os.target);}333 else{return;} 334 //boolean, function, number, text, select, color335 var bs = [], fs = [], ns = [], ts = [], cs = [], ss = [];336 if(Array.isArray(os.select) == true && arr.length === 1){337 ss.push(arr[0]);338 }else if(typeof(os.select) === "object" && Array.isArray(os.select) == false){339 let ks;340 for(ks in os.select){341 len = arr.length;342 for(k = 0; k < len; k++){343 if(ks === arr[k]){ss.push(arr[k]); arr.splice(k, 1);}344 }345 }346 }347 len = arr.length;348 for(k = 0; k < len; k++){349 T = typeof(obj[arr[k]]);350 if(T === "boolean"){bs.push(arr[k]);}351 else if(T === "function"){fs.push(arr[k]);}352 else if(T === "number"){ns.push(arr[k]);}353 else if(T === "string"){354 if(obj[arr[k]].length === 7 && obj[arr[k]].charAt(0) === "#"){cs.push(arr[k]);}//color355 else{ts.push(arr[k]);}//string356 }357 }358 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;359 var lens = bs_len + fs_len + ns_len + ts_len + ss_len + cs_len;360 361 //确认 绑定362 var isB = false;363 if(typeof(os.isBind) === "boolean"){isB = os.isBind;}364 365 //确认 _name366 if(os.title && lens === 1){_name = os.title; delete(os.title);}367 368 //确认 新的块369 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};370 if(!m){371 isNewObj = false;372 line = _line(id, felem);373 fel = _cons(line, id, felem, map);374 title = _title(timerAll, id, _osTitle || os.title, fel);//os.title375 _osTitle = null;376 map.set(id, {377 hide : false,378 line : line, 379 fel : fel, 380 title : title, 381 obj : obj, 382 par : par,383 objs : new Map([[obj, {384 parameter : par,385 callback : {},386 nameEl : {}387 }]])388 });389 m = map.get(id);390 }391 392 //更新 obj393 if(isNewObj === true){394 m.objs.set(obj, {395 parameter : par,396 callback : {},397 nameEl : {}398 });399 }400 401 //更新参数402 m.par = par;403 var objs_g = m.objs.get(obj), pars = objs_g.parameter;404 for(k in os){if(k !== "target"){pars[k] = os[k];}}405 for(k = 0; k < bs_len; k++){if(pars.target.bs.indexOf(bs[k]) === -1){pars.target.bs.push(bs[k]);}}406 for(k = 0; k < fs_len; k++){if(pars.target.fs.indexOf(fs[k]) === -1){pars.target.fs.push(fs[k]);}}407 for(k = 0; k < ns_len; k++){if(pars.target.ns.indexOf(ns[k]) === -1){pars.target.ns.push(ns[k]);}}408 for(k = 0; k < ts_len; k++){if(pars.target.ts.indexOf(ts[k]) === -1){pars.target.ts.push(ts[k]);}}409 for(k = 0; k < ss_len; k++){if(pars.target.ss.indexOf(ss[k]) === -1){pars.target.ss.push(ss[k]);}}410 for(k = 0; k < cs_len; k++){if(pars.target.cs.indexOf(cs[k]) === -1){pars.target.cs.push(cs[k]);}}411 412 //console.log(objs_g.callback);413 //创建视图//os.select os.range os.isBind414 let che, cli, ran, tex, col, sel;415 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];} }416 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];} }417 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];} }418 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];} }419 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];} }420 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];} }421 return {nowObject:obj};422 }423 424 //验证 并 获取 _start 参数425 var _getispro = function (obj, cons, nos){426 var o_t = typeof(cons), o_a = Array.isArray(cons), r;427 if(o_t === "string"){428 if(obj[cons] !== undefined){429 r = "target";430 }else{431 r = "title";432 }433 434 }else if(o_t === "boolean"){435 r = "isBind";436 437 }else if(o_t === "object"){438 let k, len, isT = (arr, type)=>{439 let ct = true;440 len = cons.length;441 for(k = 0; k < len; k++){if(typeof(cons[k]) !== type){ct = false; break;}}442 return ct;443 }444 if(o_a === true){445 if(isT(cons, "string") === true){r = "target";}446 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";}447 else{console.log("忽略了参数");}448 }else{449 let isArr = true;450 for(k in cons){if(Array.isArray(cons[k]) === false){isArr = false; break;}}451 if(isArr === true){452 let ka, isN; 453 for(k in cons){454 len = cons[k].length;455 if(len === 0 || len === 3){456 for(ka = 0; ka < len; ka++){457 if(typeof(cons[k][ka]) !== "number" || isNaN(cons[k][ka]) === true){isN = false; break;}458 }459 if(typeof(obj[k]) !== "number"){isN = false;}460 461 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;}462 }else{463 isN = false;464 break;465 }466 }467 if(isN === false){r = "select";}else{r = "range";}//数组长度为空也判定为 range, 因为range 有默认值468 }else{469 let isSel = true;470 for(k in cons){if(obj[k] === undefined){isSel = false; break;}}471 if(isSel === true){r = "select";}else{console.log("忽略了参数");}472 }473 }474 }475 476 if(nos.indexOf(r) !== -1){console.log("重复了参数"); return;}477 478 return r;479 }480 481 //隐藏视图482 var hide = function (l, f, elem, map, isHide){483 elem.bindMoveIsHideAll = false;484 if(isHide === false){485 l.className = "line-block"; 486 f.style.display = "block";487 elem.className = "Gui box-shadown box-scroll-block";488 elem.bindMove.className = "bindMove_elemCla-up";489 }else{490 l.className = "line-none"; 491 f.style.display = "none"; 492 let isAll = true, con, k, len = map.size;493 for(k = 1; k <= len; k++){494 con = map.get(k).fel.style.display;495 if(con === "" || con === "block"){isAll = false; break;}496 }497 if(isAll === true){498 elem.bindMoveIsHideAll = true;499 elem.className = "Gui-none box-shadown box-scroll-block";500 elem.bindMove.className = "bindMove_elemCla-hidden";501 }502 }503 _setElemPos(elem);504 }505 506 //调整 son(this.elem)的位置507 var _setElemPos = function (son, father){508 if(!father){father = son.bindMove;}509 let s = 0;510 if(son.bindMoveIsHideAll === true) s = 10;511 //son.style.zIndex = "2"; father.style.zIndex = "1"; 512 son.style.left = father.offsetLeft-(son.clientWidth || son.offsetWidth)+(father.clientWidth || father.offsetWidth) +"px";513 son.style.top = father.offsetTop+(father.clientHeight || father.clientHeight)+ s -1 +"px";514 }515 516 //添加 内容 容器517 var _cons = function (line, id, fel, map){518 var f = tar.add(fel, "div", null, "Gui-content"), di;519 tar.addEvent(line, 'click', (e)=>{520 di = map.get(id);521 di.hide = !di.hide;522 hide(line, f, fel, map, di.hide);523 });524 return f;525 }526 527 //添加 标题 ← ↑ → ↓ ↖ ↙ ↗ ↘ ↕528 var _title = function (timerAll, id, title, fel){529 var tf = tar.add(fel, "div");530 var t = tar.add(tf, "p");531 //var ts = tar.add(tf, "p");532 t.innerHTML = ""+timerAll+""+"."+""+id+""+" "+(title || "");533 //ts.style = "height:5px;";534 return t;535 }536 537 //添加 分块线538 var _line = function (id, fel){539 var toper = id === 1 ? 0 : 10;540 var l = tar.add(fel, 'p', null, "line-block");541 l.style= "cursor:pointer; margin-top:" + toper + "px";542 return l;543 }544 545 //创建 绑定 可移动 的html元素546 var addBindMove = function (fel, elemName, id, cls){547 var father = tar.add(fel, "div", null, "bindMove_elemCla-up");548 var son = tar.add(fel, elemName, id, cls);549 550 var isMove = false, sx, sy, tar_input, k, len, path;551 552 //初始化 father 位置553 var getFatherPosition = function (){554 if(!son.offsetLeft || !(son.clientWidth || son.offsetWidth) || !(father.clientWidth || father.offsetWidth)){555 setTimeout(()=>{getFatherPosition(); _setElemPos(son);}, 500);556 console.log("调整father位置");557 return;558 }559 father.style.left = son.offsetLeft + (son.clientWidth || son.offsetWidth) - (father.clientWidth || father.offsetWidth) +"px";560 }561 562 //更新 zIndex563 var setzIndex = function (e){564 path = e.path || (e.composedPath && e.composedPath());565 len = path.length;566 for(k = 0; k < len; k++){567 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"){568 if(tar_zIndex.move && tar_zIndex.elem){tar_zIndex.move.style.zIndex = "1"; tar_zIndex.elem.style.zIndex = "1";}569 tar_zIndex.move = father; tar_zIndex.elem = son;570 tar_zIndex.move.style.zIndex = "2"; tar_zIndex.elem.style.zIndex = "2";571 break;572 }573 }574 }575 tar.addEvent(son, 'click', (e)=>{576 setzIndex(e);577 //if(e.target.type !== undefined){tar_input = e.target; e.target.focus();}else if(tar_input){tar_input.blur();}578 });579 580 //移动581 var down = tar.addEvent(father, 'mousedown', (e)=>{582 setzIndex(e);583 if(e.target.className === "bindMove_elemCla-up" || e.target.className === "bindMove_elemCla-hidden"){584 sx = e.offsetX; sy = e.offsetY;585 if(father.className === "bindMove_elemCla-up") father.className = "bindMove_elemCla-down";586 isMove = true;587 }588 });589 var up = tar.addEvent(father, 'mouseup', (e)=>{590 isMove = false;591 if(father.className === "bindMove_elemCla-down") father.className = "bindMove_elemCla-up";592 tar.removeEvent(father, 'mousedown', down);593 tar.removeEvent(document.body, 'mousemove', move);594 tar.removeEvent(father, 'mouseup', up);595 });596 var move = tar.addEvent(document.body, 'mousemove', (e)=>{597 if(isMove === true){598 father.style.left = e.clientX - sx +"px";599 father.style.top = e.clientY - sy +"px";600 _setElemPos(son, father);601 }602 });603 604 son.bindMove = father;605 son.bindMoveIsHideAll = false;606 //getFatherPosition();607 return son;608 }609 610 var _view = function (obj, arr, fel, isBind, type, name, clas, event_fun, bind_fun){611 612 var p = tar.add(fel, 'p'), info = {p:p, nameEl:{}}, k, len = arr.length, vn = "value", cla = clas || "p-float-"+type;613 var nameer;614 if(type === "checkbox"){vn = "checked";}615 616 var create = (val)=>{617 let _val = obj[val];618 let f = tar.add(p, 'p', null, cla);619 let i = tar.add(f, 'input');620 let fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";621 let s = tar.add(f, 'span');622 fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";623 nameer = val;624 if(type === "color"){nameer = _val;}625 i.type = type;626 i[vn] = _val;627 628 s.innerHTML = name || nameer+"";629 630 tar.addEvent(i, 'change', (e)=>{631 _val = e.target[vn];632 if(!isBind) obj[val] = _val;633 if(type === "color") s.innerHTML = _val;634 if(typeof(event_fun[val]) === "function") event_fun[val](e);635 });636 637 //bind(obj, arr[k], _val, (now)=>{el_f.i.checked = now;});638 if(isBind === true){639 Object.defineProperty(obj, val, {640 get(){return _val;},641 set(v){642 _val = v;643 i[vn] = v;644 if(typeof(bind_fun) === "function"){bind_fun(v);}645 }646 });647 }648 649 info.nameEl[val] = s;650 }651 652 for(k = 0; k < len; k++){create(arr[k]);}653 654 return info;655 }656 657 //添加 text输入框(string)658 var _text = function (obj, arr, fel, isBind, callbacks, name){659 return _view(obj, arr, fel, isBind, "text", name, "p-text", callbacks);660 }661 662 //添加 复选框(boolean)663 var _check = function (obj, arr, fel, isBind, callbacks, name){664 return _view(obj, arr, fel, isBind, "checkbox", name, null, callbacks);665 }666 667 //添加 下拉选项框()668 var _select = function (obj, arr, info, fel, isBind, callbacks, name){669 //小狗670 var infos = {nameEl:{}}, k, len = arr.length;671 672 var create = (val, cons)=>{673 let _val = obj[val];674 let p = tar.add(fel, 'p');675 let f = tar.add(p, 'p', null, "p-float-select");676 let i = tar.add(f, "select");677 let fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";678 let s = tar.add(f, 'span'); s.innerHTML = name || val;679 fgx = tar.add(f, 'input', null, "gui-mesh-fgx"); fgx.readOnly = "true";680 let ka, lena, T = typeof(cons), A = Array.isArray(cons);681 if(T === "object" && A === false){682 for(ka in cons){683 let opt = tar.add(i, "option");684 opt.value = cons[ka];685 opt.innerHTML = ka;686 }687 }else if(A === true){688 lena = cons.length;689 for(ka = 0; ka < lena; ka++){690 if(Array.isArray(cons[ka]) === true && cons[ka].length === 2){691 let opt = tar.add(i, "option");692 opt.value = cons[ka][1];693 opt.innerHTML = cons[ka][0];694 continue;695 }696 let opt = tar.add(i, "option");697 opt.value = cons[ka];698 opt.innerHTML = cons[ka];699 }700 }701 tar.addEvent(i, 'change', (e)=>{702 if(typeof(callbacks[val]) === "function") callbacks[val](e);703 });704 705 infos.nameEl[val] = s;706 }707 708 if(len === 1){709 if(typeof(info) === "object"){710 create(arr[0], info[arr[0]]);711 }else{712 create(arr[0], info);713 }714 }else{715 for(k = 0; k < len; k++){716 create(arr[k], info[arr[k]]);717 }718 }719 720 return infos;721 }722 723 //添加 颜色选择器724 var _color = function (obj, arr, fel, isBind, callbacks, name){725 return _view(obj, arr, fel, isBind, "color", name, null, callbacks);726 }727 728 //添加 按钮(function)729 var _click = function (obj, arr, fel, callbacks, name){730 var p = tar.add(fel, 'p'), info = {p:p, nameEl:{}}, k, len = arr.length, ends = [];731 var create = (val)=>{732 let f = tar.add(p, 'p', null, "p-float-button");733 let i = tar.add(f, 'input');734 i.type = "button";735 i.value = name || val;736 tar.addEvent(i, 'click', ()=>{737 obj[val]();738 if(typeof(callbacks[val]) === "function"){callbacks[val](e);}739 });740 info.nameEl[val] = i;741 }742 for(k = 0; k < len; k++){create(arr[k]);}743 return info;744 }745 746 //添加 计量控制器(number) info: object 可选 默认[min, max, step]747 //注意: number属性的初始值不能 小于min 和 大于max; step不能大于max-min 否则会被判定为 下拉选项框 的参数748 var _range = function (obj, arr, info, fel, isBind, callbacks, timerAll, id, name){749 var create = (val)=>{750 let c = info[val] || di;751 if(obj[val] < c[0] || obj[val] > c[1] || typeof(obj[val]) !== "number" || isNaN(obj[val]) === true){return;}752 let p = tar.add(fel, 'p'), i = tar.add(p, 'input');753 i.type = "range"; i.value = obj[val]; i.min = c[0]; i.max = c[1]; i.step = c[2];754 let nul = tar.add(p, 'span'); nul.innerHTML = " ";755 let is = tar.add(p, 'input'); is.type = "tel"; is.value = obj[val];756 let key = false, x, xs, spva = name || val, s = tar.add(p, 'span'); s.innerHTML = "" + spva;757 let _val = obj[arr[k]];758 759 let getNum = (num)=>{760 //if(num === _val){return _val;}761 if(typeof(num) !== "number" || isNaN(num) === true){762 return _val;763 }764 if(num > c[0] && num < c[1]){765 return num;766 }else if(num > c[0]){767 return c[1];768 }else if(num < c[1]){769 return c[0];770 }771 return _val;772 }773 774 let setNum = (num, e)=>{775 if(num !== undefined){776 i.value = num;777 is.value = num;778 _val = num;779 if(!isBind){obj[val] = _val;}780 if(typeof(callbacks[val]) === "function"){callbacks[val](_val);}781 }782 }783 784 tar.addEvent(is, 'blur', (e)=>{setNum(getNum(Math.round(Number(e.target.value)/c[2])*c[2]), e);});785 tar.addEvent(i, 'change', (e)=>{786 setNum(getNum(e.target.valueAsNumber), e);787 });788 789 if(isBind === true){790 Object.defineProperty(obj, arr[k], {791 get() {return _val;},792 set(v) {793 _val = getNum(Math.round(Number(v)/c[2])*c[2]);794 i.value = _val;795 is.value = _val;796 }797 });798 }799 infos.nameEl[val] = s;800 }801 var di = [0, 100, 1], k, len = arr.length, infos = {p:null, nameEl:{}};802 if(Array.isArray(info) === true){di = info;}803 for(k = 0; k < len; k++){create(arr[k]);}804 return infos;805 }806 807 return _Gui;808 809 })()
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 mesh.geometry.dispose(); 145 mesh.geometry = geometry; 146 }, 147 148 updateMaterial: function (mesh, material){//更换材质 149 if(!mesh || !material){ 150 console.log("_Three: 材质更换失败"); 151 return; 152 } 153 let newMat = material.clone(true); 154 //newMat.color.copy(mesh.material.color); 155 newMat.transparent = true; 156 if(mesh.material.map !== null){this.updateTexture(newMat, mesh.material.map);} 157 mesh.material.dispose(); 158 mesh.material = newMat; 159 }, 160 161 updateTexture: function (material, texture){//更换纹理 162 if(!material || !texture){ 163 console.log("_Three: 纹理更换失败"); 164 return; 165 } 166 let map = new THREE.Texture(texture.image); 167 map.wrapS = THREE.RepeatWrapping; 168 map.wrapT = THREE.RepeatWrapping; 169 map.repeat.set(1, 1); 170 map.minFilter = THREE.NearestFilter; 171 map.magFilter = THREE.NearestFilter; 172 if(material.map !== null){ 173 map.wrapS = material.map.wrapS; 174 map.wrapT = material.map.wrapT; 175 map.repeat.copy(material.map.repeat); 176 map.anisotropy = material.map.anisotropy; 177 material.map.dispose(); 178 } 179 material.map = map; 180 material.map.needsUpdate = true; 181 material.needsUpdate = true; 182 }, 183 184 getBox3: function (mesh){//获取Box3 185 mesh.geometry.computeBoundingBox();//计算mesh获取box3对象 186 return mesh.geometry.boundingBox.applyMatrix4(mesh.matrixWorld); 187 }, 188 189 render: function (scene, camera, renderer){//渲染 190 renderer.render(scene, camera); 191 }, 192 193 getBSP: function (meshA, meshB, type){//剪裁 添加 重合 194 if(!meshA || !meshB || !type || meshA === meshB){console.log("getBSP:参数错误, 请选择1至2个物体进行运算"); return;} 195 if(!meshA.geometry || !meshB.geometry) return; 196 if(meshA.geometry.isGeometry !== true || meshB.geometry.isGeometry !== true) return; 197 let bsp_a = new ThreeBSP(meshA);//生成ThreeBSP对象 198 let bsp_b = new ThreeBSP(meshB);//生成ThreeBSP对象 199 let bsp = bsp_a[type](bsp_b);//进行 type 计算 200 let geo = bsp.toGeometry();//console.log(bsp); 201 geo.computeFaceNormals();//更新geo的面 202 geo.computeVertexNormals();//更新geo的顶点 203 return geo; 204 }, 205 206 toBuffer: function (geometry){//几何体 转为缓存几何体 207 if(geometry.isGeometry !== true) return; 208 return new THREE.BufferGeometry().fromGeometry(geometry); 209 }, 210 211 loadingGLTF: function (url, scene){//导入 212 if(!this.loadGLTF){this.__proto__.loadGLTF = new THREE.GLTFLoader();} 213 if(!scene) return; 214 this.loadGLTF.load(url, (gltf)=>{ 215 scene.add(gltf.scene); 216 }); 217 }, 218 219 exporterGLTF: function (mesh, fileType){//导出物体(限谷歌浏览器) 220 if(!this.exportGLTF){this.__proto__.exportGLTF = new THREE.GLTFExporter();} 221 if(!mesh){console.log("mesh 错误"); return;} 222 // 使用MeshBasicMaterial 或 MeshStandardMaterial 材质 效果会更好 223 //使用 BufferGeometry 缓存几何体 文件体积会更小 224 //if(mesh.geometry.isGeometry === true){mesh.geometry = new THREE.BufferGeometry().fromGeometry(mesh.geometry);} 225 var opt = { 226 binary: fileType || this.exportGLTFFileType || false, 227 embedImages: true, 228 onlyVisible: true, 229 truncateDrawRange: true, 230 trs: false 231 }; 232 var download = ( blob, filename )=>{ 233 let link = _view.add(document.body, "a"); 234 link.style.display = 'none'; 235 link.href = URL.createObjectURL( blob ); console.log(link.href); 236 link.download = filename; 237 link.click(); 238 _view.remove(link); 239 } 240 241 this.exportGLTF.parse(mesh, function ( result ){ 242 if(result instanceof ArrayBuffer){ 243 download(new Blob([result], {type: 'application/octet-stream'}), 'scene.glb'); 244 }else{ 245 download(new Blob([JSON.stringify( result, null, 2 )], {type: 'text/plain'}), 'scene.gltf'); 246 } 247 }, opt); 248 }, 249 250 runRaycaster: function (o, w, h){//光线投射 251 o.result.length = 0; 252 o.vector2.set((o.x / w || _width) * 2 - 1, -(o.y / h || _height) * 2 + 1); 253 o.raycaster.setFromCamera(o.vector2, o.camera); 254 o.raycaster.intersectObjects(o.children, o.recursive, o.result); 255 }, 256 257 createClipPlane: function (handCreate){//添加 面 和 点 剪裁面 258 let pa = new THREE.Plane(new THREE.Vector3( 1, 0, 0 ), 1); 259 let pb = new THREE.Plane(new THREE.Vector3( 0, -1, 0 ), 1); 260 let pc = new THREE.Plane(new THREE.Vector3( 0, 0, -1), 1); 261 let pd = new THREE.Plane(new THREE.Vector3( 0, 1, 1), 1); 262 263 let hg = new THREE.Group(); 264 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)); 265 return { 266 planes: [pa, pb, pc, pd], 267 helpers: hg 268 }; 269 var geometry = new THREE.SphereGeometry(1, 48, 24); 270 var material = new THREE.MeshLambertMaterial({ 271 color: new THREE.Color("#666666"), 272 side: THREE.DoubleSide, 273 clippingPlanes: clipPlane, 274 clipIntersection: true 275 }); 276 console.log(helper0); console.log(material); 277 handCreate.add(new THREE.Mesh(geometry, material), helperGroup); 278 279 handCreate.renderer.localClippingEnabled = true; 280 281 //clipPlane.constant = 0.1; 282 new Gui({constant:0}, [-1, 1, 0.01]) 283 .change((val)=>{ 284 for(let k = 0; k < clipPlane.length; k++){ 285 clipPlane[k].constant = val; 286 } 287 handCreate.update(); 288 }) 289 .add(material, "clipIntersection") 290 .add(helper0, "size", [0, 10, 0.1]) 291 .change(()=>{handCreate.update();}) 292 } 293 294 }); 295 296 297 298 //几何体 299 var _Geometry = function (){ 300 _Three.call(this); 301 //this.width = 100; _width 302 this.height = 100; 303 this.y = this.campos.y; 304 this.dis = 0.5; 305 this.backMesh = {distance: 0, nowDistance: 0}; 306 this.targetChange = null; 307 this.objects = []; 308 } 309 310 _Geometry.prototype = Object.assign(Object.create(_Three.prototype), { 311 312 constructor: _Geometry, 313 314 config: [ 315 new THREE.BoxGeometry(1, 1, 1, 1, 1, 1), 316 new THREE.SphereGeometry(0.5, 8 , 6, 0, Math.PI * 2, 0, Math.PI), 317 new THREE.PlaneGeometry(1, 1, 1, 1) 318 ], 319 320 campos: {x: _width/110, y: 0, z: 1.5}, 321 322 isGoToPosition: true, 323 324 defaultMaterial: new THREE.MeshBasicMaterial({wireframe: true}), 325 326 init: function (){//初始化 327 if(this.scene === undefined) this.addScene(); 328 if(this.show === undefined) this.setShow(); 329 if(this.target === undefined) this.setTarget(); 330 this.renderView(this.config); 331 return this; 332 }, 333 334 addScene: function (){//添加 场景 335 let elem = _view.add(document.body, "div", null, "ShowObject box-scroll-block"); 336 _view.addEvent(elem, 'click', (e)=>{this.addTarget(e);}); 337 338 let scene = this.createScene(0x000000, false); 339 var camera = new THREE.OrthographicCamera(_width/-100, _width/100, this.height/100, this.height/-100, 0.1, 10); 340 camera.lookAt(0, 0, 0); 341 let renderer = this.createRenderer(elem, _width, this.height, true, true, true, true); 342 let linghts = this.addLinghts(scene); 343 let drag = new THREE.DragControls(scene.children, camera, renderer.domElement); 344 drag.enabled = false; 345 this.__proto__.scene = {e: elem, s:scene, c: camera, r: renderer, l: linghts, drag: drag, target: null} 346 drag.enabled = false; 347 drag.addEventListener('drag', (e)=>{ 348 this.update(); 349 }); 350 drag.addEventListener('hoveron', (e)=>{ 351 if(drag.enabled === true) return; 352 this.scene.target = e.object; 353 }); 354 drag.addEventListener('hoveroff', ()=>{ 355 this.scene.target = null; 356 }); 357 358 this.goToPosition(); 359 }, 360 361 addLinghts: function (scene){//重写添加灯光 362 let a = new THREE.AmbientLight(0x696969); 363 let b = new THREE.DirectionalLight(0xFFFFFF, 1); 364 b.position.set(0, 5, 5); 365 scene.add(a, b); 366 return [a, b]; 367 }, 368 369 goToPosition: function (){//跳转到 geometry 坐标 370 if(this.isGoToPosition === false) return; 371 this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z); 372 this.update(); 373 }, 374 375 setPos: function (mesh, k){//renderView-> 设置物体之间的距离 376 mesh.position.set(this.backMesh.distance, this.y, 0); 377 //let size = box3.getSize(new THREE.Vector3()); 378 let box3 = this.getBox3(mesh); 379 let width = box3.getSize(new THREE.Vector3()).x; 380 let center = box3.getCenter(new THREE.Vector3()).x; 381 382 //let dtp = box3.distanceToPoint(new THREE.Vector3(this.backMesh.distance, this.y, 0)); 383 //console.log(width); 384 this.backMesh.distance += width + this.dis; 385 386 //this.backMesh.left = this.backMesh.distance - width + center; 387 388 //this.backMesh.nowDistance = width / 2 - center + this.backMesh.distance; 389 //var helper = new THREE.Box3Helper(box3, 0xffff00); 390 //helper.position.copy(mesh.position); 391 //this.scene.s.add(helper); 392 393 //console.log(this.backMesh) 394 //console.log(width, center); 395 }, 396 397 addMesh: function (object, key){//renderView-> 添加物体 398 let mesh = new THREE.Mesh(object, this.defaultMaterial); 399 mesh.HandCreate = {type: "_Geometry", index: key, MatIndex: 0} 400 this.scene.s.add(mesh); 401 return mesh; 402 }, 403 404 renderView: function (arr){//渲染场景视图 405 for(let k = 0; k < arr.length; k++){ 406 let mesh = this.addMesh(arr[k], k); 407 this.setPos(mesh, k); 408 this.objects.push(mesh); 409 } 410 this.update(); 411 }, 412 413 setShow: function (){//是否显示场景的html元素 414 let _show = false; 415 Object.defineProperties(this.__proto__, { 416 show: { 417 get:()=>{return _show;}, 418 set:(v)=>{ 419 if(v === true){ 420 this.scene.e.style.display = "block"; 421 }else{ 422 this.scene.e.style.display = "none"; 423 } 424 _show = v; 425 } 426 } 427 }); 428 }, 429 430 addTarget: function (e){//addScene event->场景html元素的事件回调函数 431 if(!this.scene.target) return; 432 this.target = this.scene.target; 433 }, 434 435 setTarget: function (){//配置 target 436 let _target = null; 437 Object.defineProperties(this.__proto__, { 438 target: { 439 get:()=>{return _target;}, 440 set:(v)=>{ 441 if(typeof(this.targetChange) === "function") this.targetChange(v); 442 _target = v; 443 } 444 } 445 }); 446 }, 447 448 exportObject: function (){//导出 几何体 449 450 }, 451 452 importObject: function (object){//导入 几何体 453 if(object.isGeometry !== true) return; 454 let nowKey = this.config.length; 455 let mesh = this.addMesh(object, nowKey); 456 this.setPos(mesh, nowKey); 457 this.config.push(object); 458 this.objects.push(mesh); 459 this.update(); 460 }, 461 462 update: function (){//更新场景 463 this.render(this.scene.s, this.scene.c, this.scene.r); 464 }, 465 466 updateObjectColors: function (color){ 467 for(let k = 0; k < this.objects.length; k++){ 468 this.objects[k].material.color.set(color); 469 } 470 this.update(); 471 }, 472 473 debugCamera: function (){//gui调试 正交相机 474 let c = this.scene.c; 475 let pos = {x: _width/110, y: 0, lookAt: true, position: false}; 476 let upd = ()=>{ 477 if(pos.lookAt) c.lookAt(pos.x, pos.y, 0); 478 if(pos.position) c.position.set(pos.x, pos.y, 5); 479 this.update(); 480 } 481 482 new Gui(pos, [0, 10, 0.1], "调试正交相机") 483 .change({ 484 x: (v)=>{pos.x = v; upd();}, 485 y: (v)=>{pos.y = v; upd();} 486 }) 487 488 } 489 490 }); 491 492 493 494 //材质 495 var _Material = function (){ 496 _Geometry.call(this); 497 } 498 499 _Material.prototype = Object.assign(Object.create(_Geometry.prototype), { 500 501 constructor: _Material, 502 503 config:[ 504 new THREE.MeshBasicMaterial(), 505 new THREE.MeshLambertMaterial(), 506 new THREE.MeshStandardMaterial() 507 ], 508 509 defaultGeometry: new THREE.BoxGeometry(1, 1, 1, 1, 1, 1), 510 511 campos: {x: _width/110, y: 1.5, z: 1.5}, 512 513 addMesh: function (object, key){ 514 let mesh = new THREE.Mesh(this.defaultGeometry, object); 515 mesh.HandCreate = {type: "_Material", index: key}; 516 this.scene.s.add(mesh); 517 return mesh; 518 }, 519 520 goToPosition: function (mesh){ 521 if(!mesh || this.isGoToPosition === false) return; this.mesh = mesh; 522 let geometry = _Geometry.prototype.config[mesh.HandCreate.GeoCI].clone(); 523 for(let k = 0; k < this.objects.length; k++){ 524 this.updateGeometry(this.objects[k], geometry); 525 } 526 this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z); 527 this.update(); 528 } 529 530 }); 531 532 533 534 //纹理 map 535 var _Texture = function (){ 536 _Material.call(this); 537 this.textureLen = 12; 538 this.setTexture(); 539 } 540 541 _Texture.prototype = Object.assign(Object.create(_Material.prototype), { 542 543 constructor: _Texture, 544 545 config: [], 546 547 campos: {x: _width/110, y: 3, z: 1.5}, 548 549 defaultMaterial: new THREE.MeshBasicMaterial(), 550 551 load: new THREE.TextureLoader(), 552 553 loaded: 0, 554 555 setTexture: function (){ 556 let k, texture; 557 for(k = 0; k < this.textureLen; k++){ 558 texture = this.load.load("img/texture/"+k+".jpg", ()=>{this.__proto__.loaded++;}); 559 texture.wrapS = THREE.RepeatWrapping; 560 texture.wrapT = THREE.RepeatWrapping; 561 texture.repeat.set(1, 1); 562 this.__proto__.config.push(texture); 563 } 564 if(this.loaded !== this.textureLen){this.awaitLoad();} 565 }, 566 567 awaitLoad: function (){ 568 let interval = setInterval(()=>{ 569 if(this.loaded === this.textureLen){ 570 this.update(); 571 clearInterval(interval); 572 console.log("load texture: "+this.loaded+"/"+this.textureLen); 573 }else{ 574 console.log("load texture: "+this.loaded+"/"+this.textureLen); 575 } 576 }, 300); 577 }, 578 579 addMesh: function (object, key){ 580 let mesh = new THREE.Mesh(this.defaultGeometry, new THREE.MeshBasicMaterial({map: object})); 581 //let mesh = new THREE.Mesh(this.defaultGeometry, this.defaultMaterial); 582 //this.updateTexture(mesh, object); 583 mesh.HandCreate = {type: "_Texture", index: key}; 584 this.scene.s.add(mesh); 585 return mesh; 586 }, 587 588 goToPosition: function (mesh){ 589 if(!mesh || this.isGoToPosition === false) return; this.mesh = mesh; 590 let geometry = _Geometry.prototype.config[mesh.HandCreate.GeoCI].clone(); 591 let material = _Material.prototype.config[mesh.HandCreate.MatCI].clone(); 592 for(let k = 0; k < this.objects.length; k++){ 593 this.updateGeometry(this.objects[k], geometry); 594 this.updateMaterial(this.objects[k], material); 595 } 596 this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z); 597 this.update(); 598 } 599 600 }); 601 602 //物体 603 var _Mesh = function (){} 604 605 //gui 606 var SetView = function (HC, newMesh, oldMesh){ 607 this.HC = HC; 608 this.newMesh = newMesh; 609 this.oldMesh = oldMesh; 610 return this.init(); 611 } 612 613 Object.assign(SetView.prototype, { 614 615 constructor: SetView, 616 617 init: function (){ 618 if(this.globalGui === undefined) this.createGlobal(); 619 this.gui = new Gui().display("none"); 620 621 this.createMesh(); 622 this.createGeometry(); 623 this.createMaterial(); 624 return this; 625 }, 626 627 createMesh: function (){ 628 let o = { 629 exportGltf: ()=>{this.HC.Three.exporterGLTF(this.newMesh);}, 630 removeMesh: ()=>{this.HC.remove(this.newMesh);}, 631 getBSP: "intersect", 632 runGetBSP: ()=>{ 633 if(this.HC.targets[0] === undefined){console.log("请在global里勾选'选择物体'选项进行选择物体"); return;} 634 let meshB = this.HC.targets[0].mesh; 635 if(this.newMesh === meshB && this.HC.targets[1] !== undefined) meshB = this.HC.targets[1].mesh; 636 this.HC.geometry.importObject(this.HC.Three.getBSP(this.newMesh.clone(true), meshB.clone(true), o.getBSP)); 637 this.HC.removeTargets(); //this.HC.isSelectTargets = false; 638 } 639 } 640 let m = { 641 visible: this.newMesh.visible, 642 frustumCulled: this.newMesh.frustumCulled, 643 castShadow: this.newMesh.castShadow, 644 receiveShadow: this.newMesh.receiveShadow, 645 } 646 647 this.gui.create(m, true).name({visible: "显示物体", castShadow: "投射阴影", receiveShadow: "接收阴影"}) 648 .change({ 649 visible: ()=>{ 650 if(this.newMesh.visible === undefined) return; 651 this.newMesh.visible = m.visible; 652 this.HC.update(); 653 }, 654 frustumCulled: ()=>{ 655 if(this.newMesh.frustumCulled === undefined) return; 656 this.newMesh.frustumCulled = m.frustumCulled; 657 this.HC.update(); 658 }, 659 castShadow: ()=>{ 660 if(this.newMesh.castShadow === undefined) return; 661 this.newMesh.castShadow = m.castShadow; 662 this.HC.update(); 663 }, 664 receiveShadow: ()=>{ 665 if(this.newMesh.receiveShadow === undefined) return; 666 this.newMesh.receiveShadow = m.receiveShadow; 667 this.HC.update(); 668 } 669 }) 670 671 .add(o, {getBSP:[["交集", "intersect"], ["并集", "union"], ["差集", "subtract"]]}, true) 672 .name({exportGltf: "导出物体", removeMesh: "移除物体", getBSP: "布尔运算类型(选择一个物体)", runGetBSP: "布尔运算"}) 673 .change({ 674 getBSP: (e)=>{o.getBSP = e.target.value;} 675 }) 676 677 .add(this.newMesh.HandCreate.position, true, [-(_maxDistance/2), _maxDistance/2, _minDistance]) 678 .name({x: "位置X轴", y: "位置Y轴", z: "位置Z轴"}) 679 .change({ 680 x: (v)=>{this.newMesh.position.x = v; this.HC.update();}, 681 y: (v)=>{this.newMesh.position.y = v; this.HC.update();}, 682 z: (v)=>{this.newMesh.position.z = v; this.HC.update();} 683 }) 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)=>{this.newMesh.rotation.x = v; this.HC.update();}, 689 y: (v)=>{this.newMesh.rotation.y = v; this.HC.update();}, 690 z: (v)=>{this.newMesh.rotation.z = v; this.HC.update();} 691 }) 692 693 .add(this.newMesh.HandCreate.scale, true, [-(_maxDistance * 0.5), _maxDistance * 0.5, _minDistance]) 694 .name({x: "缩放X轴", y: "缩放Y轴", z: "缩放Z轴"}) 695 .change({ 696 x: (v)=>{this.newMesh.scale.x = v; this.HC.update();}, 697 y: (v)=>{this.newMesh.scale.y = v; this.HC.update();}, 698 z: (v)=>{this.newMesh.scale.z = v; this.HC.update();} 699 }) 700 701 .add(this.newMesh.HandCreate, "isSelect", true, "是否可选取").change(()=>{this.HC.removeTarget(this.newMesh);}) 702 703 .title("物体-"+this.newMesh.type+"-"+this.newMesh.id); 704 }, 705 706 createGeometry: function (){ 707 if(this.oldMesh.geometry.parameters === undefined){console.log("SetView: 忽略了geometry"); return;} 708 let o, p = {}, geo; 709 for(let k in this.oldMesh.geometry.parameters){p[k] = this.oldMesh.geometry.parameters[k];} 710 switch(this.oldMesh.geometry.type){ 711 712 case "BoxGeometry": 713 o = { 714 width:[0.1, 10, 0.1], 715 height:[0.1, 10, 0.1], 716 depth:[0.1, 10, 0.1], 717 widthSegments:[1, 30, 1], 718 heightSegments:[1, 30, 1], 719 depthSegments:[1, 30, 1] 720 } 721 this.gui.create(p, o, true) 722 .name({width: "宽度", height: "高度", depth: "深度", widthSegments: "宽段数", heightSegments: "高段数", depthSegments: "深段数"}) 723 .change(()=>{ 724 geo = new THREE.BoxGeometry(p.width, p.height, p.depth, p.widthSegments, p.heightSegments, p.depthSegments); 725 this.HC.Three.updateGeometry(this.newMesh, geo); 726 this.HC.update(); 727 }); 728 729 break; 730 731 case "SphereGeometry": 732 o = { 733 radius:[0.1, 10, 0.1], 734 widthSegments:[1, 30, 1], 735 heightSegments:[1, 30, 1], 736 phiStart:[0, Math.PI*2, 0.1], 737 phiLength:[0, Math.PI*2, 0.1], 738 thetaStart:[0, Math.PI*2, 0.1], 739 thetaLength:[0, Math.PI*2, 0.1] 740 } 741 this.gui.create(p, o, true) 742 .name({radius: "半径", widthSegments: "宽段数", heightSegments: "高段数", phiStart: "经线起始角度", phiLength: "经线起始角度大小", thetaStart: "纬线起始角度", thetaLength: "纬线起始角度大小",}) 743 .change(()=>{ 744 geo = new THREE.SphereGeometry(p.radius, p.widthSegments, p.heightSegments, p.phiStart, p.phiLength, p.thetaStart, p.thetaLength); 745 this.HC.Three.updateGeometry(this.newMesh, geo); 746 this.HC.update(); 747 }); 748 749 break; 750 751 case "PlaneGeometry": 752 o = { 753 width: [1, 100, 0.1], 754 height: [1, 100, 0.1], 755 widthSegments: [1, 30, 1], 756 heightSegments: [1, 30, 1] 757 } 758 this.gui.create(p, o, true) 759 .name({width: "宽度", height: "高度", widthSegments: "宽段数", heightSegments: "高段数"}) 760 .change(()=>{ 761 geo = new THREE.PlaneGeometry(p.width, p.height, p.widthSegments, p.heightSegments); 762 this.HC.Three.updateGeometry(this.newMesh, geo); 763 this.HC.update(); 764 }); 765 break; 766 767 default : break; 768 } 769 this.gui.title("几何体-"+this.newMesh.geometry.type+"-"+this.newMesh.id); 770 }, 771 772 createMaterial: function (){ 773 let mat = this.newMesh.material; 774 let o = { 775 color: "#" + mat.color.getHexString(), 776 emissive: mat.emissive === undefined ? "#000000" : "#" + mat.emissive.getHexString(), 777 updateMaterial: ()=>{this.HC.material.goToPosition(this.newMesh);}, 778 updateTexture: ()=>{this.HC.texture.goToPosition(this.newMesh);} 779 } 780 let m = { 781 wireframe: mat.wireframe, 782 visible: mat.visible, 783 side: mat.side, 784 fog: mat.fog, 785 aoMapIntensity: mat.aoMapIntensity, 786 colorWrite: mat.colorWrite, 787 transparent: mat.transparent, 788 opacity: mat.opacity, 789 alphaTest: mat.alphaTest, 790 flatShading: mat.flatShading, 791 emissiveIntensity: mat.emissiveIntensity === undefined ? 0 : mat.emissiveIntensity, 792 repeatU: 1, 793 repeatV: 1, 794 anisotropy: 1 795 } 796 797 let num = { 798 aoMapIntensity: [0, 1, 0.1], 799 opacity: [0, 1, 0.1], 800 alphaTest: [0, 1, 0.1], 801 emissiveIntensity: [0, 1, 0.1], 802 repeatU: [1, 100, 1], 803 repeatV: [1, 100, 1], 804 anisotropy: [1, this.HC.renderer.capabilities.getMaxAnisotropy() || 2, 1] 805 }; 806 let sel = { 807 side: [["外面", THREE.FrontSide], ["里面", THREE.BackSide], ["双面", THREE.DoubleSide]] 808 }; 809 let name = { 810 wireframe:"网格模式", 811 visible:"显示材质", 812 side: "材质显示那一面", 813 fog: "受雾气影响", 814 aoMapIntensity: "遮挡效果", 815 colorWrite: "渲染颜色", 816 transparent: "渲染透明度", 817 opacity: "透明度", 818 alphaTest: "alpha值", 819 flatShading: "平面着色", 820 emissiveIntensity: "放射光强度", 821 repeatU: "重复量,纹理U面", 822 repeatV: "重复量,纹理V面", 823 anisotropy: "纹理清晰度" 824 }; 825 let c = { 826 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();}, 827 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();}, 828 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();}, 829 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();}, 830 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();}, 831 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();}, 832 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();}, 833 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();}, 834 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();}, 835 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();}, 836 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();}, 837 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();}, 838 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();}, 839 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();}, 840 841 }; 842 843 this.gui.create(m, num, true, sel).name(name).change(c) 844 845 .add(o, true) 846 .name({color: "材质颜色", emissive: "放射光颜色", updateMaterial: "替换材质", updateTexture: "替换纹理"}) 847 .change({ 848 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();}, 849 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();} 850 }) 851 852 .title("材质-"+this.newMesh.material.type+"-"+this.newMesh.id); 853 }, 854 855 createGlobal: function (){ 856 let o = { 857 setMode: "translate", 858 exportAll: ()=>{console.log("导出全部物体")}, 859 updateMaterialAll: ()=>{console.log("替换全部材质")}, 860 isgltf: true, 861 dragEnabled: false, 862 addMesh: ()=>{this.HC.geometry.goToPosition();} 863 } 864 865 let gui = new Gui(this.HC.geometry, "show", "显示选项栏") 866 867 .add(o, true, {dragEnabled: [["创建模式", false], ["编辑模式", true]], isgltf: [[".gltf", false], [".glb", true]], setMode: [["平移", "translate"], ["旋转", "rotate"], ["缩放", "scale"]]}) 868 .name({exportAll: "导出全部物体", updateMaterialAll: "替换全部材质", setMode: "控制模式", isgltf: "导出类型", addMesh: "添加物体", dragEnabled: "底部物体选项栏的状态(创建 或 调整其位置)"}) 869 .change({ 870 isgltf: (e)=>{this.HC.Three.exportGLTFFileType = eval(e.target.value);}, 871 setMode: (e)=>{this.HC.control.transform.setMode(e.target.value);}, 872 dragEnabled: (e)=>{ 873 let ty = "geometry"; 874 if(this.HC.geometry.scene.c.position.y === this.HC.material.campos.y){ty = "material";} 875 else if(this.HC.geometry.scene.c.position.y === this.HC.texture.campos.y){ty = "texture";} 876 877 this.HC.geometry.scene.drag.enabled = eval(e.target.value); 878 if(this.HC.geometry.scene.drag.enabled === true){ 879 this.HC.geometry.__proto__.isGoToPosition = false; 880 this.HC[ty].updateObjectColors(0xff0000); 881 }else{ 882 this.HC[ty].updateObjectColors(0xffffff); 883 this.HC.geometry.__proto__.isGoToPosition = true; 884 } 885 886 } 887 }) 888 889 .add(this.HC, true, ["lockTarget", "isSelectTargets"]) 890 .name({lockTarget: "是否可选取", isSelectTargets: "标记物体"}) 891 .change({ 892 isSelectTargets: ()=>{ 893 if(this.HC.isSelectTargets === false){ 894 this.HC.removeTargets(); 895 } 896 897 }, 898 lockTarget: ()=>{ 899 if(this.HC.lockTarget === false){ 900 this.HC.removeTargets(); 901 } 902 } 903 }) 904 905 .setPos(310, 10) 906 907 .title("global"); 908 909 this.__proto__.globalGui = gui; 910 } 911 912 }); 913 914 915 916 //main 917 var HandCreate = function (){ 918 this.Three = new _Three(); 919 this.group = new THREE.Group(); 920 this.target = {}; 921 this.isSelectTargets = false; 922 this.targets = []; 923 this.backMesh = null; 924 this.lockTarget = false; 925 this.scene = this.Three.createScene([], false); 926 this.renderer = this.Three.createRenderer(document.body, _width, _height, true, true, true, true); 927 928 } 929 930 Object.assign(HandCreate.prototype, { 931 932 constructor: HandCreate, 933 934 init: function (){ 935 this.intersects = { 936 raycaster: new THREE.Raycaster(), 937 group: new THREE.Group(), 938 vector2: new THREE.Vector2(), 939 result: [], 940 camera: this.camera, 941 recursive: true, 942 x: 0, 943 y: 0, 944 }; 945 this.renderer.domElement.style = "position:absolute; top:0; left:0";//如果不定位, gui的移动块会不正常显示 946 //this.renderer.localClippingEnabled = true;//是否渲染 平面剪裁 947 this.camera = this.Three.createCamera(45, _width, _height, _minDistance, _maxDistance * _minDistance * 0.2); 948 this.camera.position.set(0, _maxDistance * 0.001, _maxDistance * 0.001); 949 this.linghts = this.Three.addLinghts(this.scene, this); 950 this.control = this.Three.addControls(this.scene, this.camera, this.renderer, this.intersects.group.children, this); 951 this.control.drag.addEventListener('hoveron', (e)=>{this.setTarget(e.object);}); 952 this.control.transform.addEventListener('change', ()=>{ 953 if(!this.target || !this.target.mesh || !this.target.mesh.HandCreate){return;} 954 let type = this.control.transform.getMode(); 955 switch(type){ 956 case "translate": 957 this.target.mesh.HandCreate.position.x = this.target.mesh.position.x; 958 this.target.mesh.HandCreate.position.y = this.target.mesh.position.y; 959 this.target.mesh.HandCreate.position.z = this.target.mesh.position.z; 960 break; 961 962 case "rotate": 963 this.target.mesh.HandCreate.rotation.x = this.target.mesh.rotation.x; 964 this.target.mesh.HandCreate.rotation.y = this.target.mesh.rotation.y; 965 this.target.mesh.HandCreate.rotation.z = this.target.mesh.rotation.z; 966 break; 967 968 case "scale": 969 this.target.mesh.HandCreate.scale.x = this.target.mesh.scale.x; 970 this.target.mesh.HandCreate.scale.y = this.target.mesh.scale.y; 971 this.target.mesh.HandCreate.scale.z = this.target.mesh.scale.z; 972 break; 973 974 default: break; 975 } 976 this.update(); 977 }); 978 979 this.geometry = new _Geometry().init(); 980 this.geometry.targetChange = (v)=>{this.createObject(v);}; 981 this.geometry.show = true; 982 983 this.material = new _Material().init(); 984 985 this.texture = new _Texture().init(); 986 987 this.gridHelper = new THREE.GridHelper(_maxDistance, _maxDistance/1); 988 this.scene.add(this.group, this.intersects.group, this.camera, this.gridHelper); 989 990 //this.clip = this.Three.createClip(); 991 //this.globalView(); 992 //this.Three.loadingGLTF("img/gltfs/scene.gltf", this.intersects.group); 993 //this.Three.loadingGLTF("img/gltfs/scene.glb", this.intersects.group); 994 return this; 995 }, 996 997 add: function (mesh, group){ 998 if(!mesh) return; 999 let gro = group || this.intersects.group;1000 if(Array.isArray(mesh) === true){1001 let k, len = mesh.length;1002 for(k; k < len; k++){1003 if(!mesh[k]) continue;1004 gro.add(mesh[k]);1005 }1006 }else{1007 gro.add(mesh);1008 }1009 this.update();1010 },1011 1012 remove: function (mesh, group){1013 if(!mesh){console.log("remove: mesh不存在"); return;}1014 let arr = group || this.intersects.group;1015 if(!arr.remove){console.log("remove: group错误"); return;}1016 this.removeTarget();1017 if(mesh.gui) mesh.gui.remove();1018 mesh.HandCreate.SV.gui.remove();1019 if(mesh.material.map){mesh.material.map.dispose();}1020 mesh.material.dispose();1021 mesh.geometry.dispose();1022 arr.remove(mesh);1023 this.update();1024 },1025 1026 update: function (){1027 this.Three.render(this.scene, this.camera, this.renderer);1028 },1029 1030 setTarget: function (mesh){1031 if(mesh.HandCreate.isSelect === false) return;1032 if(this.isSelectTargets === true) this.setTargets(mesh);1033 if(this.target.mesh === mesh || this.lockTarget === true) return;1034 if(mesh.HandCreate === undefined || mesh.HandCreate.SV === undefined){1035 mesh.HandCreate.isSelect = false;1036 this.lockTarget = true; 1037 console.log("setTarget: mesh 错误,取消选择"); 1038 return;1039 }1040 1041 this.removeTarget();1042 1043 this.target.mesh = mesh;1044 this.control.transform.attach(mesh);1045 mesh.HandCreate.SV.gui.display("block");1046 this.geometry.goToPosition();1047 this.update();1048 },1049 1050 removeTarget: function (){1051 if(!this.target.mesh) return;1052 this.control.transform.detach(this.target.mesh);1053 this.target.mesh.HandCreate.SV.gui.display("none");1054 delete(this.target.mesh);1055 this.update();1056 },1057 1058 setTargets: function (mesh){1059 //if(this.targets.indexOf(mesh) !== -1){return;}1060 for(let k = 0; k < this.targets.length; k ++){if(this.targets[k].mesh === mesh){return;}}1061 this.isSelectTargets = true;1062 this.lockTarget = true;1063 this.targets.push({mesh: mesh, color: mesh.material.color.getHex()}); 1064 mesh.material.color.set("red");1065 this.update();1066 },1067 1068 removeTargets: function (){1069 this.isSelectTargets = false;1070 this.lockTarget = false;1071 for(let k = 0; k < this.targets.length; k++){1072 this.targets[k].mesh.material.color.set(this.targets[k].color);1073 }1074 this.targets.length = 0; 1075 this.update();1076 },1077 1078 createObject: function (v){1079 1080 let geo = ()=>{1081 let mesh = new THREE.Mesh(v.geometry.clone(), v.material.clone());1082 mesh.material.transparent = true;1083 mesh.castShadow = true;1084 mesh.receiveShadow = true;1085 mesh.customDepthMaterial = new THREE.MeshDepthMaterial({depthPacking: THREE.RGBADepthPacking});1086 1087 mesh.HandCreate = {1088 SV: null,1089 GeoCI: v.HandCreate.index, 1090 MatCI: v.HandCreate.MatIndex,1091 TexCI: null,1092 isSelect: true,1093 position: {x: mesh.position.x, y: mesh.position.y, z: mesh.position.z},1094 rotation: {x: mesh.rotation.x, y: mesh.rotation.y, z: mesh.rotation.z},1095 scale: {x: mesh.scale.x, y: mesh.scale.y, z: mesh.scale.z}1096 };1097 1098 mesh.HandCreate.SV = new SetView(this, mesh, v);1099 1100 this.backMesh = mesh;1101 1102 this.add(mesh);1103 this.setTarget(mesh);1104 }1105 1106 let mat = ()=>{1107 this.Three.updateMaterial(this.material.mesh, v.material);1108 this.material.mesh.HandCreate.MatCI = v.HandCreate.index;1109 this.update();1110 }1111 1112 let tex = ()=>{1113 this.Three.updateTexture(this.texture.mesh.material, v.material.map);1114 this.texture.mesh.HandCreate.TexCI = v.HandCreate.index;1115 this.update();1116 }1117 1118 switch(v.HandCreate.type){1119 case "_Geometry": geo(); break;1120 case "_Material": mat(); break;1121 case "_Texture": tex(); break;1122 default: break;1123 }1124 1125 }1126 1127 });1128 1129 //代理1130 /* this.ForCreate = new Proxy(new HandCreate().init(), {1131 get(o, k){1132 return o[k];1133 },1134 set(o, k, v){1135 o[k] = v;1136 }1137 }); */1138 1139 this.ForCreate = new HandCreate().init();1140 1141 }).call(this)
Copyright © 2004-2024 Ynicp.com 版权所有 法律顾问:建纬(昆明)律师事务所 昆明市网翼通科技有限公司 滇ICP备08002592号-4