Compare commits
1 Commits
main
...
feat/mnemo
| Author | SHA1 | Date | |
|---|---|---|---|
| 08117ef43a |
@@ -140,6 +140,47 @@ const SpatialMemory = (() => {
|
|||||||
return new THREE.OctahedronGeometry(size, 0);
|
return new THREE.OctahedronGeometry(size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── TRUST-BASED VISUALS ─────────────────────────────
|
||||||
|
// Wire crystal visual properties to fact trust score (0.0-1.0).
|
||||||
|
// Issue #1166: Trust > 0.8 = bright glow/full opacity,
|
||||||
|
// 0.5-0.8 = medium/80%, < 0.5 = dim/40%, < 0.3 = near-invisible pulsing red.
|
||||||
|
function _getTrustVisuals(trust, regionColor) {
|
||||||
|
const t = Math.max(0, Math.min(1, trust));
|
||||||
|
if (t >= 0.8) {
|
||||||
|
return {
|
||||||
|
opacity: 1.0,
|
||||||
|
emissiveIntensity: 2.0 * t,
|
||||||
|
emissiveColor: regionColor,
|
||||||
|
lightIntensity: 1.2,
|
||||||
|
glowDesc: 'high'
|
||||||
|
};
|
||||||
|
} else if (t >= 0.5) {
|
||||||
|
return {
|
||||||
|
opacity: 0.8,
|
||||||
|
emissiveIntensity: 1.2 * t,
|
||||||
|
emissiveColor: regionColor,
|
||||||
|
lightIntensity: 0.6,
|
||||||
|
glowDesc: 'medium'
|
||||||
|
};
|
||||||
|
} else if (t >= 0.3) {
|
||||||
|
return {
|
||||||
|
opacity: 0.4,
|
||||||
|
emissiveIntensity: 0.5 * t,
|
||||||
|
emissiveColor: regionColor,
|
||||||
|
lightIntensity: 0.2,
|
||||||
|
glowDesc: 'dim'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
opacity: 0.15,
|
||||||
|
emissiveIntensity: 0.3,
|
||||||
|
emissiveColor: 0xff2200,
|
||||||
|
lightIntensity: 0.1,
|
||||||
|
glowDesc: 'untrusted'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ─── REGION MARKER ───────────────────────────────────
|
// ─── REGION MARKER ───────────────────────────────────
|
||||||
function createRegionMarker(regionKey, region) {
|
function createRegionMarker(regionKey, region) {
|
||||||
const cx = region.center[0];
|
const cx = region.center[0];
|
||||||
@@ -216,17 +257,20 @@ const SpatialMemory = (() => {
|
|||||||
const region = REGIONS[mem.category] || REGIONS.working;
|
const region = REGIONS[mem.category] || REGIONS.working;
|
||||||
const pos = mem.position || _assignPosition(mem.category, mem.id);
|
const pos = mem.position || _assignPosition(mem.category, mem.id);
|
||||||
const strength = Math.max(0.05, Math.min(1, mem.strength != null ? mem.strength : 0.7));
|
const strength = Math.max(0.05, Math.min(1, mem.strength != null ? mem.strength : 0.7));
|
||||||
|
const trust = mem.trust != null ? Math.max(0, Math.min(1, mem.trust)) : 0.7;
|
||||||
const size = 0.2 + strength * 0.3;
|
const size = 0.2 + strength * 0.3;
|
||||||
|
|
||||||
|
const tv = _getTrustVisuals(trust, region.color);
|
||||||
|
|
||||||
const geo = createCrystalGeometry(size);
|
const geo = createCrystalGeometry(size);
|
||||||
const mat = new THREE.MeshStandardMaterial({
|
const mat = new THREE.MeshStandardMaterial({
|
||||||
color: region.color,
|
color: region.color,
|
||||||
emissive: region.color,
|
emissive: tv.emissiveColor,
|
||||||
emissiveIntensity: 1.5 * strength,
|
emissiveIntensity: tv.emissiveIntensity,
|
||||||
metalness: 0.6,
|
metalness: 0.6,
|
||||||
roughness: 0.15,
|
roughness: 0.15,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.5 + strength * 0.4
|
opacity: tv.opacity
|
||||||
});
|
});
|
||||||
|
|
||||||
const crystal = new THREE.Mesh(geo, mat);
|
const crystal = new THREE.Mesh(geo, mat);
|
||||||
@@ -239,10 +283,12 @@ const SpatialMemory = (() => {
|
|||||||
region: mem.category,
|
region: mem.category,
|
||||||
pulse: Math.random() * Math.PI * 2,
|
pulse: Math.random() * Math.PI * 2,
|
||||||
strength: strength,
|
strength: strength,
|
||||||
|
trust: trust,
|
||||||
|
glowDesc: tv.glowDesc,
|
||||||
createdAt: mem.timestamp || new Date().toISOString()
|
createdAt: mem.timestamp || new Date().toISOString()
|
||||||
};
|
};
|
||||||
|
|
||||||
const light = new THREE.PointLight(region.color, 0.8 * strength, 5);
|
const light = new THREE.PointLight(tv.emissiveColor, tv.lightIntensity, 5);
|
||||||
crystal.add(light);
|
crystal.add(light);
|
||||||
|
|
||||||
_scene.add(crystal);
|
_scene.add(crystal);
|
||||||
@@ -337,8 +383,16 @@ const SpatialMemory = (() => {
|
|||||||
mesh.scale.setScalar(pulse);
|
mesh.scale.setScalar(pulse);
|
||||||
|
|
||||||
if (mesh.material) {
|
if (mesh.material) {
|
||||||
|
const trust = mesh.userData.trust != null ? mesh.userData.trust : 0.7;
|
||||||
const base = mesh.userData.strength || 0.7;
|
const base = mesh.userData.strength || 0.7;
|
||||||
mesh.material.emissiveIntensity = 1.0 + Math.sin(mesh.userData.pulse * 0.7) * 0.5 * base;
|
if (trust < 0.3) {
|
||||||
|
// Low trust: pulsing red — visible warning
|
||||||
|
const pulseAlpha = 0.15 + Math.sin(mesh.userData.pulse * 2.0) * 0.15;
|
||||||
|
mesh.material.emissiveIntensity = 0.3 + Math.sin(mesh.userData.pulse * 2.0) * 0.3;
|
||||||
|
mesh.material.opacity = pulseAlpha;
|
||||||
|
} else {
|
||||||
|
mesh.material.emissiveIntensity = 1.0 + Math.sin(mesh.userData.pulse * 0.7) * 0.5 * base;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -368,6 +422,42 @@ const SpatialMemory = (() => {
|
|||||||
return REGIONS;
|
return REGIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── UPDATE VISUAL PROPERTIES ────────────────────────
|
||||||
|
// Re-render crystal when trust/strength change (no position move).
|
||||||
|
function updateMemoryVisual(memId, updates) {
|
||||||
|
const obj = _memoryObjects[memId];
|
||||||
|
if (!obj) return false;
|
||||||
|
|
||||||
|
const mesh = obj.mesh;
|
||||||
|
const region = REGIONS[obj.region] || REGIONS.working;
|
||||||
|
|
||||||
|
if (updates.trust != null) {
|
||||||
|
const trust = Math.max(0, Math.min(1, updates.trust));
|
||||||
|
mesh.userData.trust = trust;
|
||||||
|
obj.data.trust = trust;
|
||||||
|
const tv = _getTrustVisuals(trust, region.color);
|
||||||
|
mesh.material.emissive = new THREE.Color(tv.emissiveColor);
|
||||||
|
mesh.material.emissiveIntensity = tv.emissiveIntensity;
|
||||||
|
mesh.material.opacity = tv.opacity;
|
||||||
|
mesh.userData.glowDesc = tv.glowDesc;
|
||||||
|
if (mesh.children.length > 0 && mesh.children[0].isPointLight) {
|
||||||
|
mesh.children[0].intensity = tv.lightIntensity;
|
||||||
|
mesh.children[0].color = new THREE.Color(tv.emissiveColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updates.strength != null) {
|
||||||
|
const strength = Math.max(0.05, Math.min(1, updates.strength));
|
||||||
|
mesh.userData.strength = strength;
|
||||||
|
obj.data.strength = strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dirty = true;
|
||||||
|
saveToStorage();
|
||||||
|
console.info('[Mnemosyne] Visual updated:', memId, 'trust:', mesh.userData.trust, 'glow:', mesh.userData.glowDesc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ─── QUERY ───────────────────────────────────────────
|
// ─── QUERY ───────────────────────────────────────────
|
||||||
function getMemoryAtPosition(position, maxDist) {
|
function getMemoryAtPosition(position, maxDist) {
|
||||||
maxDist = maxDist || 2;
|
maxDist = maxDist || 2;
|
||||||
@@ -507,6 +597,7 @@ const SpatialMemory = (() => {
|
|||||||
source: o.data.source || 'unknown',
|
source: o.data.source || 'unknown',
|
||||||
timestamp: o.data.timestamp || o.mesh.userData.createdAt,
|
timestamp: o.data.timestamp || o.mesh.userData.createdAt,
|
||||||
strength: o.mesh.userData.strength || 0.7,
|
strength: o.mesh.userData.strength || 0.7,
|
||||||
|
trust: o.mesh.userData.trust != null ? o.mesh.userData.trust : 0.7,
|
||||||
connections: o.data.connections || []
|
connections: o.data.connections || []
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
@@ -653,7 +744,7 @@ const SpatialMemory = (() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init, placeMemory, removeMemory, update,
|
init, placeMemory, removeMemory, update, updateMemoryVisual,
|
||||||
getMemoryAtPosition, getRegionAtPosition, getMemoriesInRegion, getAllMemories,
|
getMemoryAtPosition, getRegionAtPosition, getMemoriesInRegion, getAllMemories,
|
||||||
getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId,
|
getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId,
|
||||||
exportIndex, importIndex, searchNearby, REGIONS,
|
exportIndex, importIndex, searchNearby, REGIONS,
|
||||||
|
|||||||
Reference in New Issue
Block a user