|
15 | 15 |
|
16 | 16 | import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js'; |
17 | 17 | import { BufferGeometryUtils } from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/utils/BufferGeometryUtils.js'; |
18 | | -var canvas,renderer,scene,camera,raycaster; |
19 | | - |
20 | | - |
21 | | -canvas=document.querySelector('#c'); |
22 | | -renderer= new THREE.WebGLRenderer({ |
23 | | - canvas |
24 | | -}); |
25 | | - |
26 | | -scene = new THREE.Scene(); |
27 | | -scene.background = new THREE.Color('lightblue'); |
28 | | -scene.fog= new THREE.Fog(new THREE.Color('lightblue'),0.0025, 100) |
29 | | - |
30 | | -camera = new THREE.PerspectiveCamera(75, 2, 0.1, 1000); |
31 | | -camera.rotation.order="YXZ" |
32 | | -camera.position.set(25,25,25) |
33 | | -FirstPersonControls(canvas,camera,0.07) |
| 18 | +import { EffectComposer } from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/postprocessing/EffectComposer.js'; |
| 19 | + import { SSAOPass } from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/postprocessing/SSAOPass.js'; |
34 | 20 |
|
35 | 21 |
|
36 | | -var ambientLight = new THREE.AmbientLight( 0xcccccc ); |
37 | | -scene.add( ambientLight ); |
38 | | -raycaster = new THREE.Raycaster(); |
39 | | -var mouse = {x:0,y:0}; |
40 | | - |
41 | | -animate() |
42 | | - |
43 | 22 | class Terrain{ |
44 | 23 | constructor(options){ |
45 | 24 | this.textureAtlas=options.textureAtlas; |
|
54 | 33 | [0,-1,0], |
55 | 34 | [0,1,0], |
56 | 35 | [0,0,-1], |
57 | | - [0,0,1]] |
| 36 | + [0,0,1]], |
| 37 | + this.blocks={ |
| 38 | + 1:{ |
| 39 | + nx:[3,15], |
| 40 | + ny:[2,15], |
| 41 | + nz:[3,15], |
| 42 | + px:[3,15], |
| 43 | + py:[0,15], |
| 44 | + pz:[3,15] |
| 45 | + }, |
| 46 | + 2:{ |
| 47 | + nx:[1,15], |
| 48 | + ny:[1,15], |
| 49 | + nz:[1,15], |
| 50 | + px:[1,15], |
| 51 | + py:[1,15], |
| 52 | + pz:[1,15] |
| 53 | + } |
| 54 | + } |
58 | 55 | } |
59 | 56 | parseVec(x,y,z){ |
60 | 57 | return `${x}:${y}:${z}`; |
|
73 | 70 | const cellZ = Math.floor(z / cellSize); |
74 | 71 | return `${cellX}:${cellY}:${cellZ}` |
75 | 72 | } |
76 | | - getCellId(x,y,z){ |
77 | | - const {cellSize} = this; |
78 | | - const cellX = Math.floor(x / cellSize); |
79 | | - const cellY = Math.floor(y / cellSize); |
80 | | - const cellZ = Math.floor(z / cellSize); |
81 | | - return [cellX,cellY,cellZ] |
82 | | - } |
83 | 73 | getCellForVoxel(x,y,z){ |
84 | 74 | return this.cells[this.computeCellId(x, y, z)]; |
85 | 75 | } |
|
93 | 83 | this.cells[cellId][this.parseVec(...voxel)]=v; |
94 | 84 | } |
95 | 85 | this.cells[cellId].needsUpdate=true; |
96 | | - for(var i=0;i<this.neighbours;i++){ |
| 86 | + // console.log(this.neighbours) |
| 87 | + for(var i=0;i<this.neighbours.length;i++){ |
97 | 88 | var neigh=this.neighbours[i]; |
98 | | - cellIdX=this.computeCellId(x+neigh[0],y+neigh[1],z+neigh[2]); |
99 | | - this.cells[cellIdX].needsUpdate=true; |
| 89 | + var cellIdX=this.computeCellId(x+neigh[0],y+neigh[1],z+neigh[2]); |
| 90 | + try{ |
| 91 | + this.cells[cellIdX].needsUpdate=true; |
| 92 | + }catch(e){} |
| 93 | + |
100 | 94 | } |
101 | 95 | } |
102 | 96 | getVoxel(x,y,z){ |
|
113 | 107 | return 0; |
114 | 108 | } |
115 | 109 | } |
| 110 | + updateCells(){ |
| 111 | + const{cells}=this; |
| 112 | + Object.keys(cells).forEach(function (id){ |
| 113 | + if(cells[id].needsUpdate){ |
| 114 | + world.updateCellGeometry(...id.split(":")) |
| 115 | + } |
| 116 | + }) |
| 117 | + } |
116 | 118 | updateCellGeometry(x,y,z){ |
117 | 119 | const {textureAtlas}=this; |
118 | 120 | if(this.cells[this.parseVec(x,y,z)]==undefined || this.cells[this.parseVec(x,y,z)].needsUpdate){ |
|
124 | 126 | }else{ |
125 | 127 | var geometry=geometry; |
126 | 128 | var mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { map: textureAtlas, side: 0 } ) ); |
| 129 | + // mesh.computeAngleVertexNormals(Math.PI/2); |
127 | 130 | scene.add(mesh) |
128 | 131 | this.cells_meshes[this.parseVec(x,y,z)]=mesh; |
129 | 132 | } |
|
163 | 166 | var voxel=this.getVoxel(x,y,z); |
164 | 167 | var matrix = new THREE.Matrix4(); |
165 | 168 | matrix.makeTranslation(x,y,z); |
166 | | - if(voxel==1){ |
| 169 | + if(this.blocks[voxel]!=undefined){ |
167 | 170 | var geometries=[]; |
168 | 171 | if(this.getVoxel(x-1,y,z)==0){ |
169 | | - var nxGeometry=this.generateFace("nx"); |
| 172 | + var nxGeometry=this.generateFace("nx",voxel); |
170 | 173 | geometries.push( nxGeometry.applyMatrix4( matrix ) ) |
171 | 174 | } |
172 | 175 | if(this.getVoxel(x+1,y,z)==0){ |
173 | | - var pxGeometry=this.generateFace("px"); |
| 176 | + var pxGeometry=this.generateFace("px",voxel); |
174 | 177 | geometries.push( pxGeometry.applyMatrix4( matrix ) ) |
175 | 178 | } |
176 | 179 | if(this.getVoxel(x,y-1,z)==0){ |
177 | | - var nyGeometry=this.generateFace("ny"); |
| 180 | + var nyGeometry=this.generateFace("ny",voxel); |
178 | 181 | geometries.push( nyGeometry.applyMatrix4( matrix ) ) |
179 | 182 | } |
180 | 183 | if(this.getVoxel(x,y+1,z)==0){ |
181 | | - var pyGeometry=this.generateFace("py"); |
| 184 | + var pyGeometry=this.generateFace("py",voxel); |
182 | 185 | geometries.push( pyGeometry.applyMatrix4( matrix ) ) |
183 | 186 | } |
184 | 187 | if(this.getVoxel(x,y,z-1)==0){ |
185 | | - var nzGeometry=this.generateFace("nz"); |
| 188 | + var nzGeometry=this.generateFace("nz",voxel); |
186 | 189 | geometries.push( nzGeometry.applyMatrix4( matrix ) ) |
187 | 190 | } |
188 | 191 | if(this.getVoxel(x,y,z+1)==0){ |
189 | | - var pzGeometry=this.generateFace("pz"); |
| 192 | + var pzGeometry=this.generateFace("pz",voxel); |
190 | 193 | geometries.push( pzGeometry.applyMatrix4( matrix ) ) |
191 | 194 | } |
192 | 195 | return geometries; |
193 | 196 | }else{ |
194 | 197 | return [] |
195 | 198 | } |
196 | 199 | } |
197 | | - generateFace(type){ |
| 200 | + generateFace(type,voxel){ |
198 | 201 | var geometry = new THREE.PlaneBufferGeometry(1, 1); |
199 | 202 | if(type=="px"){ |
200 | 203 | geometry.rotateY( Math.PI / 2 ); |
|
219 | 222 | geometry.rotateY( Math.PI ); |
220 | 223 | geometry.translate( 0, 0, -0.5 ); |
221 | 224 | } |
222 | | - var rx=Math.floor(Math.random()*4) |
223 | | - var ry=15 |
224 | | - this.setUv(geometry,rx,ry,180) |
| 225 | + var uv=this.blocks[voxel][type] |
| 226 | + this.setUv(geometry,uv[0],uv[1],180) |
| 227 | + |
225 | 228 | return geometry; |
226 | 229 | } |
227 | 230 | setUv(geometry,x,y,rotation=0){ |
|
256 | 259 | } |
257 | 260 |
|
258 | 261 | } |
| 262 | +var canvas,renderer,scene,camera,raycaster; |
| 263 | + |
| 264 | + |
| 265 | +canvas=document.querySelector('#c'); |
| 266 | +renderer= new THREE.WebGLRenderer({ |
| 267 | + canvas |
| 268 | +}); |
| 269 | + |
| 270 | +scene = new THREE.Scene(); |
| 271 | +scene.background = new THREE.Color('lightblue'); |
| 272 | +scene.fog= new THREE.Fog(new THREE.Color('lightblue'),50, 64) |
| 273 | + |
| 274 | +camera = new THREE.PerspectiveCamera(75, 2, 0.1, 1000); |
| 275 | +camera.rotation.order="YXZ" |
| 276 | +camera.position.set(50,50,50) |
| 277 | +FirstPersonControls(canvas,camera,0.07) |
| 278 | + |
| 279 | + |
| 280 | +var ambientLight = new THREE.AmbientLight( 0xcccccc ); |
| 281 | +scene.add( ambientLight ); |
| 282 | +raycaster = new THREE.Raycaster(); |
| 283 | +var mouse = {x:0,y:0}; |
| 284 | + |
| 285 | +var composer = new EffectComposer( renderer ); |
| 286 | +var ssaoPass = new SSAOPass( scene, camera, window.innerWidth, window.innerHeight ); |
| 287 | + ssaoPass.kernelRadius = 8; |
| 288 | + ssaoPass.minDistance = 0.001; |
| 289 | + ssaoPass.maxDistance=0.3 |
| 290 | + composer.addPass( ssaoPass ); |
| 291 | + |
| 292 | +animate() |
| 293 | + |
259 | 294 | function precision(number){ |
260 | | - var precision = (number + "").split(".")[1].length; |
| 295 | + try{ |
| 296 | + var precision = (number + "").split(".")[1].length; |
| 297 | + }catch(e){ |
| 298 | + precision=0; |
| 299 | + } |
| 300 | + |
261 | 301 | return precision; |
262 | 302 | } |
263 | 303 | var geometry = new THREE.BoxGeometry( 1, 1, 1 ); |
264 | | -var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); |
265 | | -var cube = new THREE.Mesh( geometry, material ); |
| 304 | +// var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); |
| 305 | +var edges = new THREE.EdgesGeometry( geometry ); |
| 306 | +var cube = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0x000000,linewidth:1 } ) ); |
| 307 | +var positionQ=[] |
266 | 308 | // cube.material.visible=false; |
267 | 309 | scene.add( cube ); |
268 | 310 | function raycast(){ |
|
285 | 327 |
|
286 | 328 | } |
287 | 329 | if(mini!=null){ |
| 330 | + cube.visible=true; |
288 | 331 | var xd=Math.round(mini.point.x) |
289 | 332 | var yd=Math.round(mini.point.y) |
290 | 333 | var zd=Math.round(mini.point.z) |
291 | 334 | if(precision(mini.point.x)==1){ |
292 | | - console.log("x") |
293 | 335 | var x1=Math.ceil(mini.point.x); |
294 | 336 | var x2=Math.floor(mini.point.x); |
295 | | - if(!world.getVoxel(x1,yd,zd)){ |
| 337 | + if(world.getVoxel(x1,yd,zd)){ |
296 | 338 | cube.position.set(x1,yd,zd) |
297 | | - }else if(!world.getVoxel(x2,yd,zd)){ |
| 339 | + }else if(world.getVoxel(x2,yd,zd)){ |
298 | 340 | cube.position.set(x2,yd,zd) |
299 | 341 | } |
| 342 | + if(!world.getVoxel(x1,yd,zd)){ |
| 343 | + positionQ=[x1,yd,zd] |
| 344 | + }else if(!world.getVoxel(x2,yd,zd)){ |
| 345 | + positionQ=[x2,yd,zd] |
| 346 | + } |
300 | 347 | } |
301 | 348 | if(precision(mini.point.y)==1){ |
302 | | - console.log("y") |
303 | 349 | var y1=Math.ceil(mini.point.y); |
304 | 350 | var y2=Math.floor(mini.point.y); |
305 | | - if(!world.getVoxel(xd,y1,zd)){ |
| 351 | + if(world.getVoxel(xd,y1,zd)){ |
306 | 352 | cube.position.set(xd,y1,zd) |
307 | | - }else if(!world.getVoxel(xd,y2,zd)){ |
| 353 | + }else if(world.getVoxel(xd,y2,zd)){ |
308 | 354 | cube.position.set(xd,y2,zd) |
309 | 355 | } |
| 356 | + if(!world.getVoxel(xd,y1,zd)){ |
| 357 | + positionQ=[xd,y1,zd] |
| 358 | + }else if(!world.getVoxel(xd,y2,zd)){ |
| 359 | + positionQ=[xd,y2,zd] |
| 360 | + } |
310 | 361 | } |
311 | 362 | if(precision(mini.point.z)==1){ |
312 | | - console.log("z") |
313 | 363 | var z1=Math.ceil(mini.point.z); |
314 | 364 | var z2=Math.floor(mini.point.z); |
315 | | - if(!world.getVoxel(xd,yd,z1)){ |
| 365 | + if(world.getVoxel(xd,yd,z1)){ |
316 | 366 | cube.position.set(xd,yd,z1) |
317 | | - }else if(!world.getVoxel(xd,yd,z2)){ |
| 367 | + }else if(world.getVoxel(xd,yd,z2)){ |
318 | 368 | cube.position.set(xd,yd,z2) |
319 | 369 | } |
| 370 | + if(!world.getVoxel(xd,yd,z1)){ |
| 371 | + positionQ=[xd,yd,z1] |
| 372 | + }else if(!world.getVoxel(xd,yd,z2)){ |
| 373 | + positionQ=[xd,yd,z2] |
| 374 | + } |
320 | 375 | } |
321 | 376 | // console.log(mini.point) |
| 377 | + }else{ |
| 378 | + cube.visible=false; |
322 | 379 | } |
323 | 380 |
|
324 | 381 | } |
325 | 382 |
|
326 | 383 | setInterval(function (){ |
327 | 384 | raycast() |
328 | 385 | }) |
| 386 | +setInterval(function (){ |
| 387 | + world.updateCells() |
| 388 | +},100) |
| 389 | +$(document).click(function (e){ |
| 390 | + // console.log(positionQ) |
| 391 | + // console.log(cube.position) |
| 392 | + if(e.which==1){ |
| 393 | + world.setVoxel(cube.position.x,cube.position.y,cube.position.z,0) |
| 394 | + }else{ |
| 395 | + |
| 396 | + world.setVoxel(positionQ[0],positionQ[1],positionQ[2],1) |
| 397 | + } |
| 398 | + |
| 399 | +}) |
329 | 400 |
|
330 | 401 |
|
331 | 402 | var texture = new THREE.TextureLoader().load( 'atla.png' ); |
|
334 | 405 | textureAtlas:texture, |
335 | 406 | textureRows:16, |
336 | 407 | textureCols:16, |
337 | | - cellSize:16, |
| 408 | + cellSize:24, |
338 | 409 | }) |
339 | | -var vari=50 |
| 410 | +var vari=100 |
340 | 411 | for (let y = 0; y < vari; ++y) { |
341 | | - for (let z = 0; z < vari*4; ++z) { |
| 412 | + for (let z = 0; z < vari; ++z) { |
342 | 413 | for (let x = 0; x < vari; ++x) { |
343 | 414 | const height = (Math.sin(x / vari * Math.PI * 2) + Math.sin(z / vari * Math.PI * 3)) * (vari / 6) + (vari / 2); |
344 | 415 | if (y < height) { |
345 | | - world.setVoxel(x, y, z, 1); |
| 416 | + world.setVoxel(x, y, z, 2); |
346 | 417 | } |
347 | 418 | } |
348 | 419 | } |
349 | 420 | } |
350 | | -// console.log(world.cells["0:0:0"]) |
351 | | -for(var i=0;i<10;i++){ |
352 | | - for(var j=0;j<10;j++){ |
353 | | - for(var k=0;k<10;k++){ |
354 | | - world.updateCellGeometry(i,j,k); |
355 | | - } |
356 | | - } |
357 | | -} |
358 | | - |
| 421 | +// // console.log(world.cells["0:0:0"]) |
| 422 | +// for(var i=0;i<5;i++){ |
| 423 | +// for(var j=0;j<5;j++){ |
| 424 | +// for(var k=0;k<5;k++){ |
| 425 | +// world.updateCellGeometry(i,j,k); |
| 426 | +// } |
| 427 | +// } |
| 428 | +// } |
| 429 | +world.updateCells() |
359 | 430 |
|
360 | 431 |
|
361 | 432 | function animate() { |
|
370 | 441 | const needResize = canvas.width !== width || canvas.height !== height; |
371 | 442 | if (needResize) { |
372 | 443 | renderer.setSize(width, height, false); |
| 444 | + // composer.setSize(width,height); |
373 | 445 | } |
374 | 446 | return needResize; |
375 | 447 | } |
|
381 | 453 | camera.updateProjectionMatrix(); |
382 | 454 | } |
383 | 455 | renderer.render(scene, camera); |
| 456 | + |
| 457 | + // composer.render(); |
384 | 458 | } |
385 | 459 |
|
386 | 460 |
|
|
0 commit comments