Refactor OceanLOD LOD levels and patch management; implement grid recentering based on camera movement
This commit is contained in:
@@ -13,18 +13,22 @@ export class OceanLOD {
|
|||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
private readonly LOD_LEVELS = [
|
private readonly LOD_LEVELS = [
|
||||||
{ distance: 5.0, gridSize: 128 }, // Closest - highest detail
|
{ distance: 3.0, gridSize: 256 }, // Very close - ultra detail
|
||||||
{ distance: 15.0, gridSize: 64 }, // Medium distance
|
{ distance: 8.0, gridSize: 128 }, // Close - high detail
|
||||||
{ distance: 40.0, gridSize: 32 }, // Far distance
|
{ distance: 20.0, gridSize: 64 }, // Medium distance
|
||||||
{ distance: 80.0, gridSize: 16 }, // Very far
|
{ distance: 40.0, gridSize: 16 }, // Far - low detail
|
||||||
{ distance: 150.0, gridSize: 8 }, // Horizon - minimal detail
|
{ distance: 80.0, gridSize: 8 }, // Very far - minimal
|
||||||
{ distance: Infinity, gridSize: 4 },// Beyond horizon - lowest detail
|
{ 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 PATCH_SIZE = 10.0; // Larger patches = fewer needed
|
||||||
private readonly PATCHES_PER_SIDE = 51; // 51x51 = 2601 patches (covers ~200 units in each direction)
|
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)
|
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() {
|
constructor() {
|
||||||
this.createGridPatches();
|
this.createGridPatches();
|
||||||
}
|
}
|
||||||
@@ -34,8 +38,8 @@ export class OceanLOD {
|
|||||||
|
|
||||||
for (let y = -halfPatches; y <= halfPatches; y++) {
|
for (let y = -halfPatches; y <= halfPatches; y++) {
|
||||||
for (let x = -halfPatches; x <= halfPatches; x++) {
|
for (let x = -halfPatches; x <= halfPatches; x++) {
|
||||||
const centerX = x * this.PATCH_SIZE;
|
const centerX = x * this.PATCH_SIZE + this.gridOriginX;
|
||||||
const centerY = y * this.PATCH_SIZE;
|
const centerY = y * this.PATCH_SIZE + this.gridOriginY;
|
||||||
|
|
||||||
// Start with lowest detail - will be updated based on camera
|
// Start with lowest detail - will be updated based on camera
|
||||||
const grid = new Grid(
|
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 */
|
/** Update LOD based on camera position and view direction */
|
||||||
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3, cameraTarget: vec3): void {
|
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3, cameraTarget: vec3): void {
|
||||||
// Calculate view direction (normalized)
|
// Calculate view direction (normalized)
|
||||||
@@ -64,6 +94,14 @@ export class OceanLOD {
|
|||||||
vec3.subtract(viewDir, cameraTarget, cameraPos);
|
vec3.subtract(viewDir, cameraTarget, cameraPos);
|
||||||
vec3.normalize(viewDir, viewDir);
|
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) {
|
for (const patch of this.grids) {
|
||||||
// Calculate vector from camera to patch center (on XY plane, Z=0 for ocean surface)
|
// Calculate vector from camera to patch center (on XY plane, Z=0 for ocean surface)
|
||||||
const toPatch = vec3.fromValues(
|
const toPatch = vec3.fromValues(
|
||||||
|
|||||||
Reference in New Issue
Block a user