Interactive Preview & Customizer
3D STL viewer with browser-based OpenSCAD rendering on parameter changes.
Loading preview...
Width and length of the base
step 0.5
Maximum height of the peaks
step 0.5
Number of divisions (higher = smoother, lower = more low-poly)
step 0.1
Random seed for different mountain shapes
step 0.5
WASM compiler loads on first parameter change.
Prompt
please generate a low-poly mountain range
OpenSCAD Code
// Low-Poly Mountain Range Generator
/* [General Settings] */
// Width and length of the base
size = 100;
// Maximum height of the peaks
max_height = 45;
// Number of divisions (higher = smoother, lower = more low-poly)
resolution = 12;
// Random seed for different mountain shapes
seed = 42;
/* [Calculations] */
step = size / resolution;
// Generate pseudo-random heights based on grid position
function get_height(x, y) =
let(
// Create a central peak bias (Gaussian-like curve)
dist_from_center = sqrt(pow(x - size/2, 2) + pow(y - size/2, 2)),
center_falloff = max(0, 1 - (dist_from_center / (size/1.5))),
// Add "noise" using sine waves for a jagged look
noise = (sin(x * 15 + seed) + cos(y * 20 + seed * 1.2)) * 5,
// Final height calculation
h = (center_falloff * max_height) + noise
)
h < 2 ? 2 : h; // Ensure a minimum height for the base
// Create the point list
points = concat(
// Bottom vertices (at z=0)
[for (y = [0 : resolution]) for (x = [0 : resolution]) [x * step, y * step, 0]],
// Top vertices (mountain peaks)
[for (y = [0 : resolution]) for (x = [0 : resolution]) [x * step, y * step, get_height(x * step, y * step)]]
);
// Create the face list (triangles)
faces = concat(
// Bottom surface
[for (y = [0 : resolution - 1]) for (x = [0 : resolution - 1]) each [
[x + y * (resolution + 1), (x + 1) + y * (resolution + 1), x + (y + 1) * (resolution + 1)],
[(x + 1) + y * (resolution + 1), (x + 1) + (y + 1) * (resolution + 1), x + (y + 1) * (resolution + 1)]
]],
// Top surface (Mountain)
let(offset = pow(resolution + 1, 2))
[for (y = [0 : resolution - 1]) for (x = [0 : resolution - 1]) each [
[offset + x + y * (resolution + 1), offset + x + (y + 1) * (resolution + 1), offset + (x + 1) + y * (resolution + 1)],
[offset + (x + 1) + y * (resolution + 1), offset + x + (y + 1) * (resolution + 1), offset + (x + 1) + (y + 1) * (resolution + 1)]
]],
// Side walls
[for (i = [0 : resolution - 1])
let(
v1 = i, v2 = i + 1,
v3 = i + pow(resolution + 1, 2), v4 = i + 1 + pow(resolution + 1, 2),
// Bottom edge
b1 = i * (resolution + 1), b2 = (i + 1) * (resolution + 1),
b3 = b1 + pow(resolution + 1, 2), b4 = b2 + pow(resolution + 1, 2),
// Right edge
r1 = (resolution) + i * (resolution + 1), r2 = (resolution) + (i + 1) * (resolution + 1),
r3 = r1 + pow(resolution + 1, 2), r4 = r2 + pow(resolution + 1, 2),
// Top edge
t1 = (resolution) * (resolution + 1) + i, t2 = (resolution) * (resolution + 1) + i + 1,
t3 = t1 + pow(resolution + 1, 2), t4 = t2 + pow(resolution + 1, 2)
)
each [
// Front wall
[v1, v3, v2], [v2, v3, v4],
// Back wall
[t1, t2, t3], [t2, t4, t3],
// Left wall
[b1, b2, b3], [b2, b4, b3],
// Right wall
[r1, r3, r2], [r2, r3, r4]
]
]
);
// Render the object
color("GhostWhite")
polyhedron(points = points, faces = faces, convexity = 10);
// Optional: Add a flat base plate for stability
translate([0, 0, -2])
cube([size, size, 2]);