Files
minecraft-clone/js/raycast.js
T
minecraft-cloneandClaude 1049253d54 feat: Minecraft Clone MVP – prozedurale Welt, Blöcke, Abbauen/Setzen
- Weltgenerierung: FBM-Terrain, 3 Biome (Plains/Wald/Wüste), Höhlen, Wasser, Bäume
- Blöcke: Grass, Dirt, Stein, Sand, Holz, Blätter, Wasser (+Bedrock)
- Interaktion: DDA-Voxel-Raycast, Abbauen (LMB) & Setzen (RMB), Hotbar 1-6
- Spieler: First-Person, Gravitation, AABB-Kollision, Springen, Fly-Mode (F)
- Engine: Chunk-Streaming (16x16x64), Face-Culling, opaker+transparenter Pass
- Stack: Three.js + simplex-noise via CDN, prozedurale Texturen, kein Build-Step

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 23:55:12 +02:00

51 lines
1.8 KiB
JavaScript

// DDA-Voxel-Raycast (Amanatides & Woo). Liefert ersten getroffenen, soliden
// (nicht Luft, nicht Wasser) Block sowie die Eintrittsnormale (face).
import { BLOCK } from './constants.js';
export function raycastVoxel(getBlock, originX, originY, originZ, dirX, dirY, dirZ, maxDist) {
let x = Math.floor(originX);
let y = Math.floor(originY);
let z = Math.floor(originZ);
const stepX = dirX > 0 ? 1 : dirX < 0 ? -1 : 0;
const stepY = dirY > 0 ? 1 : dirY < 0 ? -1 : 0;
const stepZ = dirZ > 0 ? 1 : dirZ < 0 ? -1 : 0;
const tDeltaX = stepX !== 0 ? Math.abs(1 / dirX) : Infinity;
const tDeltaY = stepY !== 0 ? Math.abs(1 / dirY) : Infinity;
const tDeltaZ = stepZ !== 0 ? Math.abs(1 / dirZ) : Infinity;
let tMaxX = stepX > 0 ? (x + 1 - originX) * tDeltaX
: stepX < 0 ? (originX - x) * tDeltaX : Infinity;
let tMaxY = stepY > 0 ? (y + 1 - originY) * tDeltaY
: stepY < 0 ? (originY - y) * tDeltaY : Infinity;
let tMaxZ = stepZ > 0 ? (z + 1 - originZ) * tDeltaZ
: stepZ < 0 ? (originZ - z) * tDeltaZ : Infinity;
let nx = 0, ny = 0, nz = 0;
let t = 0;
// Start-Voxel pruefen
let b = getBlock(x, y, z);
if (b !== BLOCK.AIR && b !== BLOCK.WATER) {
return { x, y, z, block: b, nx: 0, ny: 0, nz: 0 };
}
const maxSteps = 128;
for (let i = 0; i < maxSteps; i++) {
if (tMaxX < tMaxY && tMaxX < tMaxZ) {
x += stepX; t = tMaxX; tMaxX += tDeltaX; nx = -stepX; ny = 0; nz = 0;
} else if (tMaxY < tMaxZ) {
y += stepY; t = tMaxY; tMaxY += tDeltaY; nx = 0; ny = -stepY; nz = 0;
} else {
z += stepZ; t = tMaxZ; tMaxZ += tDeltaZ; nx = 0; ny = 0; nz = -stepZ;
}
if (t > maxDist) break;
b = getBlock(x, y, z);
if (b !== BLOCK.AIR && b !== BLOCK.WATER) {
return { x, y, z, block: b, nx, ny, nz };
}
}
return null;
}