欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-19 10:14:40
1 完整代码下载 https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ 提取码 3fzt (压缩包名: 2020-3-24-demo.zip) 2 图片展示 3 主要代码 布尔运算后的物体的几何体会自动 导入到 几何体列表选项中, 可*选配 挺简单的 都是 ......

1 完整代码下载

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

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

2 图片展示

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

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

 

 

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

3 主要代码

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

  挺简单的 都是中文

   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     var _view = new view().initbody();
  14     var _width = _view.size.w;
  15     var _height = _view.size.h;
  16     var _mindistance = 0.1;
  17     var _maxdistance = 5000;
  18     
  19     //three
  20     var _three = function (){}
  21     
  22     object.assign(_three.prototype, {
  23         
  24         constructor: _three,
  25         
  26         depthmaterial: new three.meshdepthmaterial({depthpacking: three.rgbadepthpacking}),
  27         
  28         createscene: function (bg, fog){//场景
  29             let scene = new three.scene();
  30             if(typeof(bg) === "number"){scene.background = bg;}
  31             else if(array.isarray(bg) === true){
  32                 scene.background = new three.cubetextureloader()
  33                 .setpath('img/cube/skyboxsun25deg/')
  34                 .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
  35             }
  36             if(fog) scene.fog = new three.fog(fog.color, fog.near, fog.far);
  37             return scene;
  38         },
  39         
  40         createcamera: function (fov, width, height, near, far){//相机
  41             let w = width === undefined ? _width : width;
  42             let h = height === undefined ? _height : height;
  43             let camera = new three.perspectivecamera(fov || 45, w / h, near || _mindistance, far || _mindistance * 1000);
  44             camera.position.set(0, 0, _maxdistance * 0.001);
  45             camera.lookat( 0, 0, 0 );
  46             return camera;
  47         },
  48         
  49         createrenderer: function (felem, width, height, antialias, lights, shadow, checkshadererrors){//渲染器
  50             let fel = felem || document.body;
  51             let renderer = new three.webglrenderer({
  52                 antialias : antialias || false, //抗割齿
  53                 powerpreference:"high-performance" //选择高性能gpu渲染
  54             });
  55             renderer.setsize(width || _width, height || _height);
  56             renderer.setpixelratio(window.devicepixelratio);
  57             renderer.gammafactor = 2.2; //着色校正
  58             renderer.physicallycorrectlights = lights || false; //使其精确照明
  59             renderer.shadowmap.enabled = shadow || false; //渲染阴影
  60             renderer.debug.checkshadererrors = checkshadererrors || false; //
  61             if(!renderer.extensions.get('webgl_depth_texture')){console.log("深度纹理扩展获取失败:webgl_depth_texture");}
  62             fel.appendchild(renderer.domelement);
  63             return renderer;
  64         },
  65         
  66         addlinghts: function (scene, hc){//灯光
  67             let a = new three.ambientlight(0x696969);//环境光(无处不在的光,太阳光)
  68             
  69             let b = new three.directionallight(0xffffff, 1);//平行光(产生阴影的光)
  70             b.position.set(0, 50, 50);//位置
  71             b.castshadow = true;// 产生动态阴影
  72             //b.target = object3d; //平行光的方向是从它的位置到目标位置。默认的目标位置为原点 (0,0,0)。
  73             b.shadow.radius = 1;//使阴影边缘变模糊
  74             b.shadow.bias = 0.0001;
  75             b.shadow.mapsize.width = 1024;//阴影质量w
  76             b.shadow.mapsize.height = 1024;//阴影质量h
  77             
  78             //下面属性默认不自动更新
  79         /*     let l_d = 20; //光照区域的大小 100 * 100
  80             b.shadow.camera.left = -l_d;
  81             b.shadow.camera.right = l_d;
  82             b.shadow.camera.top = l_d;
  83             b.shadow.camera.bottom = -l_d; */
  84             b.shadow.camera.near = 0.1;//最近
  85             b.shadow.camera.far = 100;//最远
  86             
  87             
  88            /* var helpershadow = new three.camerahelper(b.shadow.camera);
  89             scene.add(a, b, helpershadow);
  90             var c = ()=>{()=>{helpershadow.update(); hc.update(); }}
  91             new gui(b.position, ["x", "y", "z"], [-2500, 2500, 1]).change(c)
  92             .add(b.shadow, "radius", [-1, 1, 0.1]).change(c)
  93             .add(b.shadow.mapsize, ["width", "height"], [0, 2048, 1]).change(c)
  94             .title("调试灯光");*/
  95             scene.add(a, b);
  96             return [a, b];
  97         },
  98         
  99         addcontrols: function (scene, camera, renderer, children){//控件
 100 
 101             //拖放控件
 102             let drag = new three.dragcontrols(children, camera, renderer.domelement);
 103             //drag.addeventlistener('hoveron', (e)=>{this.addtarget(e.object);});
 104             drag.enabled = false;
 105             //this.dragcontrols = dc;
 106             
 107             //轨道控件
 108             let orbit = new three.orbitcontrols(camera, renderer.domelement);
 109             orbit.target = new three.vector3(0, 0, 0);//控件焦点
 110             //orbit.minpolarangle = math.pi * 0.3;//向上最大角度
 111             //orbit.maxpolarangle = math.pi * 0.4;//向下最大角度
 112             orbit.mindistance = _mindistance;//最小距离
 113             orbit.maxdistance = _maxdistance;//最大距离
 114             orbit.autorotatespeed = 10;//自动旋转速度
 115             //orbit.panspeed = 100;//鼠标旋转速度
 116             orbit.enablezoom = true;//是否启用缩放
 117             orbit.enablekeys = true;//是否启用键盘
 118             orbit.panspeed = 1;//鼠标平移速度
 119             orbit.keypanspeed = 100;//按键平移的速度
 120             orbit.keys.left = 65;//key a左
 121             orbit.keys.up = 87;//key w前
 122             orbit.keys.right = 68;//key d右
 123             orbit.keys.bottom = 83;//key s后
 124             orbit.addeventlistener("change", ()=>{this.render(scene, camera, renderer);});
 125             
 126             
 127             //平移控件
 128             var transform = new three.transformcontrols(camera, renderer.domelement);
 129             transform.addeventlistener( 'dragging-changed', (e)=>{orbit.enabled = !e.value;});
 130             transform.addeventlistener('change', ()=>{this.render(scene, camera, renderer);});
 131             scene.add(transform);
 132             
 133             return {drag: drag, orbit: orbit, transform: transform};
 134         },
 135         
 136         updategeometry: function (mesh, geometry){//更换几何体
 137             if(!mesh || !geometry){
 138                 console.log("_three: 几何体更换失败"); 
 139                 return;
 140             }
 141             mesh.geometry.dispose();
 142             mesh.geometry = geometry;
 143         },
 144         
 145         updatematerial: function (mesh, material){//更换材质
 146             if(!mesh || !material){
 147                 console.log("_three: 材质更换失败"); 
 148                 return;
 149             }
 150             let newmat = material.clone(true);
 151             //newmat.color.copy(mesh.material.color);
 152             newmat.transparent = true;
 153             if(mesh.material.map !== null){this.updatetexture(newmat, mesh.material.map);}
 154             mesh.material.dispose();
 155             mesh.material = newmat;
 156         },
 157         
 158         updatetexture: function (material, texture){//更换纹理
 159             if(!material || !texture){
 160                 console.log("_three: 纹理更换失败"); 
 161                 return;
 162             }
 163             let map = new three.texture(texture.image);
 164             map.wraps = three.repeatwrapping;
 165             map.wrapt = three.repeatwrapping;
 166             map.repeat.set(1, 1);
 167             map.minfilter = three.nearestfilter;
 168             map.magfilter = three.nearestfilter;
 169             if(material.map !== null){
 170                 map.wraps = material.map.wraps;
 171                 map.wrapt = material.map.wrapt;
 172                 map.repeat.copy(material.map.repeat);
 173                 map.anisotropy = material.map.anisotropy;
 174                 material.map.dispose();
 175             }
 176             material.map = map;
 177             material.map.needsupdate = true;
 178             material.needsupdate = true;
 179         },
 180         
 181         render: function (scene, camera, renderer){//渲染
 182             renderer.render(scene, camera);
 183         },
 184 
 185         getbsp: function (mesha, meshb, type){//剪裁 添加 重合
 186             if(!mesha || !meshb || !type || mesha === meshb){console.log("getbsp:参数错误, 请选择1至2个物体进行运算"); return;}
 187             if(!mesha.geometry || !meshb.geometry) return;
 188             if(mesha.geometry.isgeometry !== true || meshb.geometry.isgeometry !== true) return;
 189             let bsp_a = new threebsp(mesha);//生成threebsp对象
 190             let bsp_b = new threebsp(meshb);//生成threebsp对象
 191             let bsp = bsp_a[type](bsp_b);//进行 type 计算
 192             let mesh = bsp.tomesh();//转换为mesh模型
 193             mesh.geometry.computefacenormals();//更新模型的面
 194             mesh.geometry.computevertexnormals();//更新模型的顶点
 195             mesh.material = mesha.material;//重赋值纹理
 196             return mesh;
 197         },
 198         
 199         tobuffer: function (geometry){//几何体 转为缓存几何体
 200             if(geometry.isgeometry !== true) return;
 201             return new three.buffergeometry().fromgeometry(geometry);
 202         },
 203         
 204         loadinggltf: function (url, scene){//导入
 205             if(!this.loadgltf){this.__proto__.loadgltf = new three.gltfloader();}
 206             if(!scene) return;
 207             this.loadgltf.load(url, (gltf)=>{
 208                 scene.add(gltf.scene);
 209             });
 210         },
 211         
 212         exportergltf: function (mesh, filetype){//导出物体(限谷歌浏览器)
 213             if(!this.exportgltf){this.__proto__.exportgltf = new three.gltfexporter();}
 214             if(!mesh){console.log("mesh 错误"); return;}
 215             // 使用meshbasicmaterial 或 meshstandardmaterial 材质 效果会更好
 216             //使用 buffergeometry 缓存几何体 文件体积会更小
 217             //if(mesh.geometry.isgeometry === true){mesh.geometry = new three.buffergeometry().fromgeometry(mesh.geometry);}
 218             var opt = {
 219                 binary: filetype || this.exportgltffiletype || false,
 220                 embedimages: true,
 221                 onlyvisible: true,
 222                 truncatedrawrange: true,
 223                 trs: false
 224             };
 225             var download = ( blob, filename )=>{
 226                 let link = _view.add(document.body, "a");
 227                 link.style.display = 'none';
 228                 link.href = url.createobjecturl( blob ); console.log(link.href);
 229                 link.download = filename;
 230                 link.click();
 231                 _view.remove(link); 
 232             }
 233             
 234             this.exportgltf.parse(mesh, function ( result ){
 235                 if(result instanceof arraybuffer){
 236                     download(new blob([result], {type: 'application/octet-stream'}), 'scene.glb');
 237                 }else{
 238                     download(new blob([json.stringify( result, null, 2 )], {type: 'text/plain'}), 'scene.gltf');
 239                 }
 240             }, opt);
 241         },
 242         
 243         runraycaster: function (o, w, h){//光线投射
 244             o.result.length = 0;
 245             o.vector2.set((o.x / w || _width) * 2 - 1, -(o.y / h || _height) * 2 + 1);
 246             o.raycaster.setfromcamera(o.vector2, o.camera);
 247             o.raycaster.intersectobjects(o.children, o.recursive, o.result);
 248         },
 249         
 250         createclipplane: function (handcreate){//添加 面 和 点 剪裁面
 251             let pa = new three.plane(new three.vector3( 1, 0, 0 ), 1);
 252             let pb = new three.plane(new three.vector3( 0, -1, 0 ), 1);
 253             let pc = new three.plane(new three.vector3( 0, 0, -1), 1);
 254             let pd = new three.plane(new three.vector3( 0, 1, 1), 1);
 255             
 256             let hg = new three.group();
 257             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));
 258             return {
 259                 planes: [pa, pb, pc, pd],
 260                 helpers: hg
 261             };
 262             var geometry = new three.spheregeometry(1, 48, 24);
 263             var material = new three.meshlambertmaterial({
 264                 color: new three.color("#666666"),
 265                 side: three.doubleside,
 266                 clippingplanes: clipplane,
 267                 clipintersection: true
 268             });
 269             console.log(helper0); console.log(material);
 270             handcreate.add(new three.mesh(geometry, material), helpergroup);
 271             
 272             handcreate.renderer.localclippingenabled = true;
 273             
 274             //clipplane.constant = 0.1;
 275             new gui({constant:0}, [-1, 1, 0.01])
 276             .change((val)=>{
 277                 for(let k = 0; k < clipplane.length; k++){
 278                     clipplane[k].constant = val;
 279                 }
 280                 handcreate.update();
 281             })
 282             .add(material, "clipintersection")
 283             .add(helper0, "size", [0, 10, 0.1])
 284             .change(()=>{handcreate.update();})
 285         }
 286         
 287     });
 288     
 289     
 290     
 291     //几何体
 292     var _geometry = function (){
 293         _three.call(this);
 294         //this.width = 100; _width
 295         this.height = 100;
 296         this.y = this.campos.y;
 297         this.dis = 1.5;
 298         this.targetchange = null;
 299         this.objects = [];
 300     }
 301     
 302     _geometry.prototype = object.assign(object.create(_three.prototype), {
 303         
 304         constructor: _geometry,
 305         
 306         config: [
 307             new three.boxgeometry(1, 1, 1, 1, 1, 1), 
 308             new three.spheregeometry(0.5, 8 , 6, 0, math.pi * 2, 0, math.pi),
 309             new three.planegeometry(1, 1, 1, 1)
 310         ],
 311 
 312         campos: {x: _width/110, y: 0, z: 1.5},
 313 
 314         defaultmaterial: new three.meshbasicmaterial({wireframe: true}),
 315         
 316         init: function (){//初始化
 317             if(this.scene === undefined)  this.addscene();
 318             if(this.show === undefined)  this.setshow();
 319             if(this.target === undefined) this.settarget();
 320             this.renderview(this.config);
 321             return this;
 322         },
 323         
 324         addscene: function (){//添加 场景
 325             let elem = _view.add(document.body, "div", null, "showobject box-scroll-block");
 326             _view.addevent(elem, 'click', (e)=>{this.addtarget(e);});
 327             
 328             let scene = this.createscene(0x000000, false);
 329             var camera = new three.orthographiccamera(_width/-100, _width/100, this.height/100, this.height/-100, 0.1, 10);
 330             camera.lookat(0, 0, 0);
 331             let renderer = this.createrenderer(elem, _width, this.height, true, true, true, true);
 332             let linghts = this.addlinghts(scene);
 333             let drag = new three.dragcontrols(scene.children, camera, renderer.domelement);
 334             drag.enabled = false;
 335             this.__proto__.scene = {e: elem, s:scene, c: camera, r: renderer, l: linghts, drag: drag, target: null}
 336             drag.addeventlistener('hoveron', (e)=>{this.scene.target = e.object;});
 337             drag.addeventlistener('hoveroff', ()=>{this.scene.target = null;});
 338             this.gotoposition();
 339         },
 340         
 341         addlinghts: function (scene){//重写添加灯光
 342             let a = new three.ambientlight(0x696969);
 343             let b = new three.directionallight(0xffffff, 1);
 344             b.position.set(0, 5, 5);
 345             scene.add(a, b);
 346             return [a, b];
 347         },
 348         
 349         gotoposition: function (){//跳转到 geometry 坐标
 350             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 351             this.update();
 352         },
 353         
 354         setpos: function (k, mesh){//renderview-> 设置物体之间的距离
 355             mesh.position.set(k * this.dis, this.y, 0);
 356         },
 357         
 358         addmesh: function (object, key){//renderview-> 添加物体
 359             let mesh = new three.mesh(object, this.defaultmaterial);
 360             mesh.handcreate = {type: "_geometry", index: key, matindex: 0}
 361             this.scene.s.add(mesh);
 362             return mesh;
 363         },
 364         
 365         renderview: function (arr){//渲染场景视图
 366             for(let k = 0; k < arr.length; k++){
 367                 let mesh = this.addmesh(arr[k], k);
 368                 this.setpos(k, mesh);
 369                 this.objects.push(mesh);
 370             }
 371             this.update();
 372         },
 373         
 374         setshow: function (){//是否显示场景的html元素
 375             let _show = false;
 376             object.defineproperties(this.__proto__, {
 377                 show: {
 378                     get:()=>{return _show;},
 379                     set:(v)=>{
 380                         if(v === true){
 381                             this.scene.e.style.display = "block";
 382                         }else{
 383                             this.scene.e.style.display = "none";
 384                         }
 385                         _show = v;
 386                     }
 387                 }
 388             });
 389         },
 390         
 391         addtarget: function (e){//addscene event->场景html元素的事件回调函数
 392             if(!this.scene.target) return;
 393             this.target = this.scene.target;
 394         },
 395         
 396         settarget: function (){//配置 target
 397             let _target = null;
 398             object.defineproperties(this.__proto__, {
 399                 target: {
 400                     get:()=>{return _target;},
 401                     set:(v)=>{
 402                         if(typeof(this.targetchange) === "function") this.targetchange(v);
 403                         _target = v;
 404                     }
 405                 }
 406             });
 407         },
 408         
 409         exportobject: function (){//导出 几何体
 410             
 411         },
 412         
 413         importobject: function (object){//导入 几何体
 414             if(object.isgeometry !== true) return;
 415             let nowkey = this.config.length;
 416             let mesh = this.addmesh(object, nowkey);
 417             this.setpos(nowkey, mesh);
 418             this.config.push(object);
 419             this.objects.push(mesh);
 420             this.update();
 421         },
 422         
 423         update: function (){//更新场景
 424             this.render(this.scene.s, this.scene.c, this.scene.r);
 425         },
 426         
 427         debugcamera: function (){//gui调试 正交相机
 428             let c = this.scene.c;
 429             let pos = {x: _width/110, y: 0, lookat: true, position: false};
 430             let upd = ()=>{
 431                 if(pos.lookat) c.lookat(pos.x, pos.y, 0); 
 432                 if(pos.position) c.position.set(pos.x, pos.y, 5);
 433                 this.update();
 434             }
 435 
 436             new gui(pos, [0, 10, 0.1], "调试正交相机")
 437             .change({
 438                 x: (v)=>{pos.x = v; upd();},
 439                 y: (v)=>{pos.y = v;  upd();}
 440             })
 441 
 442         }
 443         
 444     });
 445     
 446     
 447     
 448     //材质
 449     var _material = function (){
 450         _geometry.call(this);
 451     }
 452     
 453     _material.prototype = object.assign(object.create(_geometry.prototype), {
 454         
 455         constructor: _material,
 456         
 457         config:[
 458             new three.meshbasicmaterial(),
 459             new three.meshlambertmaterial(),
 460             new three.meshstandardmaterial()
 461         ],
 462         
 463         defaultgeometry: new three.boxgeometry(1, 1, 1, 1, 1, 1),
 464         
 465         campos: {x: _width/110, y: 1.5, z: 1.5},
 466         
 467         addmesh: function (object, key){
 468             let mesh = new three.mesh(this.defaultgeometry, object);
 469             mesh.handcreate = {type: "_material", index: key};
 470             this.scene.s.add(mesh);
 471             return mesh;
 472         },
 473         
 474         gotoposition: function (mesh){
 475             if(!mesh) return; this.mesh = mesh;
 476             let geometry = _geometry.prototype.config[mesh.handcreate.geoci].clone();
 477             for(let k = 0; k < this.objects.length; k++){
 478                 this.updategeometry(this.objects[k], geometry);
 479             }
 480             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 481             this.update();
 482         }
 483         
 484     });
 485     
 486     
 487     
 488     //纹理 map
 489     var _texture = function (){
 490         _material.call(this);
 491         this.texturelen = 12;
 492         this.settexture();
 493     }
 494     
 495     _texture.prototype = object.assign(object.create(_material.prototype), {
 496         
 497         constructor: _texture,
 498         
 499         config: [],
 500         
 501         campos: {x: _width/110, y: 3, z: 1.5},
 502         
 503         defaultmaterial: new three.meshbasicmaterial(),
 504         
 505         load: new three.textureloader(),
 506         
 507         loaded: 0,
 508         
 509         settexture: function (){
 510             let k, texture;
 511             for(k = 0; k < this.texturelen; k++){
 512                 texture = this.load.load("img/texture/"+k+".jpg", ()=>{this.__proto__.loaded++;});
 513                 texture.wraps = three.repeatwrapping;
 514                 texture.wrapt = three.repeatwrapping;
 515                 texture.repeat.set(1, 1);
 516                 this.__proto__.config.push(texture);
 517             }
 518             if(this.loaded !== this.texturelen){this.awaitload();}
 519         },
 520         
 521         awaitload: function (){
 522             let interval = setinterval(()=>{
 523                 if(this.loaded === this.texturelen){
 524                     this.update();
 525                     clearinterval(interval);
 526                     console.log("load texture: "+this.loaded+"/"+this.texturelen);
 527                 }else{
 528                     console.log("load texture: "+this.loaded+"/"+this.texturelen);
 529                 }
 530             }, 300);
 531         },
 532 
 533         addmesh: function (object, key){
 534             let mesh = new three.mesh(this.defaultgeometry, new three.meshbasicmaterial({map: object}));
 535             //let mesh = new three.mesh(this.defaultgeometry, this.defaultmaterial);
 536             //this.updatetexture(mesh, object);
 537             mesh.handcreate = {type: "_texture", index: key};
 538             this.scene.s.add(mesh);
 539             return mesh;
 540         },
 541         
 542         gotoposition: function (mesh){
 543             if(!mesh) return; this.mesh = mesh;
 544             let geometry = _geometry.prototype.config[mesh.handcreate.geoci].clone();
 545             let material = _material.prototype.config[mesh.handcreate.matci].clone();
 546             for(let k = 0; k < this.objects.length; k++){
 547                 this.updategeometry(this.objects[k], geometry);
 548                 this.updatematerial(this.objects[k], material);
 549             }
 550             this.scene.c.position.set(this.campos.x, this.campos.y, this.campos.z);
 551             this.update();
 552         }
 553         
 554     });
 555     
 556     //物体
 557     var _mesh = function (){}
 558     
 559     //gui
 560     var setview = function (hc, newmesh, oldmesh){
 561         this.hc = hc;
 562         this.newmesh = newmesh;
 563         this.oldmesh = oldmesh;
 564         return this.init();
 565     }
 566     
 567     object.assign(setview.prototype, {
 568         
 569         constructor: setview,
 570         
 571         init: function (){
 572             if(this.globalgui === undefined) this.createglobal();
 573             this.gui = new gui().display("none");
 574             
 575             this.createmesh();
 576             this.creategeometry();
 577             this.creatematerial();
 578             return this;
 579         },
 580         
 581         createmesh: function (){
 582             let o = {
 583                 exportgltf: ()=>{this.hc.three.exportergltf(this.newmesh);},
 584                 addmesh: ()=>{this.hc.geometry.gotoposition();},
 585                 removemesh: ()=>{this.hc.remove(this.newmesh);},
 586                 getbsp: "intersect",
 587                 rungetbsp: ()=>{
 588                     let meshb = this.hc.targets[0].mesh;
 589                     if(this.newmesh === meshb) meshb = this.hc.targets[1].mesh;
 590                     let result = this.hc.three.getbsp(this.newmesh, meshb, o.getbsp);
 591                     this.hc.geometry.importobject(result.geometry);
 592                     this.hc.isselecttargets = false;
 593                 }
 594             }
 595             let m = {
 596                 visible: this.newmesh.visible,
 597                 frustumculled: this.newmesh.frustumculled,
 598                 castshadow: this.newmesh.castshadow,
 599                 receiveshadow: this.newmesh.receiveshadow,
 600             }
 601             
 602             this.gui.create(m, true).name({visible: "显示物体", castshadow: "投射阴影", receiveshadow: "接收阴影"})
 603             .change({
 604                 visible: ()=>{
 605                     if(this.newmesh.visible === undefined) return;
 606                     this.newmesh.visible = m.visible;
 607                     this.hc.update();
 608                 },
 609                 frustumculled: ()=>{
 610                     if(this.newmesh.frustumculled === undefined) return;
 611                     this.newmesh.frustumculled = m.frustumculled;
 612                     this.hc.update();
 613                 },
 614                 castshadow: ()=>{
 615                     if(this.newmesh.castshadow === undefined) return;
 616                     this.newmesh.castshadow = m.castshadow;
 617                     this.hc.update();
 618                 },
 619                 receiveshadow: ()=>{
 620                     if(this.newmesh.receiveshadow === undefined) return;
 621                     this.newmesh.receiveshadow = m.receiveshadow;
 622                     this.hc.update();
 623                 }
 624             })
 625             
 626             .add(o, {getbsp:[["交集", "intersect"], ["并集", "union"], ["差集", "subtract"]]}, true)
 627             .name({exportgltf: "导出物体", addmesh: "添加物体", removemesh: "移除物体", getbsp: "布尔运算类型(选择一个物体)", rungetbsp: "布尔运算"})
 628             .change({
 629                 getbsp: (e)=>{o.getbsp = e.target.value;}
 630             })
 631             
 632             .title("物体-"+this.newmesh.type+"-"+this.newmesh.id);
 633         },
 634         
 635         creategeometry: function (){
 636             if(this.oldmesh.geometry.parameters === undefined){console.log("setview: 忽略了geometry"); return;}
 637             let o, p = {}, geo;
 638             for(let k in this.oldmesh.geometry.parameters){p[k] = this.oldmesh.geometry.parameters[k];}
 639             switch(this.oldmesh.geometry.type){
 640             
 641                 case "boxgeometry": 
 642                     o = {
 643                         width:[0.1, 10, 0.1], 
 644                         height:[0.1, 10, 0.1], 
 645                         depth:[0.1, 10, 0.1], 
 646                         widthsegments:[1, 30, 1], 
 647                         heightsegments:[1, 30, 1], 
 648                         depthsegments:[1, 30, 1]
 649                     }
 650                     this.gui.create(p, o, true)
 651                     .name({width: "宽度", height: "高度", depth: "深度", widthsegments: "宽段数", heightsegments: "高段数", depthsegments: "深段数"})
 652                     .change(()=>{
 653                         geo = new three.boxgeometry(p.width, p.height, p.depth, p.widthsegments, p.heightsegments, p.depthsegments);
 654                         this.hc.three.updategeometry(this.newmesh, geo);
 655                         this.hc.update();
 656                     });
 657                     
 658                 break;
 659                 
 660                 case "spheregeometry": 
 661                     o = {
 662                         radius:[0.1, 10, 0.1], 
 663                         widthsegments:[1, 30, 1], 
 664                         heightsegments:[1, 30, 1], 
 665                         phistart:[0, math.pi*2, 0.1], 
 666                         philength:[0, math.pi*2, 0.1], 
 667                         thetastart:[0, math.pi*2, 0.1], 
 668                         thetalength:[0, math.pi*2, 0.1]
 669                     }
 670                     this.gui.create(p, o, true)
 671                     .name({radius: "半径", widthsegments: "宽段数", heightsegments: "高段数", phistart: "经线起始角度", philength: "经线起始角度大小", thetastart: "纬线起始角度", thetalength: "纬线起始角度大小",})
 672                     .change(()=>{
 673                         geo = new three.spheregeometry(p.radius, p.widthsegments, p.heightsegments, p.phistart, p.philength, p.thetastart, p.thetalength);
 674                         this.hc.three.updategeometry(this.newmesh, geo);
 675                         this.hc.update();
 676                     });
 677                     
 678                 break;
 679                 
 680                 case "planegeometry": 
 681                     o = {
 682                         width: [1, 100, 0.1],
 683                         height: [1, 100, 0.1],
 684                         widthsegments: [1, 30, 1],
 685                         heightsegments: [1, 30, 1]
 686                     }
 687                     this.gui.create(p, o, true)
 688                     .name({width: "宽度", height: "高度", widthsegments: "宽段数", heightsegments: "高段数"})
 689                     .change(()=>{
 690                         geo = new three.planegeometry(p.width, p.height, p.widthsegments, p.heightsegments);
 691                         this.hc.three.updategeometry(this.newmesh, geo);
 692                         this.hc.update();
 693                     });
 694                 break;
 695                     
 696                 default : break;
 697             }
 698             this.gui.title("几何体-"+this.newmesh.geometry.type+"-"+this.newmesh.id);
 699         },
 700         
 701         creatematerial: function (){
 702             let mat = this.newmesh.material;
 703             let o = {
 704                 color: "#" + mat.color.gethexstring(),
 705                 emissive: mat.emissive === undefined ? "#000000" : "#" + mat.emissive.gethexstring(),
 706                 updatematerial: ()=>{this.hc.material.gotoposition(this.newmesh);},
 707                 updatetexture: ()=>{this.hc.texture.gotoposition(this.newmesh);}
 708             }
 709             let m = {
 710                 wireframe: mat.wireframe, 
 711                 visible: mat.visible, 
 712                 side: mat.side, 
 713                 fog: mat.fog, 
 714                 aomapintensity: mat.aomapintensity, 
 715                 colorwrite: mat.colorwrite, 
 716                 transparent: mat.transparent, 
 717                 opacity: mat.opacity, 
 718                 alphatest: mat.alphatest, 
 719                 flatshading: mat.flatshading,
 720                 emissiveintensity: mat.emissiveintensity === undefined ? 0 : mat.emissiveintensity,
 721                 repeatu: 1,
 722                 repeatv: 1,
 723                 anisotropy: 1
 724             }
 725             
 726             let num = {
 727                 aomapintensity: [0, 1, 0.1], 
 728                 opacity: [0, 1, 0.1], 
 729                 alphatest: [0, 1, 0.1], 
 730                 emissiveintensity: [0, 1, 0.1],
 731                 repeatu: [1, 100, 1],
 732                 repeatv: [1, 100, 1],
 733                 anisotropy: [1, this.hc.renderer.capabilities.getmaxanisotropy() || 2, 1]
 734             };
 735             let sel = {
 736                 side: [["外面", three.frontside], ["里面", three.backside], ["双面", three.doubleside]]
 737             };
 738             let name = {
 739                 wireframe:"网格模式", 
 740                 visible:"显示材质", 
 741                 side: "材质显示那一面", 
 742                 fog: "受雾气影响", 
 743                 aomapintensity: "遮挡效果", 
 744                 colorwrite: "渲染颜色", 
 745                 transparent: "渲染透明度", 
 746                 opacity: "透明度", 
 747                 alphatest: "alpha值", 
 748                 flatshading: "平面着色",
 749                 emissiveintensity: "放射光强度",
 750                 repeatu: "重复量,纹理u面",
 751                 repeatv: "重复量,纹理v面",
 752                 anisotropy: "纹理清晰度"
 753             };
 754             let c = {
 755                 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();},
 756                 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();},
 757                 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();},
 758                 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();},
 759                 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();},
 760                 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();},
 761                 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();},
 762                 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();},
 763                 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();},
 764                 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();},
 765                 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();},
 766                 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();},
 767                 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();},
 768                 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();},
 769                 
 770             };
 771             
 772             this.gui.create(m, num, true, sel).name(name).change(c)
 773             
 774             .add(o, true)
 775             .name({color: "材质颜色", emissive: "放射光颜色", updatematerial: "替换材质", updatetexture: "替换纹理"})
 776             .change({
 777                 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();},
 778                 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();}
 779             })
 780             
 781             .title("材质-"+this.newmesh.material.type+"-"+this.newmesh.id);
 782         },
 783         
 784         createglobal: function (){
 785             let o = {
 786                 setmode: "translate",
 787                 exportall: ()=>{console.log("导出全部物体")},
 788                 updatematerialall: ()=>{console.log("替换全部材质")},
 789                 isgltf: true
 790             }
 791 
 792             let gui = new gui(this.hc.geometry, "show", "显示创建选项")
 793             
 794             .add(o, true, {isgltf: [[".gltf", false], [".glb", true]], setmode: [["平移", "translate"], ["旋转", "rotate"], ["缩放", "scale"]]})
 795             .name({exportall: "导出全部物体", updatematerialall: "替换全部材质", setmode: "控制模式", isgltf:"导出类型"})
 796             .change({
 797                 isgltf: (e)=>{this.hc.three.exportgltffiletype = eval(e.target.value);},
 798                 setmode: (e)=>{this.hc.control.transform.setmode(e.target.value);}
 799             })
 800             
 801             .add(this.hc, true, ["locktarget", "isselecttargets"])
 802             .name({locktarget: "锁定物体", isselecttargets: "选择物体"})
 803             .change({
 804                 isselecttargets: ()=>{
 805                     if(this.hc.isselecttargets === false){
 806                         this.hc.removetargets();
 807                     }
 808                 },
 809                 locktarget: ()=>{
 810                     if(this.hc.locktarget === false){
 811                         this.hc.removetargets();
 812                     }
 813                 }
 814             })
 815             
 816             .title("global");
 817             this.__proto__.globalgui = gui;
 818         }
 819         
 820     });
 821     
 822     
 823     
 824     //main
 825     var handcreate = function (){
 826         this.three = new _three();
 827         this.group = new three.group();
 828         this.target = {};
 829         this.isselecttargets = false;
 830         this.targets = [];
 831         this.backmesh = null;
 832         this.locktarget = false;
 833         this.scene = this.three.createscene([], false);
 834         this.renderer = this.three.createrenderer(document.body, _width, _height, true, true, true, true);
 835         
 836     }
 837     
 838     object.assign(handcreate.prototype, {
 839         
 840         constructor: handcreate,
 841         
 842         init: function (){
 843             this.intersects = {
 844                 raycaster: new three.raycaster(),
 845                 group: new three.group(),
 846                 vector2: new three.vector2(),
 847                 result: [],
 848                 camera: this.camera,
 849                 recursive: true,
 850                 x: 0,
 851                 y: 0,
 852             };
 853             this.renderer.domelement.style = "position:absolute; top:0; left:0";//如果不定位, gui的移动块会不正常显示
 854             //this.renderer.localclippingenabled = true;//是否渲染 平面剪裁
 855             this.camera = this.three.createcamera(45, _width, _height, _mindistance, _maxdistance * _mindistance * 0.2);
 856             this.camera.position.set(0, _maxdistance * 0.001, _maxdistance * 0.001);
 857             this.linghts = this.three.addlinghts(this.scene, this);
 858             this.control = this.three.addcontrols(this.scene, this.camera, this.renderer, this.intersects.group.children);
 859             this.control.drag.addeventlistener('hoveron', (e)=>{this.settarget(e.object);});
 860             
 861             this.geometry = new _geometry().init();
 862             this.geometry.targetchange = (v)=>{this.createobject(v);};
 863             this.geometry.show = true;
 864             
 865             this.material = new _material().init();
 866             
 867             this.texture = new _texture().init();
 868             
 869             this.gridhelper = new three.gridhelper(_maxdistance, _maxdistance/1);
 870             this.scene.add(this.group, this.intersects.group, this.camera, this.gridhelper);
 871             
 872             //this.clip = this.three.createclip();
 873             //this.globalview();
 874             //this.three.loadinggltf("img/gltfs/scene.gltf", this.intersects.group);
 875             //this.three.loadinggltf("img/gltfs/scene.glb", this.intersects.group);
 876             return this;
 877         },
 878         
 879         add: function (mesh, group){
 880             if(!mesh) return;
 881             let gro = group || this.intersects.group;
 882             if(array.isarray(mesh) === true){
 883                 let k, len = mesh.length;
 884                 for(k; k < len; k++){
 885                     if(!mesh[k]) continue;
 886                     gro.add(mesh[k]);
 887                 }
 888             }else{
 889                 gro.add(mesh);
 890             }
 891             this.update();
 892         },
 893         
 894         remove: function (mesh, group){
 895             if(!mesh){console.log("remove: mesh不存在"); return;}
 896             let arr = group || this.intersects.group;
 897             if(!arr.remove){console.log("remove: group错误"); return;}
 898             this.removetarget();
 899             if(mesh.gui) mesh.gui.remove();
 900             mesh.handcreate.sv.gui.remove();
 901             if(mesh.material.map){mesh.material.map.dispose();}
 902             mesh.material.dispose();
 903             mesh.geometry.dispose();
 904             arr.remove(mesh);
 905             this.update();
 906         },
 907         
 908         update: function (){
 909             this.three.render(this.scene, this.camera, this.renderer);
 910         },
 911 
 912         settarget: function (mesh){
 913             if(this.isselecttargets === true){this.settargets(mesh);}
 914             if(this.target.mesh === mesh || this.locktarget === true){return;}
 915             if(mesh.handcreate === undefined || mesh.handcreate.sv === undefined){this.locktarget = true; console.log("settarget: mesh 错误,取消选择"); return;}
 916 
 917             this.removetarget();
 918             
 919             this.target.mesh = mesh;
 920             this.control.transform.attach(mesh);
 921             mesh.handcreate.sv.gui.display("block");
 922             this.geometry.gotoposition();
 923             this.update();
 924         },
 925         
 926         removetarget: function (){
 927             if(!this.target.mesh) return;
 928             this.control.transform.detach(this.target.mesh);
 929             this.target.mesh.handcreate.sv.gui.display("none");
 930             delete(this.target.mesh);
 931             this.update();
 932         },
 933         
 934         settargets: function (mesh){
 935             //if(this.targets.indexof(mesh) !== -1){return;}
 936             for(let k = 0; k < this.targets.length; k ++){if(this.targets[k].mesh === mesh){return;}}
 937             this.isselecttargets = true;
 938             this.locktarget = true;
 939             this.targets.push({mesh: mesh, color: mesh.material.color.gethex()}); 
 940             mesh.material.color.set("red");
 941             this.update();
 942         },
 943         
 944         removetargets: function (){
 945             this.isselecttargets = false;
 946             this.locktarget = false;
 947             for(let k = 0; k < this.targets.length; k++){
 948                 this.targets[k].mesh.material.color.set(this.targets[k].color);
 949             }
 950             this.targets.length = 0; 
 951             this.update();
 952         },
 953         
 954         createobject: function (v){
 955             
 956             let geo = ()=>{
 957                 let mesh = new three.mesh(v.geometry.clone(), v.material.clone());
 958                 mesh.material.transparent = true;
 959                 mesh.castshadow = true;
 960                 mesh.receiveshadow = true;
 961                 mesh.customdepthmaterial = new three.meshdepthmaterial({depthpacking: three.rgbadepthpacking});
 962                 
 963                 mesh.handcreate = {
 964                     sv: new setview(this, mesh, v),
 965                     geoci: v.handcreate.index, 
 966                     matci: v.handcreate.matindex,
 967                     texci: null
 968                 };
 969                 
 970                 this.backmesh = mesh;
 971                 this.add(mesh);
 972                 this.settarget(mesh);
 973             }
 974             
 975             let mat = ()=>{
 976                 this.three.updatematerial(this.material.mesh, v.material);
 977                 this.material.mesh.handcreate.matci = v.handcreate.index;
 978                 this.update();
 979             }
 980             
 981             let tex = ()=>{
 982                 this.three.updatetexture(this.texture.mesh.material, v.material.map);
 983                 this.texture.mesh.handcreate.texci = v.handcreate.index;
 984                 this.update();
 985             }
 986             
 987             switch(v.handcreate.type){
 988                 case "_geometry": geo(); break;
 989                 case "_material": mat(); break;
 990                 case "_texture": tex(); break;
 991                 default: break;
 992             }
 993 
 994         }
 995         
 996     });
 997     
 998     //代理
 999     /* this.forcreate = new proxy(new handcreate().init(), {
1000         get(o, k){
1001             return o[k];
1002         },
1003         set(o, k, v){
1004             o[k] = v;
1005         }
1006     }); */
1007     
1008     this.forcreate = new handcreate().init();
1009     
1010 }).call(this)