From 770e6f47d274368f26e387b4fc2dd11a2bbcdbf0 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Wed, 5 Aug 2026 14:37:54 +0800 Subject: [PATCH] =?UTF-8?q?cmake=E5=BA=93=E6=94=B9=E9=80=A0=E5=89=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Map/Terrarium_Height.ts | 80 +++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/Map/Terrarium_Height.ts diff --git a/src/Map/Terrarium_Height.ts b/src/Map/Terrarium_Height.ts new file mode 100644 index 0000000..86514e5 --- /dev/null +++ b/src/Map/Terrarium_Height.ts @@ -0,0 +1,80 @@ +export function terrarium_height(red: number, green: number, blue: number): number { + return red * 256 + green + blue / 256 - 32768; +} +export function is_valid_earth_height(height: number): boolean { + return Number.isFinite(height) && height >= -12000 && height <= 12000; +} +export function bilinear_height(heights: Float32Array, size: number, x: number, y: number): number { + const x0 = Math.floor(x); + const y0 = Math.floor(y); + const x1 = Math.min(size - 1, x0 + 1); + const y1 = Math.min(size - 1, y0 + 1); + const tx = x - x0; + const ty = y - y0; + const h00 = heights[y0 * size + x0]; + const h10 = heights[y0 * size + x1]; + const h01 = heights[y1 * size + x0]; + const h11 = heights[y1 * size + x1]; + const h0 = h00 * (1 - tx) + h10 * tx; + const h1 = h01 * (1 - tx) + h11 * tx; + return h0 * (1 - ty) + h1 * ty; +} +export function fill_height_gaps_from_parent(heights: Float32Array, parent: Float32Array, size: number, tile_x: number, tile_y: number): number { + const quadrant_x = tile_x & 1; + const quadrant_y = tile_y & 1; + let filled = 0; + for (let y = 0; y < size; ++y) { + const local_v = y / (size - 1); + const parent_y = (quadrant_y + local_v) * 0.5 * (size - 1); + for (let x = 0; x < size; ++x) { + const index = y * size + x; + if (Number.isFinite(heights[index])) { + continue; + } + const local_u = x / (size - 1); + const parent_x = (quadrant_x + local_u) * 0.5 * (size - 1); + heights[index] = bilinear_height(parent, size, parent_x, parent_y); + ++filled; + } + } + return filled; +} +export function fill_height_gaps_from_nearest(heights: Float32Array, size: number): boolean { + const queue = new Int32Array(heights.length); + let head = 0; + let tail = 0; + for (let index = 0; index < heights.length; ++index) { + if (Number.isFinite(heights[index])) { + queue[tail++] = index; + } + } + if (tail === 0) { + return false; + } + while (head < tail) { + const index = queue[head++]; + const x = index % size; + const y = Math.floor(index / size); + if (x > 0) { + tail = fill_neighbor(heights, queue, tail, index, index - 1); + } + if (x + 1 < size) { + tail = fill_neighbor(heights, queue, tail, index, index + 1); + } + if (y > 0) { + tail = fill_neighbor(heights, queue, tail, index, index - size); + } + if (y + 1 < size) { + tail = fill_neighbor(heights, queue, tail, index, index + size); + } + } + return true; +} +function fill_neighbor(heights: Float32Array, queue: Int32Array, tail: number, source: number, target: number): number { + if (Number.isFinite(heights[target])) { + return tail; + } + heights[target] = heights[source]; + queue[tail] = target; + return tail + 1; +}