Skip to content

Commit 3a7a938

Browse files
committed
Break and place blocks
1 parent 90faab3 commit 3a7a938

File tree

3 files changed

+175
-186
lines changed

3 files changed

+175
-186
lines changed

misc/kaaba/index.js

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,59 +1756,65 @@ async function init(format) {
17561756
}
17571757
};
17581758
}
1759-
function traceRay_impl(getVoxel, px, py, pz, dx, dy, dz, max_d = 64, hit_pos, hit_norm) {
1760-
var t = 0.0, floor = Math.floor, ix = floor(px) | 0, iy = floor(py) | 0, iz = floor(pz) | 0, stepx = dx > 0 ? 1 : -1, stepy = dy > 0 ? 1 : -1, stepz = dz > 0 ? 1 : -1, txDelta = Math.abs(1 / dx), tyDelta = Math.abs(1 / dy), tzDelta = Math.abs(1 / dz), xdist = stepx > 0 ? ix + 1 - px : px - ix, ydist = stepy > 0 ? iy + 1 - py : py - iy, zdist = stepz > 0 ? iz + 1 - pz : pz - iz, txMax = txDelta < Infinity ? txDelta * xdist : Infinity, tyMax = tyDelta < Infinity ? tyDelta * ydist : Infinity, tzMax = tzDelta < Infinity ? tzDelta * zdist : Infinity, steppedIndex = -1;
1761-
while(t <= max_d){
1762-
var b = getVoxel(ix, iy, iz);
1759+
function* raycast(getVoxel, [px, py, pz], [dx, dy, dz], maxDistance = 64) {
1760+
let t = 0;
1761+
let ix = Math.floor(px);
1762+
let iy = Math.floor(py);
1763+
let iz = Math.floor(pz);
1764+
const stepx = Math.sign(dx);
1765+
const stepy = Math.sign(dy);
1766+
const stepz = Math.sign(dz);
1767+
const txDelta = Math.abs(1 / dx);
1768+
const tyDelta = Math.abs(1 / dy);
1769+
const tzDelta = Math.abs(1 / dz);
1770+
let txMax = txDelta < Infinity ? txDelta * (stepx > 0 ? ix + 1 - px : px - ix) : Infinity;
1771+
let tyMax = tyDelta < Infinity ? tyDelta * (stepy > 0 ? iy + 1 - py : py - iy) : Infinity;
1772+
let tzMax = tzDelta < Infinity ? tzDelta * (stepz > 0 ? iz + 1 - pz : pz - iz) : Infinity;
1773+
let steppedIndex = null;
1774+
while(t <= maxDistance){
1775+
const b = getVoxel(ix, iy, iz);
17631776
if (b) {
1764-
if (hit_pos) {
1765-
hit_pos[0] = px + t * dx;
1766-
hit_pos[1] = py + t * dy;
1767-
hit_pos[2] = pz + t * dz;
1768-
}
1769-
if (hit_norm) {
1770-
hit_norm[0] = hit_norm[1] = hit_norm[2] = 0;
1771-
if (steppedIndex === 0) hit_norm[0] = -stepx;
1772-
if (steppedIndex === 1) hit_norm[1] = -stepy;
1773-
if (steppedIndex === 2) hit_norm[2] = -stepz;
1774-
}
1775-
return b;
1777+
yield {
1778+
block: [
1779+
ix,
1780+
iy,
1781+
iz
1782+
],
1783+
position: [
1784+
px + t * dx,
1785+
py + t * dy,
1786+
pz + t * dz
1787+
],
1788+
normal: [
1789+
steppedIndex === 'x' ? -stepx : 0,
1790+
steppedIndex === 'y' ? -stepy : 0,
1791+
steppedIndex === 'z' ? -stepz : 0
1792+
]
1793+
};
17761794
}
1777-
if (txMax < tyMax) {
1778-
if (txMax < tzMax) {
1795+
switch(Math.min(txMax, tyMax, tzMax)){
1796+
case txMax:
17791797
ix += stepx;
17801798
t = txMax;
17811799
txMax += txDelta;
1782-
steppedIndex = 0;
1783-
} else {
1784-
iz += stepz;
1785-
t = tzMax;
1786-
tzMax += tzDelta;
1787-
steppedIndex = 2;
1788-
}
1789-
} else {
1790-
if (tyMax < tzMax) {
1800+
steppedIndex = 'x';
1801+
break;
1802+
case tyMax:
17911803
iy += stepy;
17921804
t = tyMax;
17931805
tyMax += tyDelta;
1794-
steppedIndex = 1;
1795-
} else {
1806+
steppedIndex = 'y';
1807+
break;
1808+
case tzMax:
17961809
iz += stepz;
17971810
t = tzMax;
17981811
tzMax += tzDelta;
1799-
steppedIndex = 2;
1800-
}
1812+
steppedIndex = 'z';
1813+
break;
1814+
default:
1815+
throw new Error('The minimum is none of these. ??');
18011816
}
18021817
}
1803-
if (hit_pos) {
1804-
hit_pos[0] = px + t * dx;
1805-
hit_pos[1] = py + t * dy;
1806-
hit_pos[2] = pz + t * dz;
1807-
}
1808-
if (hit_norm) {
1809-
hit_norm[0] = hit_norm[1] = hit_norm[2] = 0;
1810-
}
1811-
return 0;
18121818
}
18131819
const errorMessages = document.getElementById('error');
18141820
function handleError(error) {
@@ -2039,43 +2045,47 @@ function paint() {
20392045
});
20402046
frameId = requestAnimationFrame(paint);
20412047
}
2042-
function raycast() {
2043-
const hit_position = [
2044-
0,
2045-
20,
2046-
0
2047-
];
2048-
const hit_normal = [
2049-
0,
2050-
20,
2051-
0
2052-
];
2048+
function doRaycast() {
20532049
const [dx, dy, dz] = oe.transformMat4Upper3x3([
20542050
0,
20552051
0,
20562052
-1
20572053
], ce.rotateZ(ce.rotateX(ce.rotationY(-player.yaw), -player.pitch), -player.roll));
20582054
const length = Math.hypot(dx, dy, dz);
2059-
console.log('dir', dx / length, dy / length, dz / length);
2060-
const result = traceRay_impl((x, y, z)=>{
2061-
console.log('getblock', x, y, z, getBlock(x, y, z));
2062-
return isSolid(getBlock(x, y, z));
2063-
}, player.x, player.y, player.z, dx / length, dy / length, dz / length, 10, hit_position, hit_normal);
2064-
if (result) {
2065-
return {
2066-
hit_position,
2067-
hit_normal
2068-
};
2069-
} else {
2070-
return null;
2071-
}
2055+
const result = raycast((x, y, z)=>isSolid(getBlock(x, y, z)), [
2056+
player.x,
2057+
player.y,
2058+
player.z
2059+
], [
2060+
dx / length,
2061+
dy / length,
2062+
dz / length
2063+
], 64).next();
2064+
return result.done ? null : result.value;
20722065
}
20732066
canvas.addEventListener('mousedown', (e)=>{
2074-
if (e.button === 0) {
2075-
const result = raycast();
2076-
console.log(result);
2077-
if (result) {
2078-
setBlock(Math.floor(result.hit_position[0]), Math.floor(result.hit_position[1]), Math.floor(result.hit_position[2]), Block.WHITE);
2067+
const result = doRaycast();
2068+
if (result) {
2069+
switch(e.button){
2070+
case 0:
2071+
{
2072+
setBlock(...result.block, Block.AIR);
2073+
break;
2074+
}
2075+
case 1:
2076+
{
2077+
console.log(getBlock(...result.block));
2078+
break;
2079+
}
2080+
case 2:
2081+
{
2082+
const target = oe.add(result.block, result.normal);
2083+
if (getBlock(target[0], target[1], target[2]) === Block.AIR) {
2084+
setBlock(target[0], target[1], target[2], Block.WHITE);
2085+
}
2086+
break;
2087+
}
20792088
}
20802089
}
2090+
if (e.button === 0) {}
20812091
});

misc/kaaba/index.ts

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
import '@webgpu/types'
66
import { Vector2 } from 'https://sheeptester.github.io/javascripts/Vector2.js'
77
// _ @deno-types="npm:wgpu-matrix"
8-
import { mat4, vec3, vec4 } from 'wgpu-matrix'
9-
import { ChunkPosition, SIZE } from './Chunk.ts'
8+
import { mat4, vec3 } from 'wgpu-matrix'
9+
import { SIZE } from './Chunk.ts'
1010
import { Block, isSolid } from './blocks.ts'
11-
import { traceRay_impl } from './raycast.ts'
11+
import { raycast } from './raycast.ts'
1212
import { init } from './webgpu.ts'
13+
import { RaycastResult } from './raycast.ts'
1314

1415
const errorMessages = document.getElementById('error')
1516
function handleError (error: unknown) {
@@ -309,10 +310,7 @@ function paint () {
309310
frameId = requestAnimationFrame(paint)
310311
}
311312

312-
function raycast () {
313-
const hit_position: ChunkPosition = [0, 20, 0]
314-
const hit_normal: ChunkPosition = [0, 20, 0]
315-
313+
function doRaycast (): RaycastResult | null {
316314
const [dx, dy, dz] = vec3.transformMat4Upper3x3(
317315
[0, 0, -1],
318316
mat4.rotateZ(
@@ -321,41 +319,36 @@ function raycast () {
321319
)
322320
)
323321
const length = Math.hypot(dx, dy, dz)
324-
325-
console.log('dir', dx / length, dy / length, dz / length)
326-
const result = traceRay_impl(
327-
(x, y, z) => {
328-
console.log('getblock', x, y, z, getBlock(x, y, z))
329-
return isSolid(getBlock(x, y, z))
330-
},
331-
player.x,
332-
player.y,
333-
player.z,
334-
dx / length,
335-
dy / length,
336-
dz / length,
337-
10,
338-
hit_position,
339-
hit_normal
340-
)
341-
if (result) {
342-
return { hit_position, hit_normal }
343-
} else {
344-
return null
345-
}
322+
const result = raycast(
323+
(x, y, z) => isSolid(getBlock(x, y, z)),
324+
[player.x, player.y, player.z],
325+
[dx / length, dy / length, dz / length],
326+
64
327+
).next()
328+
return result.done ? null : result.value
346329
}
347330

348331
canvas.addEventListener('mousedown', e => {
349-
if (e.button === 0) {
350-
const result = raycast()
351-
console.log(result)
352-
if (result) {
353-
setBlock(
354-
Math.floor(result.hit_position[0]),
355-
Math.floor(result.hit_position[1]),
356-
Math.floor(result.hit_position[2]),
357-
Block.WHITE
358-
)
332+
const result = doRaycast()
333+
if (result) {
334+
switch (e.button) {
335+
case 0: {
336+
setBlock(...result.block, Block.AIR)
337+
break
338+
}
339+
case 1: {
340+
console.log(getBlock(...result.block))
341+
break
342+
}
343+
case 2: {
344+
const target = vec3.add(result.block, result.normal)
345+
if (getBlock(target[0], target[1], target[2]) === Block.AIR) {
346+
setBlock(target[0], target[1], target[2], Block.WHITE)
347+
}
348+
break
349+
}
359350
}
360351
}
352+
if (e.button === 0) {
353+
}
361354
})

0 commit comments

Comments
 (0)