CORTEX
OS
Il cervello vivente · secondo cervello 81+
Lobi (sezioni)
Sinapsi
Fulcro
Impulsi
Corteccia
Tessuto
Cervelletto
↻ Auto
Avvio CORTEX OS…
>>0)/4294967295} function brainR(dx,dy,dz){const ex=.54,ey=.46,ez=.66;let r=1/Math.sqrt((dx/ex)**2+(dy/ey)**2+(dz/ez)**2);r*=(1+.07*dz);if(dy<0)r*=(1+.16*Math.abs(dx)*(-dy));if(dy<-.55)r*=.9;const a=Math.atan2(dx,dz),e=Math.asin(Math.max(-1,Math.min(1,dy)));r*=1+.04*Math.sin(a*9)*Math.cos(e*7)+.025*Math.sin(a*15+e*11);return r} // distribuzione UNIFORME: sfera di Fibonacci (direzioni) + raggio a bassa discrepanza (volume) // copre l'intero volume senza grumi ne buchi, a parita di numero di nodi const NN=DATA.nodi.length,GA=Math.PI*(3-Math.sqrt(5)),ROOT=DATA.root; const idx={};DATA.nodi.forEach((n,i)=>{idx[n.id]=i; if(n.id===ROOT){n.p=[0,-0.02,-0.04];return;} const y=1-2*(i+0.5)/NN,rad=Math.sqrt(Math.max(0,1-y*y)),th=GA*i; let dx=Math.cos(th)*rad,dy=y,dz=Math.sin(th)*rad; const u=((i+0.5)*0.7548776662466927)%1,rf=0.10+0.90*Math.cbrt(u); const R=brainR(dx,dy,dz),hemi=dx>=0?1:-1; let px=dx*R*rf*.55+hemi*(.13+.30*Math.abs(dx*R*rf)),py=dy*R*rf,pz=dz*R*rf; if(py>.12&&Math.abs(px)<.05)px+=hemi*.055;n.p=[px,py,pz];}); // texture tonda luminosa function glowTex(){const c=document.createElement('canvas');c.width=c.height=64;const x=c.getContext('2d');const g=x.createRadialGradient(32,32,0,32,32,32);g.addColorStop(0,'rgba(255,255,255,1)');g.addColorStop(.25,'rgba(255,255,255,.9)');g.addColorStop(.55,'rgba(255,255,255,.35)');g.addColorStop(1,'rgba(255,255,255,0)');x.fillStyle=g;x.beginPath();x.arc(32,32,32,0,7);x.fill();return new THREE.CanvasTexture(c)} const TEX=glowTex(); // NEURONI TONDI LUMINOSI per LOBO (un Points per sezione = toggle facile) const sectPoints={};const sectCount={}; Object.keys(DATA.lobi).forEach(sez=>{const pos=[];const ref=[];DATA.nodi.forEach((n,i)=>{if(n.sez===sez){pos.push(...n.p);ref.push(i)}});sectCount[sez]=ref.length;if(!ref.length)return; const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.Float32BufferAttribute(pos,3)); const p=new THREE.Points(g,new THREE.PointsMaterial({map:TEX,color:new THREE.Color(DATA.lobi[sez]),size:0.027,transparent:true,depthWrite:false,blending:THREE.AdditiveBlending,sizeAttenuation:true})); p.userData={sez,ref};BRAIN.add(p);sectPoints[sez]=p;}); // stato VIVO per ogni super-insieme (lobo): base, fase per neurone, ritmo dai dati reali (grado medio) const living=[];Object.keys(sectPoints).forEach((sez,li)=>{const P=sectPoints[sez],ref=P.userData.ref; const base=P.geometry.attributes.position.array.slice();const phase=new Float32Array(ref.length);let deg=0; for(let k=0;k
{const na=DATA.nodi[idx[a]],nb=DATA.nodi[idx[b]];if(!na||!nb)return;lp.push(...na.p,...nb.p);const c=new THREE.Color(DATA.lobi[na.sez]||'#889');lc.push(c.r,c.g,c.b,c.r,c.g,c.b);synArcs.push([a,b])}); const sg=new THREE.BufferGeometry();sg.setAttribute('position',new THREE.Float32BufferAttribute(lp,3));sg.setAttribute('color',new THREE.Float32BufferAttribute(lc,3)); synapses=new THREE.LineSegments(sg,new THREE.LineBasicMaterial({vertexColors:true,transparent:true,opacity:.17,blending:THREE.AdditiveBlending}));BRAIN.add(synapses)} // CORTECCIA let surf;{const g=new THREE.SphereGeometry(1,72,50);const pos=g.attributes.position;for(let i=0;i
=0?1:-1;let px=vx*R*.55+hemi*(.13+.30*Math.abs(vx*R));let py=vy*R;let pz=vz*R;if(py>.12&&Math.abs(px)<.05)px+=hemi*.055;pos.setXYZ(i,px,py,pz)}g.computeVertexNormals(); surf=new THREE.Mesh(g,new THREE.MeshBasicMaterial({color:0x33b7ff,transparent:true,opacity:.11,wireframe:true}));BRAIN.add(surf)} // TESSUTO NEURALE ambientale — micro-neuroni che riempiono densamente TUTTO il volume let dust;{const N=85000,dp=new Float32Array(N*3);let d=0;while(d
=0?1:-1;let px=dx*R*rf*.55+hemi*(.13+.30*Math.abs(dx*R*rf)),py=dy*R*rf,pz=dz*R*rf;if(py>.12&&Math.abs(px)<.05)px+=hemi*.055;dp[d*3]=px;dp[d*3+1]=py;dp[d*3+2]=pz;d++} const dg=new THREE.BufferGeometry();dg.setAttribute('position',new THREE.BufferAttribute(dp,3)); dust=new THREE.Points(dg,new THREE.PointsMaterial({map:TEX,color:0x5f8fd0,size:0.010,transparent:true,opacity:.34,depthWrite:false,blending:THREE.AdditiveBlending}));BRAIN.add(dust)} // CERVELLETTO (INBOX) const CB=new THREE.Group();CB.position.set(0,-0.42,-0.42);BRAIN.add(CB);const cbData=[]; {const cg=new THREE.SphereGeometry(0.26,40,24);cg.scale(1.2,0.55,0.85);CB.add(new THREE.Mesh(cg,new THREE.MeshBasicMaterial({color:0x5a3a12,transparent:true,opacity:.06,wireframe:true})));} const inbox=DATA.inbox||[];let cbPoints=null; if(inbox.length){const pos=[];inbox.forEach(f=>{const s1=seeded(f.name),s2=seeded(f.name+'a'),s3=seeded(f.name+'b');const u=s1*2-1,th=s2*6.283,sp=Math.sqrt(1-u*u),rr=0.22*Math.cbrt(s3);const px=sp*Math.cos(th)*rr*1.2,py=u*rr*0.5,pz=sp*Math.sin(th)*rr*0.85;cbData.push({name:f.name,rel:f.rel,p:[px,py,pz]});pos.push(px,py,pz)}); const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.Float32BufferAttribute(pos,3));cbPoints=new THREE.Points(g,new THREE.PointsMaterial({map:TEX,color:0xffa63d,size:0.05,transparent:true,depthWrite:false,blending:THREE.AdditiveBlending}));CB.add(cbPoints)} // IMPULSI tondi function roundTex(){const c=document.createElement('canvas');c.width=c.height=48;const x=c.getContext('2d');const g=x.createRadialGradient(24,24,0,24,24,24);g.addColorStop(0,'#fff');g.addColorStop(.3,'#FFD166');g.addColorStop(.6,'#00E5FF');g.addColorStop(1,'rgba(0,229,255,0)');x.fillStyle=g;x.beginPath();x.arc(24,24,24,0,7);x.fill();return new THREE.CanvasTexture(c)} const pulses=DATA.archi.filter((_,i)=>i%4===0).slice(0,450).map(a=>({a,t:seeded(a[0]+a[1])})); const pg=new THREE.BufferGeometry();const pp=new Float32Array(pulses.length*3);pg.setAttribute('position',new THREE.BufferAttribute(pp,3)); const pulseObj=new THREE.Points(pg,new THREE.PointsMaterial({map:roundTex(),size:0.04,transparent:true,depthWrite:false,blending:THREE.AdditiveBlending}));BRAIN.add(pulseObj); // ═══ NUCLEO — Centro di Comando (tutto parte dal cervelletto) ═══ const CORE=new THREE.Group();CORE.position.set(0,-0.02,-0.04);BRAIN.add(CORE); const coreMesh=new THREE.Mesh(new THREE.SphereGeometry(0.042,24,20),new THREE.MeshBasicMaterial({color:0xd6f4ff}));CORE.add(coreMesh); const coreGlow=new THREE.Sprite(new THREE.SpriteMaterial({map:TEX,color:0x5cc8ff,transparent:true,depthWrite:false,blending:THREE.AdditiveBlending}));coreGlow.scale.set(0.5,0.5,0.5);CORE.add(coreGlow); const coreHalo=new THREE.Sprite(new THREE.SpriteMaterial({map:TEX,color:0x2ea8ff,opacity:.55,transparent:true,depthWrite:false,blending:THREE.AdditiveBlending}));coreHalo.scale.set(0.95,0.95,0.95);CORE.add(coreHalo); const corePos=CORE.position; // FULCRO: ogni file e collegato al nucleo — da qui partono tutte le sinapsi (assoni radiali) let backbone;{const bl=[];DATA.nodi.forEach(n=>{bl.push(corePos.x,corePos.y,corePos.z,n.p[0],n.p[1],n.p[2])});const bg=new THREE.BufferGeometry();bg.setAttribute('position',new THREE.Float32BufferAttribute(bl,3));backbone=new THREE.LineSegments(bg,new THREE.LineBasicMaterial({color:0x3aa0ff,transparent:true,opacity:.06,blending:THREE.AdditiveBlending}));BRAIN.add(backbone)} const NE=150;const emit=[];for(let i=0;i
{const r=renderer.domElement.getBoundingClientRect();mouse.x=((e.clientX-r.left)/r.width)*2-1;mouse.y=-((e.clientY-r.top)/r.height)*2+1;ray.setFromCamera(mouse,camera);ray.params.Points.threshold=0.028;ray.params.Line.threshold=0.008; // nucleo / centro di comando {const hc=ray.intersectObject(coreMesh);if(hc.length){hEl.innerHTML='🔷
NUCLEO — Nodo Radice
'+ROOT+'
qui convergono tutti i file ·
click apri
';hEl.style.display='block';hEl.style.left=(e.clientX+13)+'px';hEl.style.top=(e.clientY+11)+'px';document.body.style.cursor='pointer';synFrozen=false;clickTarget=coreRel?{rel:coreRel,base:'WIKI'}:null;return}} // neuroni (solo lobi visibili) let best=null,bd=1e9;Object.values(sectPoints).forEach(P=>{if(!P.visible)return;const h=ray.intersectObject(P);if(h.length&&h[0].distanceToRay
'+n.id+'
'+n.sez+' · '+n.g+' link ·
click apri
';hEl.style.display='block';hEl.style.left=(e.clientX+13)+'px';hEl.style.top=(e.clientY+11)+'px';document.body.style.cursor='pointer';synFrozen=false;clickTarget={rel:n.rel,base:'WIKI'};return} // cervelletto if(cbPoints&&cbPoints.visible){const h=ray.intersectObject(cbPoints);if(h.length){const f=cbData[h[0].index];hEl.innerHTML='🟠
'+f.name+'
INBOX · da processare ·
click apri
';hEl.style.display='block';hEl.style.left=(e.clientX+13)+'px';hEl.style.top=(e.clientY+11)+'px';document.body.style.cursor='pointer';synFrozen=false;clickTarget={rel:f.rel,base:''};return}} // sinapsi → FERMA impulso if(synapses.visible){const h=ray.intersectObject(synapses);if(h.length){const arc=synArcs[Math.floor(h[0].index/2)];if(arc){synFrozen=true;hEl.innerHTML='⚡
Sinapsi
(impulso fermo)
'+arc[0]+' ↔ '+arc[1]+'
click apri file
';hEl.style.display='block';hEl.style.left=(e.clientX+13)+'px';hEl.style.top=(e.clientY+11)+'px';document.body.style.cursor='pointer';clickTarget={rel:DATA.nodi[idx[arc[0]]].rel,base:'WIKI'};return}}} hEl.style.display='none';document.body.style.cursor='default';synFrozen=false;clickTarget=null}); renderer.domElement.addEventListener('click',()=>{if(clickTarget){const u=clickTarget.base?'http://127.0.0.1:8183/'+clickTarget.base+'/'+clickTarget.rel:'http://127.0.0.1:8183/'+clickTarget.rel;window.open(u,'_blank')}}); let auto=true,pulseOn=true,clock=0; function frame(){requestAnimationFrame(frame);clock+=0.016;if(auto&&!synFrozen)BRAIN.rotation.y+=.0016; const b=1+0.30*Math.sin(clock*2.2);coreGlow.scale.set(0.5*b,0.5*b,0.5*b);coreHalo.scale.setScalar(0.95*(1+0.12*Math.sin(clock*1.6)));coreMesh.scale.setScalar(1+0.12*Math.sin(clock*2.2)); // NEURONI VIVI: micro-movimento organico + PULSAZIONE di ogni super-insieme (lobo) if(!synFrozen){for(let li=0;li
{p.t+=.005;if(p.t>1)p.t=0;const na=DATA.nodi[idx[p.a[0]]].p,nb=DATA.nodi[idx[p.a[1]]].p;pp[i*3]=na[0]+(nb[0]-na[0])*p.t;pp[i*3+1]=na[1]+(nb[1]-na[1])*p.t;pp[i*3+2]=na[2]+(nb[2]-na[2])*p.t});pg.attributes.position.needsUpdate=true; emit.forEach((e,i)=>{e.t+=.006;if(e.t>1){e.t=0;e.tn=Math.floor(seeded('em'+i+(clock|0))*DATA.nodi.length)}const tp=DATA.nodi[e.tn].p,tt=e.t*e.t;ep[i*3]=corePos.x+(tp[0]-corePos.x)*tt;ep[i*3+1]=corePos.y+(tp[1]-corePos.y)*tt;ep[i*3+2]=corePos.z+(tp[2]-corePos.z)*tt});eg.attributes.position.needsUpdate=true; } if(focusGoal&&focusGoal.on){camera.position.lerp(focusGoal.cam,0.09);controls.target.lerp(focusGoal.tar,0.09);if(camera.position.distanceTo(focusGoal.cam)<0.015)focusGoal.on=false} if(markerNode){const s=0.13*(1+0.25*Math.sin(clock*4));marker.scale.set(s,s,s);const rs=0.30*(1+0.30*Math.sin(clock*4+1));ring.scale.set(rs,rs,rs);BRAIN.updateMatrixWorld(); const v=new THREE.Vector3(markerNode.p[0],markerNode.p[1],markerNode.p[2]).applyMatrix4(BRAIN.matrixWorld).project(camera);const rect=renderer.domElement.getBoundingClientRect(); pinEl.style.left=(rect.left+(v.x*.5+.5)*rect.width+12)+'px';pinEl.style.top=(rect.top+(-v.y*.5+.5)*rect.height-10)+'px';pinEl.style.display=(v.z<1)?'block':'none'} controls.update();renderer.render(scene,camera)} frame(); document.getElementById('load').style.display='none'; // ═══ SIDEBAR: lobi toggle ═══ const lobiEl=document.getElementById('lobi'); Object.entries(DATA.lobi).forEach(([sez,col])=>{const d=document.createElement('div');d.className='lobo on'; d.innerHTML='
'+sez+'
'+(sectCount[sez]||0)+'
'; d.onclick=()=>{const P=sectPoints[sez];if(!P)return;P.visible=!P.visible;d.classList.toggle('on',P.visible)};lobiEl.appendChild(d)}); document.getElementById('fstat').innerHTML='
'+DATA.nodi.length+'
neuroni ·
'+DATA.archi.length+'
sinapsi ·
'+(DATA.inbox||[]).length+'
nel cervelletto'; // ═══ RICERCA FULL-TEXT (titolo + contenuto) → zoom sul nodo ═══ function esc(s){return (s||'').replace(/&/g,'&').replace(//g,'>')} const searchEl=document.getElementById('search'),resEl=document.getElementById('results'),rcEl=document.getElementById('rcount'); searchEl.addEventListener('input',()=>{const q=searchEl.value.toLowerCase().trim();resEl.innerHTML='';rcEl.textContent='';if(q.length<2)return; const title=[],body=[];for(const n of DATA.nodi){if(n.id.toLowerCase().includes(q))title.push(n);else if(n.t&&n.t.includes(q))body.push(n)} const tot=title.length+body.length;rcEl.textContent=tot?(tot+' risultati'+(tot>25?' · primi 25':'')+' — click = zoom, ⧉ = apri'):'nessun risultato'; title.concat(body).slice(0,25).forEach(n=>{const r=document.createElement('div');r.className='r'; let snip='';if(n.t){const p=n.t.indexOf(q);if(p>=0){const s=Math.max(0,p-24);snip=(s>0?'…':'')+esc(n.t.slice(s,p))+'
'+esc(n.t.slice(p,p+q.length))+'
'+esc(n.t.slice(p+q.length,p+q.length+46))+'…'}} r.innerHTML='
🔵 '+esc(n.id)+'
'+n.sez+'
⧉
'+(snip?'
'+snip+'
':''); r.onclick=ev=>{if(ev.target.classList.contains('ropen')){window.open('http://127.0.0.1:8183/WIKI/'+n.rel,'_blank');return}focusNode(n)};resEl.appendChild(r)})}); window.TG=k=>{if(k==='syn'){synapses.visible=!synapses.visible;document.getElementById('tSyn').className=synapses.visible?'on':''} if(k==='fulcro'){backbone.visible=!backbone.visible;document.getElementById('tFul').className=backbone.visible?'on':''} if(k==='pulse'){pulseOn=!pulseOn;pulseObj.visible=pulseOn;document.getElementById('tPulse').className=pulseOn?'on':''} if(k==='surf'){surf.visible=!surf.visible;document.getElementById('tSurf').className=surf.visible?'on':''} if(k==='dust'){dust.visible=!dust.visible;document.getElementById('tDust').className=dust.visible?'on':''} if(k==='cb'){CB.visible=!CB.visible;document.getElementById('tCb').className=CB.visible?'on':''} if(k==='auto'){auto=!auto;document.getElementById('tAuto').className=auto?'on':'';if(auto)exitFocus()}}; } if(typeof THREE==='undefined'){document.getElementById('load').innerHTML='
Errore: motore 3D non caricato
'} else{try{boot()}catch(e){document.getElementById('load').innerHTML='
Errore: '+e.message+'
';console.error(e)}}