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>
This commit is contained in:
commit
1049253d54
15 files changed
+1436
No files matched your search
@@ -0,0 +1,50 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in new issue
Block a user