Implement Ocean LOD management and enhance grid generation with wireframe support

This commit is contained in:
2026-01-31 22:22:00 +01:00
parent dedcec547d
commit d61c91a267
5 changed files with 307 additions and 121 deletions

118
src/OceanLOD.ts Normal file
View File

@@ -0,0 +1,118 @@
import { Grid } from './Grid';
import { vec3 } from 'gl-matrix';
/** Manages multiple ocean grid patches with LOD based on camera distance */
export class OceanLOD {
private grids: Array<{
grid: Grid;
centerX: number;
centerY: number;
size: number;
lodLevel: number;
}> = [];
private readonly LOD_LEVELS = [
{ distance: 2.0, gridSize: 128 }, // Closest - highest detail
{ distance: 5.0, gridSize: 64 }, // Medium distance
{ distance: 10.0, gridSize: 32 }, // Far distance
{ distance: 20.0, gridSize: 16 }, // Very far - lowest detail
];
private readonly PATCH_SIZE = 2.0; // World size of each patch
private readonly PATCHES_PER_SIDE = 7; // 7x7 = 49 patches total
constructor() {
this.createGridPatches();
}
private createGridPatches(): void {
const halfPatches = Math.floor(this.PATCHES_PER_SIDE / 2);
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;
// Start with lowest detail - will be updated based on camera
const grid = new Grid(
this.LOD_LEVELS[3].gridSize,
centerX,
centerY,
this.PATCH_SIZE
);
this.grids.push({
grid,
centerX,
centerY,
size: this.PATCH_SIZE,
lodLevel: 3
});
}
}
}
/** Update LOD based on camera position */
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3): void {
for (const patch of this.grids) {
// Calculate distance from camera to patch center
const dx = patch.centerX - cameraPos[0];
const dy = patch.centerY - cameraPos[1];
const distance = Math.sqrt(dx * dx + dy * dy);
// Determine appropriate LOD level
let newLodLevel = 3; // Default to lowest detail
for (let i = 0; i < this.LOD_LEVELS.length; i++) {
if (distance < this.LOD_LEVELS[i].distance) {
newLodLevel = i;
break;
}
}
// Only recreate grid if LOD level changed
if (newLodLevel !== patch.lodLevel) {
patch.lodLevel = newLodLevel;
patch.grid = new Grid(
this.LOD_LEVELS[newLodLevel].gridSize,
patch.centerX,
patch.centerY,
patch.size
);
patch.grid.initVAO(gl);
}
}
}
initVAO(gl: WebGL2RenderingContext): void {
for (const { grid } of this.grids) {
grid.initVAO(gl);
}
}
draw(gl: WebGL2RenderingContext, wireframe: boolean = false): void {
for (const { grid } of this.grids) {
grid.draw(gl, wireframe);
}
}
getGridCount(): number {
return this.grids.length;
}
getTotalVertexCount(): number {
let total = 0;
for (const { grid } of this.grids) {
total += grid.getIndexCount() / 3;
}
return total;
}
/** Get statistics about current LOD distribution */
getLODStats(): { [key: number]: number } {
const stats: { [key: number]: number } = { 0: 0, 1: 0, 2: 0, 3: 0 };
for (const patch of this.grids) {
stats[patch.lodLevel]++;
}
return stats;
}
}