forked from mikael-lovqvist/websperiments
Strip pipeline/palette/depth/relax UI; lock to paint mode
- Remove Pipeline stage, Palette, Mesh depth, Relaxation UI sections - Remove Build button; mesh always builds as relaxed Goldberg depth-5 - Hardcode get_params() — no DOM reads for build parameters - Remove current_stage; use_relaxed is always true - Tool buttons no longer toggle paint off when re-clicking active tool Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -90,48 +90,6 @@
|
||||
<h3>Sphere Playground</h3>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Pipeline stage</h3>
|
||||
<div class="stage-grid" style="margin-top:6px">
|
||||
<button class="sb" data-stage="ico">Icosahedron</button>
|
||||
<button class="sb" data-stage="subdiv">Subdivided</button>
|
||||
<button class="sb" data-stage="goldberg">Goldberg</button>
|
||||
<button class="sb active" data-stage="relaxed">Relaxed</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Palette</h3>
|
||||
<div id="palette-grid" class="stage-grid" style="margin-top:6px">
|
||||
<!-- populated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Mesh</h3>
|
||||
<div class="param" style="margin-top:6px">
|
||||
<label>Depth</label>
|
||||
<input type="range" id="depth" min="1" max="5" value="5">
|
||||
<span class="val" id="depth-val">5</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Relaxation</h3>
|
||||
<div class="param" style="margin-top:6px">
|
||||
<label>Iterations</label>
|
||||
<input type="number" id="iters" value="500" min="0" step="50">
|
||||
</div>
|
||||
<div class="param">
|
||||
<label>α edge</label>
|
||||
<input type="number" id="alpha-edge" value="0" min="0" step="0.01">
|
||||
</div>
|
||||
<div class="param">
|
||||
<label>α centroid</label>
|
||||
<input type="number" id="alpha-centroid" value="0.04" min="0" step="0.001">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Paint</h3>
|
||||
<div style="display:flex; gap:4px; margin-top:6px">
|
||||
@@ -252,7 +210,6 @@
|
||||
</div>
|
||||
|
||||
<button id="spin-btn" style="background:#0a1a2a; border:1px solid #2a4a6a; color:#7ab; padding:7px; cursor:pointer; font-family:monospace; font-size:13px; width:100%">↻ Auto-spin</button>
|
||||
<button id="build-btn">▶ Build</button>
|
||||
|
||||
<div>
|
||||
<div id="status">Ready</div>
|
||||
|
||||
@@ -5,11 +5,11 @@ import { mat4_mul, mat4_perspective, mat4_translate_z, quat_identity, quat_from_
|
||||
import { create_program, make_buffer } from './gl_utils.mjs';
|
||||
import { PAINT_BG, PAINT_BG_PBR, PAINT_BG_NOISE, Paint_State } from './paint_state.mjs';
|
||||
import { Spin_State } from './spin_state.mjs';
|
||||
import { shape_distortion, build_triangle_geo, build_goldberg_geo } from './render_geo.mjs';
|
||||
import { shape_distortion, build_goldberg_geo } from './render_geo.mjs';
|
||||
import { build_goldberg_adjacency } from './topology.mjs';
|
||||
import { Undo_State } from './undo_state.mjs';
|
||||
import { Env_State } from './env_state.mjs';
|
||||
import { PALETTES, DEFAULT_PALETTE } from './palettes.mjs';
|
||||
import { DEFAULT_PALETTE } from './palettes.mjs';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Load shaders
|
||||
@@ -32,7 +32,6 @@ const paint = new Paint_State();
|
||||
const undo_state = new Undo_State();
|
||||
const env = new Env_State();
|
||||
let current_geo = null;
|
||||
let current_stage = 'relaxed';
|
||||
let current_palette = DEFAULT_PALETTE;
|
||||
let building = false;
|
||||
let active_brush_side = 'left';
|
||||
@@ -42,12 +41,7 @@ let paint_dirty = false;
|
||||
let debounce_timer = null;
|
||||
|
||||
function get_params() {
|
||||
return {
|
||||
depth: parseInt(document.getElementById('depth').value, 10),
|
||||
iters: parseInt(document.getElementById('iters').value, 10),
|
||||
alpha_edge: parseFloat(document.getElementById('alpha-edge').value),
|
||||
alpha_centroid: parseFloat(document.getElementById('alpha-centroid').value),
|
||||
};
|
||||
return { depth: 5, iters: 500, alpha_edge: 0, alpha_centroid: 0.04 };
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +100,7 @@ function upload_geo() {
|
||||
function rebuild_face_colors() {
|
||||
if (!cache.goldberg || !face_col_buf) { return; }
|
||||
const goldberg = cache.goldberg;
|
||||
const use_relaxed = current_stage === 'relaxed';
|
||||
const use_relaxed = true;
|
||||
const fcol = [], fpbr = [], fnoise = [];
|
||||
for (let fi = 0; fi < goldberg.faces.length; fi++) {
|
||||
const face = goldberg.faces[fi];
|
||||
@@ -202,8 +196,6 @@ function apply_history(side) {
|
||||
async function build() {
|
||||
if (building) { return; }
|
||||
building = true;
|
||||
const btn = document.getElementById('build-btn');
|
||||
btn.disabled = true;
|
||||
|
||||
const p = get_params();
|
||||
const t0 = Date.now();
|
||||
@@ -217,14 +209,6 @@ async function build() {
|
||||
cache.poly = null;
|
||||
cache.goldberg = null;
|
||||
}
|
||||
if (current_stage === 'ico') {
|
||||
current_geo = build_triangle_geo(cache.ico, current_palette);
|
||||
upload_geo();
|
||||
cache.depth = p.depth;
|
||||
set_stats(current_geo, 'Icosahedron', Date.now() - t0);
|
||||
set_status('');
|
||||
return;
|
||||
}
|
||||
|
||||
if (depth_changed || !cache.poly) {
|
||||
let poly = cache.ico;
|
||||
@@ -235,14 +219,6 @@ async function build() {
|
||||
cache.poly = poly;
|
||||
cache.goldberg = null;
|
||||
}
|
||||
if (current_stage === 'subdiv') {
|
||||
current_geo = build_triangle_geo(cache.poly, current_palette);
|
||||
upload_geo();
|
||||
cache.depth = p.depth;
|
||||
set_stats(current_geo, `Subdivided ×${p.depth}`, Date.now() - t0);
|
||||
set_status('');
|
||||
return;
|
||||
}
|
||||
|
||||
if (depth_changed || !cache.goldberg) {
|
||||
set_status('Building Goldberg dual…'); await yield_ui(30);
|
||||
@@ -250,16 +226,8 @@ async function build() {
|
||||
cache.adj = null;
|
||||
undo_state.invalidate();
|
||||
}
|
||||
if (current_stage === 'goldberg') {
|
||||
current_geo = build_goldberg_geo(cache.goldberg, false, paint, current_palette);
|
||||
upload_geo();
|
||||
cache.depth = p.depth;
|
||||
set_stats(current_geo, 'Goldberg (no relax)', Date.now() - t0);
|
||||
set_status('');
|
||||
return;
|
||||
}
|
||||
|
||||
set_status(`Relaxing (${p.iters} iters, edge=${p.alpha_edge}, centroid=${p.alpha_centroid})…`);
|
||||
set_status(`Relaxing (${p.iters} iters)…`);
|
||||
await yield_ui(50);
|
||||
cache.goldberg.relax_sphere(p.iters, p.alpha_edge, p.alpha_centroid);
|
||||
current_geo = build_goldberg_geo(cache.goldberg, true, paint, current_palette);
|
||||
@@ -270,7 +238,6 @@ async function build() {
|
||||
|
||||
} finally {
|
||||
building = false;
|
||||
btn.disabled = false;
|
||||
snapshot_now();
|
||||
}
|
||||
}
|
||||
@@ -302,7 +269,7 @@ function pick_face(px, py) {
|
||||
const hx = ro[0]+t*rd[0], hy = ro[1]+t*rd[1], hz = ro[2]+t*rd[2];
|
||||
|
||||
const goldberg = cache.goldberg;
|
||||
const use_relaxed = current_stage === 'relaxed';
|
||||
const use_relaxed = true;
|
||||
let best_fi = -1, best_dot = -Infinity;
|
||||
for (let fi = 0; fi < goldberg.faces.length; fi++) {
|
||||
const face = goldberg.faces[fi];
|
||||
@@ -409,7 +376,7 @@ function faces_at_radius(center_fi, radius) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function save_paint() {
|
||||
const depth = parseInt(document.getElementById('depth').value);
|
||||
const depth = 5;
|
||||
const faces = [];
|
||||
for (const [fi, c] of paint.face_colors) {
|
||||
const h = v => Math.round(v*255).toString(16).padStart(2, '0');
|
||||
@@ -432,10 +399,7 @@ function load_paint(file) {
|
||||
reader.onload = e => {
|
||||
try {
|
||||
const data = JSON.parse(e.target.result);
|
||||
const depth = parseInt(document.getElementById('depth').value);
|
||||
if (data.depth !== depth) {
|
||||
document.getElementById('depth').value = data.depth;
|
||||
document.getElementById('depth-val').textContent = data.depth;
|
||||
if (data.depth !== 5) {
|
||||
cache.poly = null; cache.goldberg = null; cache.adj = null;
|
||||
}
|
||||
paint.face_colors.clear();
|
||||
@@ -730,50 +694,6 @@ function render_frame(ts) {
|
||||
// UI wiring
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Palette buttons (built dynamically from PALETTES array).
|
||||
{
|
||||
const grid = document.getElementById('palette-grid');
|
||||
for (const p of PALETTES) {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'sb' + (p === DEFAULT_PALETTE ? ' active' : '');
|
||||
btn.textContent = p.name;
|
||||
btn.addEventListener('click', () => {
|
||||
current_palette = p;
|
||||
grid.querySelectorAll('.sb').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
rebuild_face_colors();
|
||||
// Triangle stages need a full rebuild since positions are shared.
|
||||
if (current_stage === 'ico' || current_stage === 'subdiv') { build(); }
|
||||
});
|
||||
grid.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('.sb').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.sb').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
current_stage = btn.dataset.stage;
|
||||
build();
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('depth').addEventListener('input', () => {
|
||||
const d = parseInt(document.getElementById('depth').value);
|
||||
document.getElementById('depth-val').textContent = d;
|
||||
document.getElementById('iters').value = d * 8;
|
||||
cache.poly = null;
|
||||
cache.goldberg = null;
|
||||
cache.adj = null;
|
||||
});
|
||||
|
||||
document.getElementById('build-btn').addEventListener('click', () => {
|
||||
if (current_stage === 'relaxed') {
|
||||
cache.goldberg = null;
|
||||
cache.adj = null;
|
||||
}
|
||||
build();
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('spin-btn').addEventListener('click', () => {
|
||||
@@ -802,12 +722,8 @@ const update_paint_buttons = () => {
|
||||
};
|
||||
|
||||
const make_tool_handler = tool => () => {
|
||||
if (!paint.enabled || paint.tool !== tool) {
|
||||
paint.enabled = true;
|
||||
paint.tool = tool;
|
||||
} else {
|
||||
paint.enabled = false;
|
||||
}
|
||||
paint.enabled = true;
|
||||
paint.tool = tool;
|
||||
update_paint_buttons();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user