1 完整代碼下載 https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ 提取碼 3fzt (壓縮包名: 2020-3-20-demo.zip) 2 圖片展示 3 主要代碼 1 /** HandCreate 簡單的 圖形界面 搭建幾何體 2 construct ...
1 完整代碼下載 https://pan.baidu.com/s/1JJyVcP2KqXsd5G6eaYpgHQ 提取碼 3fzt (壓縮包名: 2020-3-20-demo.zip) 2 圖片展示 3 主要代碼
1 /** HandCreate 簡單的 圖形界面 搭建幾何體 2 constructor: 3 params: 4 prototype: 5 method: 6 */ 7 class HandCreate{ 8 9 constructor(func, view, three){ 10 this.func = func; 11 this.view = view; 12 this.three = three; 13 this.size = 1; 14 this.color = 0xDCDCDC; 15 this.target = {}; 16 this.isOldAddMesh = true; 17 18 this.group = new THREE.Group(); 19 this.three.scene.add(this.group); 20 this.group.name = "Group_HandCreate"; 21 22 this.raycaster = { 23 raycaster:new THREE.Raycaster(), 24 vector2:new THREE.Vector2(), 25 childrens:[], 26 result:[] 27 } 28 this.raycaster.raycaster.far = 100; 29 30 this.materials = this.initMaterials(); 31 this.geometrys = this.initGeometrys(); 32 this.lands(); 33 this.controls(); 34 this.initGui(); 35 } 36 37 initMaterials(){ 38 return new Map([ 39 [0, new THREE.MeshBasicMaterial({color:this.color})], 40 [1, new THREE.MeshLambertMaterial({color:this.color})], 41 [2, new THREE.MeshStandardMaterial({color:this.color})] 42 ]); 43 } 44 45 initGeometrys(){ 46 47 var geometrys = new Map([ 48 [0, new THREE.BoxGeometry(this.size, this.size, this.size, 1, 1, 1)], 49 [1, new THREE.SphereGeometry(this.size/2, 8, 6, 0, Math.PI * 2, 0, Math.PI)], 50 ]); 51 52 for(let k = 0; k < geometrys.size; k++){ 53 this.createShowMesh(k, new THREE.Mesh(geometrys.get(k), this.materials.get(0))); 54 } 55 56 return geometrys; 57 58 } 59 60 initGui(){ 61 var g_c = ()=>{this.update();} 62 new this.view.Gui( 63 { 64 translate:()=>{this.transformControl.setMode("translate")}, 65 rotate:()=>{this.transformControl.setMode("rotate")}, 66 scale:()=>{this.transformControl.setMode("scale")} 67 }, 68 "控制類型(平移,旋轉,縮放)" 69 ) 70 .create(this, "isOldAddMesh", "是否添加共用物體").change(g_c) 71 } 72 73 addTarget(mesh){//當前物體 74 if(this.target.mesh === mesh) return; 75 76 this.removeTarget(mesh); 77 this.transformControl.attach(mesh); 78 79 var upd = ()=>{this.update();} 80 81 this.target.gui = new this.view.Gui(mesh.material, "wireframe", "修改材質-"+mesh.material.type).change(upd); 82 83 let g_rc, g_s = mesh.geometry.parameters; //克隆的物體沒有 parameters 屬性 84 switch(mesh.geometry.type){ 85 case "BoxGeometry" : 86 //g_s = {g_s.width, g_s.height, g_s.depth, g_s.widthSegments, g_s.heightSegments, g_s.depthSegments} 87 g_rc = {width:[0.1, 10, 0.1], height:[0.1, 10, 0.1], depth:[0.1, 10, 0.1], widthSegments:[1, 30, 1], heightSegments:[1, 30, 1], depthSegments:[1, 30, 1]} 88 this.target.gui.create(g_s, g_rc, "修改幾何體-"+mesh.geometry.type) 89 .change(()=>{ 90 this.updateGeometry(mesh, new THREE.BoxGeometry(g_s.width, g_s.height, g_s.depth, g_s.widthSegments, g_s.heightSegments, g_s.depthSegments)); 91 upd(); 92 }) 93 94 break; 95 96 case "SphereGeometry" : 97 let pi2 = Math.PI * 2; 98 g_rc = {radius:[0.5, 10, 0.1], widthSegments:[1, 30, 1], heightSegments:[1, 30, 1], phiStart:[0, pi2, 0.1], phiLength:[0, pi2, 0.1], thetaStart:[0, pi2, 0.1], thetaLength:[0, pi2, 0.1]} 99 this.target.gui.create(g_s, g_rc, "修改幾何體-"+mesh.geometry.type) 100 .change(()=>{ 101 this.updateGeometry(mesh, new THREE.SphereGeometry(g_s.radius, g_s.widthSegments, g_s.heightSegments, g_s.phiStart, g_s.phiLength, g_s.thetaStart, g_s.thetaLength)); 102 upd(); 103 }) 104 break; 105 106 default : break; 107 } 108 109 this.target.mesh = mesh; 110 } 111 112 removeTarget(mesh){//移除當前物體 113 this.transformControl.detach(mesh); 114 if(this.target.gui){this.target.gui.remove(this.target.gui);} 115 for(let k in this.target){delete(this.target[k]);} 116 } 117 118 lands(){//地面 119 var geometry = new THREE.PlaneBufferGeometry(this.three.sceneSize, this.three.sceneSize); 120 geometry.rotateX( - Math.PI / 2 ); 121 var mesh = new THREE.Mesh( 122 geometry, 123 new THREE.MeshLambertMaterial({color:0x00ff00, visible:false}) 124 ); 125 mesh.receiveShadow = true; 126 mesh.matrixAutoUpdate = false; 127 this.gridHelper = new THREE.GridHelper(this.three.sceneSize, this.three.sceneSize/this.size);//每1米為一格 128 this.add(this.gridHelper, false); 129 this.add(mesh, false); 130 } 131 132 controls(){//控制項 133 //平移控制項 134 var tc = new THREE.TransformControls(this.three.camera, this.three.renderer.domElement); 135 tc.addEventListener( 'dragging-changed', (e)=>{this.three.control.enabled = !e.value;}); 136 tc.addEventListener('change', ()=>{this.update();}); 137 tc.addEventListener('mouseDown', ()=>{}); 138 tc.addEventListener('mouseUp', ()=>{}); 139 tc.addEventListener('objectChange', ()=>{}); 140 this.transformControl = tc; 141 this.three.scene.add(tc); 142 143 //拖放控制項 144 var dc = new THREE.DragControls(this.raycaster.childrens, this.three.camera, this.three.renderer.domElement); 145 dc.addEventListener('hoveron', (e)=>{this.addTarget(e.object); this.update();}); 146 dc.addEventListener('hoveroff', ()=>{this.update();}); 147 dc.enabled = false; 148 this.dragcontrols = dc; 149 150 //軌道控制項 151 this.three.control.addEventListener("change", ()=>{this.update()}); 152 //this.three.control.addEventListener( 'start', ()=>{}); 153 //this.three.control.addEventListener( 'end', ()=>{}); 154 } 155 156 add(mesh, isChildrens){//添加 157 if(!mesh){return;} 158 this.group.add(mesh); 159 if(isChildrens !== false){this.raycaster.childrens.push(mesh);} 160 this.update(); 161 return mesh; 162 } 163 164 remove(mesh, group){//移除物體 165 if(!mesh){return;} 166 let arr = group || this.group, k = this.raycaster.childrens.indexOf(mesh); 167 if(k !== -1){this.raycaster.childrens.splice(k, 1);} 168 arr.remove(mesh); 169 mesh.geometry.dispose(); 170 } 171 172 addMesh(gkey, mkey, isChildrens){//添加物體 173 let g = gkey || 0, m = mkey || 0, mesh; 174 if(this.isOldAddMesh === true){ 175 mesh = new THREE.Mesh(this.geometrys.get(g), this.materials.get(m)); 176 }else{ 177 mesh = new THREE.Mesh(this.geometrys.get(g), this.materials.get(m).clone()); 178 } 179 return this.add(mesh, isChildrens); 180 } 181 182 addWireframe(geometry){//添加網格輔助線 183 var wireframe = new THREE.WireframeGeometry(geometry); 184 var line = new THREE.LineSegments(wireframe); 185 line.material.depthTest = false; 186 line.material.opacity = 0.25; 187 line.material.transparent = true; 188 return line; 189 } 190 191 createShowMesh(elemId, mesh){//物體選項 192 if(!mesh){return;} 193 if(!this.minSceneDom){ 194 this.minSceneDom = this.view.add(document.body, "div", null, "ShowMesh box-scroll-block"); 195 this.view.addEvent(this.minSceneDom, 'mousedown', (e)=>{ 196 let key = parseInt(e.target.id); 197 if(typeof(key) !== "number" || isNaN(key) === true){return;} 198 this.addMesh(key, 0); 199 }); 200 } 201 var scene = new THREE.Scene(); 202 scene.background = new THREE.Color("black"); 203 var camera = new THREE.PerspectiveCamera(45, 100/100, 0.1, 10); 204 camera.position.set(0, 1, 2); 205 camera.lookAt(0, 0, 0); 206 var renderer = new THREE.WebGLRenderer({antialias : true}); 207 renderer.setSize(100, 100); 208 renderer.domElement.id = elemId + "_ShowMeshId"; 209 this.minSceneDom.appendChild(renderer.domElement); 210 scene.add(camera, mesh); 211 mesh.material.wireframe = true; 212 mesh.matrixAutoUpdate = false; 213 this.update(scene, camera, renderer); 214 } 215 216 update(scene, camera, renderer){//更新場景 217 this.three.render(scene, camera, renderer); 218 } 219 220 updateGeometry(mesh, geometry){ 221 mesh.geometry.dispose(); 222 mesh.geometry = geometry; 223 } 224 225 //光線投射 226 runRaycaster(x, y, recursive){ 227 var c = this.raycaster; 228 c.result.length = 0; 229 c.vector2.set((x / this.view.client.w) * 2 - 1, -(y / this.view.client.h) * 2 + 1); 230 c.raycaster.setFromCamera(c.vector2, this.three.camera); 231 c.raycaster.intersectObjects(c.childrens, recursive, c.result); 232 //console.log(c.result[0]); 233 } 234 235 //布爾運算 type = intersect 交集、重合的部分 union 並集、組合、相加 subtract 差集、相減 236 getBSP(meshA, meshB, type){ 237 if(!meshA || !meshB || !type){return;} 238 var bsp_a = new ThreeBSP(meshA);//生成ThreeBSP對象 239 var bsp_b = new ThreeBSP(meshB);//生成ThreeBSP對象 240 var bsp = bsp_a[type](bsp_b);//進行 type 計算 241 var mesh = bsp.toMesh();//轉換為mesh模型 242 mesh.geometry.computeFaceNormals();//更新模型的面 243 mesh.geometry.computeVertexNormals();//更新模型的頂點 244 mesh.geometry = new THREE.BufferGeometry().fromGeometry(mesh.geometry);//轉換為 buff緩衝幾何體 245 //mesh.geometry = new BufferGeometry().fromGeometry(mesh.geometry); 246 mesh.material = meshA.material;//重賦值紋理 247 return mesh; 248 } 249 250 }