@broberg/bodymap 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/three.cjs +47 -8
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +16 -1
- package/dist/three.d.ts +16 -1
- package/dist/three.js +47 -9
- package/dist/three.js.map +1 -1
- package/package.json +1 -1
package/dist/three.d.ts
CHANGED
|
@@ -138,6 +138,21 @@ interface BodyMap3DUiLabels {
|
|
|
138
138
|
female: string;
|
|
139
139
|
hoverHint: string;
|
|
140
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* How much of the RUNNER-UP region bleeds into this vertex (F052.21).
|
|
143
|
+
*
|
|
144
|
+
* Takes SQUARED distances — what the assignment loop already has.
|
|
145
|
+
*
|
|
146
|
+
* ratio = d1 / (d1 + d2) → 0 at the anchor · 0.5 where two anchors are equidistant
|
|
147
|
+
*
|
|
148
|
+
* Returns 0 well inside a region and rises to 0.5 exactly at the seam, so the
|
|
149
|
+
* nearest region ALWAYS dominates and a vertex can never be painted mostly as
|
|
150
|
+
* its neighbour. Smoothstepped, so the fade has no visible start line of its own.
|
|
151
|
+
*
|
|
152
|
+
* This is a look, not a contract: hit-testing never sees this number, and the
|
|
153
|
+
* PainReport is unchanged.
|
|
154
|
+
*/
|
|
155
|
+
declare function seamBlend(nearestSq: number, secondSq: number): number;
|
|
141
156
|
interface BodyMap3DProps {
|
|
142
157
|
/** URLs of the male/female body GLBs (you host them; reference GLBs ship under `@broberg/bodymap/models/`). */
|
|
143
158
|
models: BodyMap3DModels;
|
|
@@ -171,4 +186,4 @@ interface BodyMap3DProps {
|
|
|
171
186
|
}
|
|
172
187
|
declare function BodyMap3D(props: BodyMap3DProps): react.JSX.Element;
|
|
173
188
|
|
|
174
|
-
export { BodyMap3D, type BodyMap3DModels, type BodyMap3DProps, type BodyMap3DSex, type BodyMap3DUiLabels, serializeReport };
|
|
189
|
+
export { BodyMap3D, type BodyMap3DModels, type BodyMap3DProps, type BodyMap3DSex, type BodyMap3DUiLabels, seamBlend, serializeReport };
|
package/dist/three.js
CHANGED
|
@@ -214,6 +214,17 @@ var ANCHORS = {
|
|
|
214
214
|
foot_left: [-0.1, 0.02, 0.11],
|
|
215
215
|
foot_right: [0.1, 0.02, 0.11]
|
|
216
216
|
};
|
|
217
|
+
var SEAM = 0.18;
|
|
218
|
+
function seamBlend(nearestSq, secondSq) {
|
|
219
|
+
const d1 = Math.sqrt(nearestSq), d2 = Math.sqrt(secondSq);
|
|
220
|
+
const sum = d1 + d2;
|
|
221
|
+
if (!(sum > 0)) return 0;
|
|
222
|
+
const ratio = d1 / sum;
|
|
223
|
+
const t = (ratio - (0.5 - SEAM)) / SEAM;
|
|
224
|
+
if (t <= 0) return 0;
|
|
225
|
+
if (t >= 1) return 0.5;
|
|
226
|
+
return t * t * (3 - 2 * t) * 0.5;
|
|
227
|
+
}
|
|
217
228
|
var ANCHOR_KEYS = Object.keys(ANCHORS);
|
|
218
229
|
for (const k of ANCHOR_KEYS) ANCHORS[k][0] = -ANCHORS[k][0];
|
|
219
230
|
function mergeLabels(locale, overrides) {
|
|
@@ -356,6 +367,8 @@ function BodyMap3D(props) {
|
|
|
356
367
|
let modelRoot = null;
|
|
357
368
|
let bodyMesh = null;
|
|
358
369
|
let vertexRegion = [];
|
|
370
|
+
let vertexNeighbour = [];
|
|
371
|
+
let vertexBlend = new Float32Array(0);
|
|
359
372
|
let colorAttr = null;
|
|
360
373
|
let hovered = null;
|
|
361
374
|
const loader = new GLTFLoader();
|
|
@@ -367,14 +380,32 @@ function BodyMap3D(props) {
|
|
|
367
380
|
if (selectedRef.current === key) return paletteRef.current.selected;
|
|
368
381
|
return baseColorFor(key, paletteRef.current);
|
|
369
382
|
};
|
|
370
|
-
const
|
|
383
|
+
const tmp2 = new THREE.Color();
|
|
384
|
+
const colourOf = (key) => hovered === key ? paletteRef.current.hover : restingHex(key);
|
|
385
|
+
const paint = () => {
|
|
371
386
|
if (!colorAttr) return;
|
|
372
|
-
|
|
373
|
-
|
|
387
|
+
const cache = /* @__PURE__ */ new Map();
|
|
388
|
+
const col = (k) => {
|
|
389
|
+
let c = cache.get(k);
|
|
390
|
+
if (!c) {
|
|
391
|
+
c = new THREE.Color(colourOf(k));
|
|
392
|
+
cache.set(k, c);
|
|
393
|
+
}
|
|
394
|
+
return c;
|
|
395
|
+
};
|
|
396
|
+
for (let i = 0; i < vertexRegion.length; i++) {
|
|
397
|
+
tmp.copy(col(vertexRegion[i]));
|
|
398
|
+
const w = vertexBlend[i];
|
|
399
|
+
if (w > 0) {
|
|
400
|
+
tmp2.copy(col(vertexNeighbour[i]));
|
|
401
|
+
tmp.lerp(tmp2, w);
|
|
402
|
+
}
|
|
403
|
+
colorAttr.setXYZ(i, tmp.r, tmp.g, tmp.b);
|
|
404
|
+
}
|
|
374
405
|
colorAttr.needsUpdate = true;
|
|
375
406
|
};
|
|
376
407
|
const refresh = () => {
|
|
377
|
-
|
|
408
|
+
paint();
|
|
378
409
|
renderFrame();
|
|
379
410
|
};
|
|
380
411
|
const loadModel = (which) => {
|
|
@@ -403,18 +434,27 @@ function BodyMap3D(props) {
|
|
|
403
434
|
const n = pos.count;
|
|
404
435
|
const cols = new Float32Array(n * 3);
|
|
405
436
|
vertexRegion = new Array(n);
|
|
437
|
+
vertexNeighbour = new Array(n);
|
|
438
|
+
vertexBlend = new Float32Array(n);
|
|
406
439
|
const v = new THREE.Vector3();
|
|
407
440
|
for (let i = 0; i < n; i++) {
|
|
408
441
|
v.fromBufferAttribute(pos, i).applyMatrix4(bodyMesh.matrixWorld);
|
|
409
|
-
let best = 0, bd = Infinity;
|
|
442
|
+
let best = 0, second = 0, bd = Infinity, sd = Infinity;
|
|
410
443
|
for (let a = 0; a < anchorVecs.length; a++) {
|
|
411
444
|
const d = v.distanceToSquared(anchorVecs[a]);
|
|
412
445
|
if (d < bd) {
|
|
446
|
+
sd = bd;
|
|
447
|
+
second = best;
|
|
413
448
|
bd = d;
|
|
414
449
|
best = a;
|
|
450
|
+
} else if (d < sd) {
|
|
451
|
+
sd = d;
|
|
452
|
+
second = a;
|
|
415
453
|
}
|
|
416
454
|
}
|
|
417
455
|
vertexRegion[i] = ANCHOR_KEYS[best];
|
|
456
|
+
vertexNeighbour[i] = ANCHOR_KEYS[second];
|
|
457
|
+
vertexBlend[i] = seamBlend(bd, sd);
|
|
418
458
|
}
|
|
419
459
|
colorAttr = new THREE.BufferAttribute(cols, 3);
|
|
420
460
|
geo.setAttribute("color", colorAttr);
|
|
@@ -474,10 +514,8 @@ function BodyMap3D(props) {
|
|
|
474
514
|
if ((e.buttons || 0) !== 0) return;
|
|
475
515
|
const k = pick(e.clientX, e.clientY);
|
|
476
516
|
if (k === hovered) return;
|
|
477
|
-
const prev = hovered;
|
|
478
517
|
hovered = k;
|
|
479
|
-
|
|
480
|
-
if (k) colorRegion(k, paletteRef.current.hover);
|
|
518
|
+
paint();
|
|
481
519
|
canvas.style.cursor = k ? "pointer" : "default";
|
|
482
520
|
renderFrame();
|
|
483
521
|
};
|
|
@@ -586,6 +624,6 @@ function BodyMap3D(props) {
|
|
|
586
624
|
] });
|
|
587
625
|
}
|
|
588
626
|
|
|
589
|
-
export { BodyMap3D, serializeReport };
|
|
627
|
+
export { BodyMap3D, seamBlend, serializeReport };
|
|
590
628
|
//# sourceMappingURL=three.js.map
|
|
591
629
|
//# sourceMappingURL=three.js.map
|