Enhance OceanLOD to consider view direction in LOD updates and adjust grid size parameters
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Grid } from './Grid';
|
import { Grid } from './Grid';
|
||||||
import { vec3 } from 'gl-matrix';
|
import { vec3 } from 'gl-matrix';
|
||||||
|
|
||||||
/** Manages multiple ocean grid patches with LOD based on camera distance */
|
/** Manages multiple ocean grid patches with LOD based on camera distance and view cone */
|
||||||
export class OceanLOD {
|
export class OceanLOD {
|
||||||
private grids: Array<{
|
private grids: Array<{
|
||||||
grid: Grid;
|
grid: Grid;
|
||||||
@@ -12,14 +12,15 @@ export class OceanLOD {
|
|||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
private readonly LOD_LEVELS = [
|
private readonly LOD_LEVELS = [
|
||||||
{ distance: 2.0, gridSize: 128 }, // Closest - highest detail
|
{ distance: 2.0, gridSize: 256 }, // Closest - highest detail
|
||||||
{ distance: 5.0, gridSize: 64 }, // Medium distance
|
{ distance: 5.0, gridSize: 128 }, // Medium distance
|
||||||
{ distance: 10.0, gridSize: 32 }, // Far distance
|
{ distance: 10.0, gridSize: 64 }, // Far distance
|
||||||
{ distance: 20.0, gridSize: 16 }, // Very far - lowest detail
|
{ distance: 20.0, gridSize: 32 }, // Very far - lowest detail
|
||||||
];
|
];
|
||||||
|
|
||||||
private readonly PATCH_SIZE = 2.0; // World size of each patch
|
private readonly PATCH_SIZE = 2.0; // World size of each patch
|
||||||
private readonly PATCHES_PER_SIDE = 7; // 7x7 = 49 patches total
|
private readonly PATCHES_PER_SIDE = 7; // 7x7 = 49 patches total
|
||||||
|
private readonly VIEW_CONE_COS = Math.cos(Math.PI * 0.45); // ~81 degree half-angle (wider than typical FOV)
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.createGridPatches();
|
this.createGridPatches();
|
||||||
@@ -52,20 +53,54 @@ export class OceanLOD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update LOD based on camera position */
|
/** Update LOD based on camera position and view direction */
|
||||||
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3): void {
|
updateLOD(gl: WebGL2RenderingContext, cameraPos: vec3, cameraTarget: vec3): void {
|
||||||
for (const patch of this.grids) {
|
// Calculate view direction (normalized)
|
||||||
// Calculate distance from camera to patch center
|
const viewDir = vec3.create();
|
||||||
const dx = patch.centerX - cameraPos[0];
|
vec3.subtract(viewDir, cameraTarget, cameraPos);
|
||||||
const dy = patch.centerY - cameraPos[1];
|
vec3.normalize(viewDir, viewDir);
|
||||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
||||||
|
|
||||||
// Determine appropriate LOD level
|
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(
|
||||||
|
patch.centerX - cameraPos[0],
|
||||||
|
patch.centerY - cameraPos[1],
|
||||||
|
0 - cameraPos[2] // Ocean is at Z=0
|
||||||
|
);
|
||||||
|
const distance = vec3.length(toPatch);
|
||||||
|
|
||||||
|
// Normalize direction to patch
|
||||||
|
const toPatchDir = vec3.create();
|
||||||
|
vec3.normalize(toPatchDir, toPatch);
|
||||||
|
|
||||||
|
// Calculate dot product with view direction (how aligned is patch with where we're looking)
|
||||||
|
const dotProduct = vec3.dot(viewDir, toPatchDir);
|
||||||
|
|
||||||
|
// Determine if patch is in front of camera and within view cone
|
||||||
|
const isInFront = dotProduct > -0.2; // Slightly behind is ok for edge cases
|
||||||
|
const isInViewCone = dotProduct > this.VIEW_CONE_COS;
|
||||||
|
|
||||||
|
// Calculate LOD level
|
||||||
let newLodLevel = 3; // Default to lowest detail
|
let newLodLevel = 3; // Default to lowest detail
|
||||||
for (let i = 0; i < this.LOD_LEVELS.length; i++) {
|
|
||||||
if (distance < this.LOD_LEVELS[i].distance) {
|
if (!isInFront) {
|
||||||
newLodLevel = i;
|
// Behind camera - always lowest detail
|
||||||
break;
|
newLodLevel = 3;
|
||||||
|
} else if (isInViewCone) {
|
||||||
|
// In view cone - use distance-based LOD
|
||||||
|
for (let i = 0; i < this.LOD_LEVELS.length; i++) {
|
||||||
|
if (distance < this.LOD_LEVELS[i].distance) {
|
||||||
|
newLodLevel = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In front but outside view cone - reduce detail by 1-2 levels
|
||||||
|
for (let i = 0; i < this.LOD_LEVELS.length; i++) {
|
||||||
|
if (distance < this.LOD_LEVELS[i].distance) {
|
||||||
|
newLodLevel = Math.min(i + 2, 3); // Reduce detail
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,8 +190,8 @@ function drawScene() {
|
|||||||
camera.setRotationY((curRotY += mouseXVel * Config.MOUSE_SENSITIVITY + keyboardRotationY));
|
camera.setRotationY((curRotY += mouseXVel * Config.MOUSE_SENSITIVITY + keyboardRotationY));
|
||||||
var view = camera.getViewMatrix();
|
var view = camera.getViewMatrix();
|
||||||
|
|
||||||
// Update LOD based on camera position
|
// Update LOD based on camera position and view direction
|
||||||
oceanLOD.updateLOD(gl, camera.pos);
|
oceanLOD.updateLOD(gl, camera.pos, camera.target);
|
||||||
|
|
||||||
var model = mat4.create();
|
var model = mat4.create();
|
||||||
mat4.identity(model);
|
mat4.identity(model);
|
||||||
|
|||||||
Reference in New Issue
Block a user