From 84c914611dcf62e5da55cb9c4e9412fe764f7fe6 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Sat, 18 Apr 2026 20:35:30 +0200 Subject: [PATCH] auto-git: [add] tests/geometry/terrain-brush.test.ts --- tests/geometry/terrain-brush.test.ts | 111 +++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/geometry/terrain-brush.test.ts diff --git a/tests/geometry/terrain-brush.test.ts b/tests/geometry/terrain-brush.test.ts new file mode 100644 index 00000000..2ca7a1e0 --- /dev/null +++ b/tests/geometry/terrain-brush.test.ts @@ -0,0 +1,111 @@ +import { describe, expect, it } from "vitest"; + +import { createDefaultTerrainBrushSettings } from "../../src/core/terrain-brush"; +import { createTerrain } from "../../src/document/terrains"; +import { + applyTerrainBrushStamp, + getTerrainBrushWeight, + sampleTerrainHeightAtWorldPosition +} from "../../src/geometry/terrain-brush"; + +describe("terrain brush geometry", () => { + it("samples terrain height across the regular XZ grid", () => { + const terrain = createTerrain({ + id: "terrain-sample-height", + position: { x: 0, y: 0, z: 0 }, + sampleCountX: 2, + sampleCountZ: 2, + cellSize: 2, + heights: [0, 2, 4, 6] + }); + + expect(sampleTerrainHeightAtWorldPosition(terrain, 1, 1)).toBe(3); + }); + + it("raises and lowers height samples with radial falloff", () => { + const terrain = createTerrain({ + id: "terrain-sculpt", + position: { x: 0, y: 0, z: 0 }, + sampleCountX: 3, + sampleCountZ: 3, + cellSize: 1, + heights: new Array(9).fill(0) + }); + const settings = { + ...createDefaultTerrainBrushSettings(), + radius: 1.2, + strength: 0.5, + falloff: 0.5 + }; + const raisedTerrain = applyTerrainBrushStamp({ + terrain, + center: { x: 1, z: 1 }, + settings, + tool: "raise" + }); + const loweredTerrain = applyTerrainBrushStamp({ + terrain: raisedTerrain, + center: { x: 1, z: 1 }, + settings, + tool: "lower" + }); + + expect(raisedTerrain.heights[4]).toBeCloseTo(0.5); + expect(raisedTerrain.heights[0]).toBe(0); + expect(loweredTerrain.heights[4]).toBeCloseTo(0); + }); + + it("smooths sharp spikes toward neighboring heights", () => { + const terrain = createTerrain({ + id: "terrain-smooth", + position: { x: 0, y: 0, z: 0 }, + sampleCountX: 3, + sampleCountZ: 3, + cellSize: 1, + heights: [0, 0, 0, 0, 10, 0, 0, 0, 0] + }); + + const smoothedTerrain = applyTerrainBrushStamp({ + terrain, + center: { x: 1, z: 1 }, + settings: { + radius: 1.5, + strength: 1, + falloff: 0 + }, + tool: "smooth" + }); + + expect(smoothedTerrain.heights[4]).toBeLessThan(10); + expect(smoothedTerrain.heights[4]).toBeCloseTo(10 / 9); + }); + + it("flattens toward the stroke-start reference height", () => { + const terrain = createTerrain({ + id: "terrain-flatten", + position: { x: 0, y: 0, z: 0 }, + sampleCountX: 3, + sampleCountZ: 3, + cellSize: 1, + heights: [0, 0, 0, 0, 4, 0, 0, 0, 0] + }); + + const flattenedTerrain = applyTerrainBrushStamp({ + terrain, + center: { x: 1, z: 1 }, + settings: { + radius: 1.2, + strength: 0.5, + falloff: 0 + }, + tool: "flatten", + referenceHeight: 2 + }); + + expect(flattenedTerrain.heights[4]).toBeCloseTo(3); + }); + + it("returns zero influence outside the brush radius", () => { + expect(getTerrainBrushWeight(2, 1, 0.5)).toBe(0); + }); +});