feat(stereo3d): Фаза 4 — визуал (подписи осей, свечение вершин, контраст рёбер)
- подписи осей X/Y/Z цветами AxesHelper - мягкое additive-свечение вершин (без текстур), вершины поверх рёбер - рёбра контрастнее (opacity 0.9, renderOrder над полупрозрачным телом) - bump stereo.js?v=7 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -917,6 +917,16 @@ class StereoSim {
|
|||||||
axes.material.transparent = true;
|
axes.material.transparent = true;
|
||||||
axes.material.opacity = 0.4;
|
axes.material.opacity = 0.4;
|
||||||
this._gridGroup.add(axes);
|
this._gridGroup.add(axes);
|
||||||
|
// axis letters, coloured to match AxesHelper (X red, Y green, Z blue)
|
||||||
|
const axLabel = (txt, color, pos) => {
|
||||||
|
const s = this._makeTextSprite(txt, color, 38);
|
||||||
|
s.position.copy(pos);
|
||||||
|
s.scale.multiplyScalar(0.85);
|
||||||
|
this._gridGroup.add(s);
|
||||||
|
};
|
||||||
|
axLabel('X', '#ff5b5b', new THREE.Vector3(6.5, 0.15, 0));
|
||||||
|
axLabel('Y', '#5bff8d', new THREE.Vector3(0, 6.6, 0));
|
||||||
|
axLabel('Z', '#5b9bff', new THREE.Vector3(0, 0.15, 6.5));
|
||||||
}
|
}
|
||||||
this._invalidate();
|
this._invalidate();
|
||||||
}
|
}
|
||||||
@@ -1432,13 +1442,15 @@ class StereoSim {
|
|||||||
this._figGroup.add(new THREE.Mesh(geo, mat));
|
this._figGroup.add(new THREE.Mesh(geo, mat));
|
||||||
}
|
}
|
||||||
|
|
||||||
_addEdges(opac = 0.8) {
|
_addEdges(opac = 0.9) {
|
||||||
if (!this.showEdges) return;
|
if (!this.showEdges) return;
|
||||||
for (const e of this._edges) {
|
for (const e of this._edges) {
|
||||||
const pts = [e.from, e.to];
|
const pts = [e.from, e.to];
|
||||||
const geo = new THREE.BufferGeometry().setFromPoints(pts);
|
const geo = new THREE.BufferGeometry().setFromPoints(pts);
|
||||||
const mat = new THREE.LineBasicMaterial({ color: 0xFFFFFF, transparent: true, opacity: opac, linewidth: 2 });
|
const mat = new THREE.LineBasicMaterial({ color: 0xFFFFFF, transparent: true, opacity: opac, linewidth: 2 });
|
||||||
this._figGroup.add(new THREE.Line(geo, mat));
|
const line = new THREE.Line(geo, mat);
|
||||||
|
line.renderOrder = 2; // draw over the translucent solid for crisp contrast
|
||||||
|
this._figGroup.add(line);
|
||||||
|
|
||||||
if (this.showEdgeLengths) {
|
if (this.showEdgeLengths) {
|
||||||
const len = e.from.distanceTo(e.to);
|
const len = e.from.distanceTo(e.to);
|
||||||
@@ -1454,10 +1466,21 @@ class StereoSim {
|
|||||||
_addVerticesAndLabels() {
|
_addVerticesAndLabels() {
|
||||||
for (const v of this._vertices) {
|
for (const v of this._vertices) {
|
||||||
if (this.showVertices) {
|
if (this.showVertices) {
|
||||||
|
// soft additive glow halo (texture-free → safe with _clearGroup disposal)
|
||||||
|
const gGeo = new THREE.SphereGeometry(0.17, 12, 12);
|
||||||
|
const gMat = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0x9B5DE5, transparent: true, opacity: 0.16,
|
||||||
|
blending: THREE.AdditiveBlending, depthWrite: false,
|
||||||
|
});
|
||||||
|
const glow = new THREE.Mesh(gGeo, gMat);
|
||||||
|
glow.position.copy(v.pos);
|
||||||
|
this._figGroup.add(glow);
|
||||||
|
|
||||||
const sGeo = new THREE.SphereGeometry(0.08, 12, 12);
|
const sGeo = new THREE.SphereGeometry(0.08, 12, 12);
|
||||||
const sMat = new THREE.MeshBasicMaterial({ color: 0xFFFFFF });
|
const sMat = new THREE.MeshBasicMaterial({ color: 0xFFFFFF });
|
||||||
const sphere = new THREE.Mesh(sGeo, sMat);
|
const sphere = new THREE.Mesh(sGeo, sMat);
|
||||||
sphere.position.copy(v.pos);
|
sphere.position.copy(v.pos);
|
||||||
|
sphere.renderOrder = 3;
|
||||||
this._figGroup.add(sphere);
|
this._figGroup.add(sphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4819,7 +4819,7 @@
|
|||||||
<script src="/js/labs/flask.js"></script>
|
<script src="/js/labs/flask.js"></script>
|
||||||
<script src="/js/labs/redox.js"></script>
|
<script src="/js/labs/redox.js"></script>
|
||||||
<script src="/js/labs/ionexchange.js"></script>
|
<script src="/js/labs/ionexchange.js"></script>
|
||||||
<script src="/js/labs/stereo.js?v=6"></script>
|
<script src="/js/labs/stereo.js?v=7"></script>
|
||||||
<script src="/js/notifications.js"></script>
|
<script src="/js/notifications.js"></script>
|
||||||
<script src="/js/search.js"></script>
|
<script src="/js/search.js"></script>
|
||||||
<script src="/js/mobile.js"></script>
|
<script src="/js/mobile.js"></script>
|
||||||
|
|||||||
@@ -36,10 +36,12 @@
|
|||||||
|
|
||||||
Бэклог: полное «построение сечения по следам» (продление рёбер, след на грани); readout углов (двугранный/линия-плоскость) — сейчас угол только в 3D-метке.
|
Бэклог: полное «построение сечения по следам» (продление рёбер, след на грани); readout углов (двугранный/линия-плоскость) — сейчас угол только в 3D-метке.
|
||||||
|
|
||||||
## Фаза 4 — Визуал
|
## Фаза 4 — Визуал — ГОТОВО (см. бэклог)
|
||||||
|
|
||||||
- [ ] 4.1 Материалы: рёбра с anti-alias, подсветка активной грани, свечение вершин.
|
- [x] 4.1 Свечение вершин (мягкий additive-ореол без текстур, безопасно с `_clearGroup`); рёбра контрастнее (opacity 0.9, `renderOrder` поверх полупрозрачного тела), вершины поверх рёбер. _(Подсветка грани по ховеру отложена — текущий centroid-пикинг граней грубоват для плавного hover.)_
|
||||||
- [ ] 4.2 Аккуратные оси X/Y/Z с подписями, опциональный фон (тёмный/бумага).
|
- [x] 4.2 Подписи осей X/Y/Z, цвета совпадают с AxesHelper (X крас., Y зел., Z син.).
|
||||||
|
|
||||||
|
Бэклог: подсветка грани по ховеру (нужен точный raycast по логическим граням); градиентный/бумажный фон (учесть захват в скриншоте).
|
||||||
|
|
||||||
## Фаза 5 — Интеграция и архитектура
|
## Фаза 5 — Интеграция и архитектура
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user