Refactor OceanLOD LOD levels and patch management; implement grid recentering based on camera movement

This commit is contained in:
2026-01-31 23:21:19 +01:00
parent 5677f03dc2
commit 503435bdf7

View File

@@ -13,18 +13,22 @@ export class OceanLOD {
}> = [];
private readonly LOD_LEVELS = [
{ distance: 5.0, gridSize: 128 }, // Closest - highest detail
{ distance: 15.0, gridSize: 64 }, // Medium distance
{ distance: 40.0, gridSize: 32 }, // Far distance
{ distance: 80.0, gridSize: 16 }, // Very far
{ distance: 150.0, gridSize: 8 }, // Horizon - minimal detail
{ distance: Infinity, gridSize: 4 },// Beyond horizon - lowest detail
{ distance: 3.0, gridSize: 256 }, // Very close - ultra detail
{ distance: 8.0, gridSize: 128 }, // Close - high detail
{ distance: 20.0, gridSize: 64 }, // Medium distance
{ distance: 40.0, gridSize: 16 }, // Far - low detail
{ distance: 80.0, gridSize: 8 }, // Very far - minimal
{ distance: Infinity, gridSize: 4 },// Horizon - lowest (will be stretched anyway)
];
private readonly PATCH_SIZE = 8.0; // World size of each patch (larger for horizon coverage)
private readonly PATCHES_PER_SIDE = 51; // 51x51 = 2601 patches (covers ~200 units in each direction)
private readonly PATCH_SIZE = 10.0; // Larger patches = fewer needed
private readonly PATCHES_PER_SIDE = 21; // 21x21 = 441 patches (covers ~200 units)
private readonly VIEW_CONE_COS = Math.cos(Math.PI * 0.45); // ~81 degree half-angle (wider than typical FOV)
// Track the grid origin to re-center when camera moves
private gridOriginX: number = 0;
private gridOriginY: number = 0;
constructor() {
this.createGridPatches();
}
@@ -34,8 +38,8 @@ export class OceanLOD {
for (let y = -halfPatches; y <= halfPatches; y++) {
for (let x = -halfPatches; x <= halfPatches; x++) {
const centerX = x * this.PATCH_SIZE;
const centerY = y * this.PATCH_SIZE;
const centerX = x * this.PATCH_SIZE + this.gridOriginX;
const centerY = y * this.PATCH_SIZE + this.gridOriginY;
// Start with lowest detail - will be updated based on camera
const grid = new Grid(
@@ -57,6 +61,32 @@ export class OceanLOD {
}
}
/** Re-center the grid around a new origin */
private recenterGrid(gl: WebGL2RenderingContext, newOriginX: number, newOriginY: number): void {
this.gridOriginX = newOriginX;
this.gridOriginY = newOriginY;
const halfPatches = Math.floor(this.PATCHES_PER_SIDE / 2);
let i = 0;
for (let y = -halfPatches; y <= halfPatches; y++) {
for (let x = -halfPatches; x <= halfPatches; x++) {
const patch = this.grids[i];
const newCenterX = x * this.PATCH_SIZE + this.gridOriginX;
const newCenterY = y * this.PATCH_SIZE + this.gridOriginY;
// Only update if patch position changed
if (patch.centerX !== newCenterX || patch.centerY !== newCenterY) {
patch.centerX = newCenterX;
patch.centerY = newCenterY;
// Force LOD recalculation
patch.lodLevel = -1;
}
i++;
}
}
}
/** Update LOD based on camera position and view direction */
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3, cameraTarget: vec3): void {
// Calculate view direction (normalized)
@@ -64,6 +94,14 @@ export class OceanLOD {
vec3.subtract(viewDir, cameraTarget, cameraPos);
vec3.normalize(viewDir, viewDir);
// Check if we need to recenter the grid (camera moved more than one patch size from origin)
const cameraGridX = Math.floor(cameraPos[0] / this.PATCH_SIZE) * this.PATCH_SIZE;
const cameraGridY = Math.floor(cameraPos[1] / this.PATCH_SIZE) * this.PATCH_SIZE;
if (cameraGridX !== this.gridOriginX || cameraGridY !== this.gridOriginY) {
this.recenterGrid(gl, cameraGridX, cameraGridY);
}
for (const patch of this.grids) {
// Calculate vector from camera to patch center (on XY plane, Z=0 for ocean surface)
const toPatch = vec3.fromValues(