1 完整代码下载
https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ
提取码 3fzt (压缩包名: 2020-3-24-demo.zip)
2 图片展示



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)
来源:https://www.cnblogs.com/weihexinCode/p/12609829.html