mirror of
https://github.com/CNCKitchen/stlTexturizer.git
synced 2026-04-07 22:11:32 +00:00
feat: update UI labels and improve scaling parameters for better user experience
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
# STL Texturizer
|
||||
|
||||
**Live demo:** https://cnckitchen.github.io/stlTexturizer/
|
||||
|
||||
A browser-based tool for applying surface displacement textures to STL files — no installation required.
|
||||
|
||||
Load any `.stl` file, pick a texture, tune the parameters, and export a new displaced STL ready for slicing.
|
||||
|
||||
+3
-3
@@ -149,7 +149,7 @@
|
||||
<div class="form-row slider-row">
|
||||
<label for="scale-u" data-i18n="labels.scaleU">Scale U</label>
|
||||
<input type="range" id="scale-u" min="0" max="1000" step="1" value="500" />
|
||||
<input type="number" class="val" id="scale-u-val" value="1" min="0.1" max="10" step="0.1" />
|
||||
<input type="number" class="val" id="scale-u-val" value="1" min="0.05" max="10" step="0.05" />
|
||||
</div>
|
||||
<div class="lock-row">
|
||||
<div class="lock-line"></div>
|
||||
@@ -165,7 +165,7 @@
|
||||
<div class="form-row slider-row">
|
||||
<label for="scale-v" data-i18n="labels.scaleV">Scale V</label>
|
||||
<input type="range" id="scale-v" min="0" max="1000" step="1" value="500" />
|
||||
<input type="number" class="val" id="scale-v-val" value="1" min="0.1" max="10" step="0.1" />
|
||||
<input type="number" class="val" id="scale-v-val" value="1" min="0.05" max="10" step="0.05" />
|
||||
</div>
|
||||
<div class="form-row slider-row">
|
||||
<label for="offset-u" data-i18n="labels.offsetU">Offset U</label>
|
||||
@@ -283,7 +283,7 @@
|
||||
<h2 data-i18n="sections.export" data-i18n-title="tooltips.export" title="Smaller edge length = finer displacement detail. Output is then decimated to the triangle limit.">Export ⓘ</h2>
|
||||
<div class="form-row slider-row">
|
||||
<label for="refine-length" data-i18n="labels.resolution" data-i18n-title="tooltips.resolution" title="Edges longer than this value will be split during export">Resolution</label>
|
||||
<input type="range" id="refine-length" min="0.05" max="5" step="0.05" value="1" />
|
||||
<input type="range" id="refine-length" min="0.01" max="5" step="0.01" value="1" />
|
||||
<input type="number" class="val" id="refine-length-val" value="1" min="0.01" max="100" step="0.01" />
|
||||
</div>
|
||||
<div class="form-row slider-row">
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ export const TRANSLATIONS = {
|
||||
'tooltips.proportionalScalingAria': 'Proportional scaling (U = V)',
|
||||
|
||||
// Displacement section
|
||||
'sections.displacement': 'Displacement',
|
||||
'sections.displacement': 'Texture Depth',
|
||||
'labels.amplitude': 'Amplitude',
|
||||
|
||||
// Surface mask section
|
||||
@@ -143,7 +143,7 @@ export const TRANSLATIONS = {
|
||||
'ui.loadStl': 'STL laden\u2026',
|
||||
|
||||
// Displacement map section
|
||||
'sections.displacementMap': 'Verschiebungstextur',
|
||||
'sections.displacementMap': 'Textur',
|
||||
'ui.uploadCustomMap': 'Eigene Textur hochladen',
|
||||
'ui.noMapSelected': 'Keine Textur ausgew\u00e4hlt',
|
||||
|
||||
|
||||
+7
-7
@@ -117,12 +117,12 @@ const exclSectionHeading = document.getElementById('excl-section-heading');
|
||||
const exclHint = document.getElementById('excl-hint');
|
||||
|
||||
// ── Scale slider log helpers ──────────────────────────────────────────────────
|
||||
// Slider stores 0–1000; actual scale spans 0.1–10 on a log axis.
|
||||
// Middle position 500 → scale 1.0 (exact midpoint on log scale).
|
||||
const _LOG_MIN = Math.log(0.1);
|
||||
// Slider stores 0–1000; actual scale spans 0.05–10 on a log axis.
|
||||
// Middle position 500 → scale ~0.71 (log midpoint between 0.05 and 10).
|
||||
const _LOG_MIN = Math.log(0.05);
|
||||
const _LOG_MAX = Math.log(10);
|
||||
const scaleToPos = v => Math.round((Math.log(Math.max(0.1, Math.min(10, v))) - _LOG_MIN) / (_LOG_MAX - _LOG_MIN) * 1000);
|
||||
const posToScale = p => parseFloat(Math.exp(_LOG_MIN + (p / 1000) * (_LOG_MAX - _LOG_MIN)).toFixed(1));
|
||||
const scaleToPos = v => Math.round((Math.log(Math.max(0.05, Math.min(10, v))) - _LOG_MIN) / (_LOG_MAX - _LOG_MIN) * 1000);
|
||||
const posToScale = p => parseFloat(Math.exp(_LOG_MIN + (p / 1000) * (_LOG_MAX - _LOG_MIN)).toFixed(2));
|
||||
|
||||
// ── Init ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -261,7 +261,7 @@ function wireEvents() {
|
||||
|
||||
// Scale U — when lock is on, mirror to V
|
||||
const applyScaleU = (v) => {
|
||||
v = Math.max(0.1, Math.min(10, v));
|
||||
v = Math.max(0.05, Math.min(10, v));
|
||||
settings.scaleU = v;
|
||||
scaleUSlider.value = scaleToPos(v);
|
||||
scaleUVal.value = v;
|
||||
@@ -273,7 +273,7 @@ function wireEvents() {
|
||||
|
||||
// Scale V — when lock is on, mirror to U
|
||||
const applyScaleV = (v) => {
|
||||
v = Math.max(0.1, Math.min(10, v));
|
||||
v = Math.max(0.05, Math.min(10, v));
|
||||
settings.scaleV = v;
|
||||
scaleVSlider.value = scaleToPos(v);
|
||||
scaleVVal.value = v;
|
||||
|
||||
+2
-2
@@ -96,8 +96,8 @@ export function computeUV(pos, normal, mode, settings, bounds) {
|
||||
const az = Math.abs(normal.z);
|
||||
let uRaw, vRaw;
|
||||
if (ax >= ay && ax >= az) {
|
||||
uRaw = (pos.z - min.z) / md;
|
||||
vRaw = (pos.y - min.y) / md;
|
||||
uRaw = (pos.y - min.y) / md;
|
||||
vRaw = (pos.z - min.z) / md;
|
||||
} else if (ay >= ax && ay >= az) {
|
||||
uRaw = (pos.x - min.x) / md;
|
||||
vRaw = (pos.z - min.z) / md;
|
||||
|
||||
@@ -66,7 +66,7 @@ const fragmentShader = /* glsl */`
|
||||
uv -= 0.5;
|
||||
uv = vec2(c * uv.x - s * uv.y, s * uv.x + c * uv.y);
|
||||
uv += 0.5;
|
||||
return texture2D(displacementMap, fract(uv)).r;
|
||||
return texture2D(displacementMap, uv).r;
|
||||
}
|
||||
|
||||
// Height at this fragment for all projection modes.
|
||||
@@ -134,7 +134,7 @@ const fragmentShader = /* glsl */`
|
||||
// Picks the single planar projection whose axis is most aligned with the face normal.
|
||||
vec3 absN = abs(MN);
|
||||
if (absN.x >= absN.y && absN.x >= absN.z) {
|
||||
return sampleMap(vec2((pos.z - boundsMin.z) / md, (pos.y - boundsMin.y) / md));
|
||||
return sampleMap(vec2((pos.y - boundsMin.y) / md, (pos.z - boundsMin.z) / md));
|
||||
} else if (absN.y >= absN.x && absN.y >= absN.z) {
|
||||
return sampleMap(vec2((pos.x - boundsMin.x) / md, (pos.z - boundsMin.z) / md));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user