/
nacha
/
pseado
Обзор
Документация
Войти
/
nacha
/
pseado
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
Безопасность
master
fullcube.html
208 строк
14 KB
alex
Update FullCube to v3.0 — optimized rendering, streamlined UI, performance metrics, interactive slice navigation
03 авг 2026, 12:26
Верифицирован
03 авг 2026, 12:26
1d1e442
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>FullCube Monitor v3.0 — 1 000 000 точек</title> <style> :root { --bg: #050510; --panel: #0a0a1a; --border: #1a1a3a; --primary: #00f0ff; --sec: #7000ff; --acc: #ff0055; --text: #d0d0e0; --dim: #505060; --font: 'Courier New', monospace; } * { margin: 0; padding: 0; box-sizing: border-box; } body { background: var(--bg); color: var(--text); font-family: var(--font); overflow: hidden; height: 100vh; display: flex; flex-direction: column; } #topbar { display: flex; justify-content: space-between; align-items: center; padding: 10px 20px; background: var(--panel); border-bottom: 1px solid var(--border); z-index: 10; } #topbar h1 { font-size: 16px; color: var(--primary); letter-spacing: 2px; } #topbar h1::before { content: '◈ '; color: var(--sec); } #metrics { display: flex; gap: 20px; font-size: 11px; } #metrics div { color: var(--dim); } #metrics span { color: var(--text); margin-left: 4px; } #viewport { flex: 1; position: relative; } canvas { display: block; width: 100%; height: 100%; } #overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .panel { position: absolute; background: rgba(10,10,26,0.9); border: 1px solid var(--border); padding: 12px; font-size: 11px; backdrop-filter: blur(4px); } #info-panel { top: 15px; left: 15px; min-width: 180px; } #info-panel h3 { color: var(--primary); margin-bottom: 8px; font-size: 12px; } .row { display: flex; justify-content: space-between; margin-bottom: 4px; } .label { color: var(--dim); } .val { color: var(--text); } #slice-panel { top: 15px; right: 15px; width: 160px; } #slice-panel h3 { color: var(--sec); margin-bottom: 8px; font-size: 12px; } input[type=range] { width: 100%; accent-color: var(--sec); margin: 8px 0; } .range-val { text-align: center; color: var(--sec); font-size: 14px; } #term { bottom: 15px; left: 15px; width: 320px; height: 120px; overflow-y: auto; border-color: var(--dim); } #term h4 { color: var(--acc); margin-bottom: 6px; font-size: 11px; } .log { font-size: 10px; color: var(--dim); margin-bottom: 2px; } .log.info { color: var(--primary); } .log.warn { color: var(--acc); } #controls { position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; z-index: 10; } .btn { background: var(--panel); border: 1px solid var(--primary); color: var(--primary); padding: 6px 14px; cursor: pointer; font-family: var(--font); font-size: 10px; transition: 0.2s; } .btn:hover { background: rgba(0,240,255,0.15); } .btn.active { background: var(--primary); color: var(--bg); } #help { bottom: 15px; right: 15px; font-size: 10px; color: var(--dim); } kbd { color: var(--primary); border: 1px solid var(--dim); padding: 1px 4px; border-radius: 3px; } </style> </head> <body> <div id="topbar"> <h1>FULLCUBE MONITOR</h1> <div id="metrics"> <div>ТОЧЕК<span>1 000 000</span></div> <div>РАЗМЕР<span>100³</span></div> <div>СЛОЕВ<span>100</span></div> <div>∛10⁶<span>= 100</span></div> <div>FPS<span id="fps-val">60</span></div> </div> </div> <div id="viewport"> <canvas id="c"></canvas> <div id="info-panel" class="panel"> <h3>СТАТУС СИСТЕМЫ</h3> <div class="row"><span class="label">Режим:</span><span class="val" id="m-mode">КУБ</span></div> <div class="row"><span class="label">Отрисовано:</span><span class="val" id="m-draw">0</span></div> <div class="row"><span class="label">Угол X:</span><span class="val" id="m-ax">0°</span></div> <div class="row"><span class="label">Угол Y:</span><span class="val" id="m-ay">0°</span></div> <div class="row"><span class="label">FOV:</span><span class="val" id="m-fov">300</span></div> <div class="row"><span class="label">Статус:</span><span class="val" style="color:#0f0">ОНЛАЙН</span></div> </div> <div id="slice-panel" class="panel"> <h3>СРЕЗ СЛОЯ</h3> <input type="range" id="slice-slider" min="0" max="99" value="0"> <div class="range-val">Слой: <span id="slice-val">0</span> / 99</div> <div style="margin-top:8px;font-size:10px;color:var(--dim)">Точек в срезе: 10 000</div> </div> <div id="term" class="panel"> <h4>> ЖУРНАЛ</h4> <div id="logs"></div> </div> <div id="help" class="panel"> <div><kbd>1-6</kbd> Режимы | <kbd>← →</kbd> Слой | <kbd>Пробел</kbd> Пауза | <kbd>R</kbd> Сброс</div> </div> <div id="controls"> <button class="btn active" data-m="cube">КУБ</button> <button class="btn" data-m="slices">СЛОИ</button> <button class="btn" data-m="explode">ВЗРЫВ</button> <button class="btn" data-m="grid">КАРКАС</button> <button class="btn" data-m="flow">ПОТОК</button> <button class="btn" data-m="stream">ПОТОК ДАННЫХ</button> </div> </div> <script> const SIZE=100, TOTAL=SIZE*SIZE*SIZE, LAYERS=SIZE, PPL=SIZE*SIZE, FOV=300; const state={mode:'cube',layer:0,ax:0.4,ay:0.3,auto:true,fov:FOV,flow:0,paused:false,strm:[],last:performance.now(),fc:0,fps:60}; const c=document.getElementById('c'), x=c.getContext('2d'), vp=document.getElementById('viewport'); let W,H,CX,CY; function resize(){W=c.width=vp.clientWidth;H=c.height=vp.clientHeight;CX=W/2;CY=H/2;} resize(); window.addEventListener('resize',resize); // Generate points const pts=[]; const B=SIZE/2; for(let z=0;z<LAYERS;z++)for(let y=0;y<SIZE;y++)for(let xx=0;xx<SIZE;xx++){ pts.push({x:xx-B,y:y-B,z:z-B,l:z,hx:xx/SIZE,hy:y/SIZE,hz:z/SIZE}); } log('Инициализация... Генерация '+TOTAL.toLocaleString()+' точек.','info'); log('Корень кубический из '+TOTAL+' = '+SIZE+' (слоёв).'); function proj(p){ const cX=Math.cos(state.ax),sX=Math.sin(state.ax),cY=Math.cos(state.ay),sY=Math.sin(state.ay); let x1=p.x*cY-p.z*sY, z1=p.x*sY+p.z*cY, y1=p.y*cX-z1*sX, z2=p.y*sX+z1*cX; const sc=state.fov/(state.fov+z2+SIZE*0.8); return {sx:CX+x1*sc,sy:CY+y1*sc,sc,z:z2}; } function hsl(p,a=1){ const h=(p.hx*60+p.hy*120+p.hz*180+state.flow*50)%360; const s=70+15*Math.sin(state.flow), l=45+15*Math.sin(p.hx*Math.PI*2); return `hsla(${h},${s}%,${l}%,${a})`; } function log(m,t=''){document.getElementById('logs').innerHTML+=`<div class="log ${t}">${m}</div>`;const el=document.getElementById('logs');el.scrollTop=el.scrollHeight;if(el.children.length>15)el.removeChild(el.firstChild);} function draw(){ if(!state.paused){ x.fillStyle='#050510'; x.fillRect(0,0,W,H); // Grid x.strokeStyle='rgba(26,26,58,0.3)'; x.lineWidth=0.5; for(let i=0;i<=12;i++){x.beginPath();x.moveTo((W/12)*i,0);x.lineTo((W/12)*i,H);x.stroke();x.beginPath();x.moveTo(0,(H/12)*i);x.lineTo(W,(H/12)*i);x.stroke();} let cnt=0, step=Math.max(1,Math.ceil(pts.length/50000)); if(state.mode==='cube'){ const prj=pts.map(p=>({...p,...proj(p)})).sort((a,b)=>b.z-a.z); for(let i=0;i<prj.length;i+=step){const p=prj[i];if(p.sc<=0)continue;x.fillStyle=hsl(p,Math.min(1,p.sc*0.7));x.fillRect(p.sx,p.sy,Math.max(0.5,p.sc),Math.max(0.5,p.sc));cnt++;} } else if(state.mode==='slices'){ const start=state.layer; for(let l=-2;l<=2;l++){ const z=(start+l+LAYERS)%LAYERS; for(let y=0;y<SIZE;y+=4)for(let xx=0;xx<SIZE;xx+=4){ const p=proj({x:xx-B,y:y-B,z:z-B,l:z,hx:xx/SIZE,hy:y/SIZE,hz:z/SIZE}); if(p.sc>0){x.fillStyle=hsl({hx:xx/SIZE,hy:y/SIZE,hz:z/SIZE,flow:state.flow},0.8-l*0.15);x.fillRect(p.sx,p.sy,2,2);cnt++;} } } } else if(state.mode==='explode'){ const f=1.8; pts.forEach(p=>{const prj=proj({x:p.x*f,y:p.y*f,z:p.z*f,l:p.l,hx:p.hx,hy:p.hy,hz:p.hz});if(prj.sc>0){x.fillStyle=hsl(p,Math.max(0.1,prj.sc*0.5));x.fillRect(prj.sx,prj.sy,Math.max(0.5,prj.sc*0.7),Math.max(0.5,prj.sc*0.7));cnt++;}}); } else if(state.mode==='grid'){ x.strokeStyle='#00f0ff'; x.globalAlpha=0.3; x.lineWidth=0.5; const s2=20; for(let z=0;z<SIZE;z+=s2)for(let y=0;y<SIZE;y+=s2){const s=proj({x:0,y:y-B,z:z-B});const e=proj({x:SIZE-1,y:y-B,z:z-B});x.beginPath();x.moveTo(s.sx,s.sy);x.lineTo(e.sx,e.sy);x.stroke();} x.globalAlpha=1; } else if(state.mode==='flow'){ for(let i=0;i<pts.length;i+=step){const p=pts[i];const w=Math.sin((p.x+p.y+p.z)*0.04+state.flow*1.5);const prj=proj({x:p.x,y:p.y+w*3,z:p.z,l:p.l,hx:p.hx,hy:p.hy,hz:p.hz});if(prj.sc>0){x.fillStyle=hsl(p,(0.4+0.6*w)*prj.sc);x.fillRect(prj.sx,prj.sy,Math.max(0.5,prj.sc),Math.max(0.5,prj.sc));cnt++;}} } else if(state.mode==='stream'){ if(Math.random()<0.002&&state.strm.length<8000){const nx=Math.floor(Math.random()*SIZE)-B;const ny=Math.floor(Math.random()*SIZE)-B;const nz=Math.floor(Math.random()*SIZE)-B;state.strm.push({x:nx,y:ny,z:nz,l:Math.abs(Math.round(nz+B)),hx:(nx+B)/SIZE,hy:(ny+B)/SIZE,hz:(nz+B)/SIZE});} state.strm.forEach(p=>{const prj=proj(p);if(prj.sc>0){x.fillStyle=hsl(p,prj.sc*0.9);x.fillRect(prj.sx,prj.sy,Math.max(1,prj.sc*1.2),Math.max(1,prj.sc*1.2));cnt++;}}); if(Math.random()<0.01)log(`Поток: ${state.strm.length} точек`,'info'); } // Outline x.strokeStyle='#00f0ff'; x.lineWidth=1; x.globalAlpha=0.2; const corners=[[-1,-1,-1],[1,-1,-1],[1,1,-1],[-1,1,-1],[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1]].map(c=>proj({x:c[0]*B,y:c[1]*B,z:c[2]*B})); x.beginPath();x.moveTo(corners[0].sx,corners[0].sy);for(let i=1;i<8;i++)x.lineTo(corners[i].sx,corners[i].sy);x.lineTo(corners[0].sx,corners[0].sy);x.stroke(); for(let i=0;i<4;i++){x.beginPath();x.moveTo(corners[i].sx,corners[i].sy);x.lineTo(corners[i+4].sx,corners[i+4].sy);x.stroke();} x.globalAlpha=1; // HUD document.getElementById('m-draw').textContent=cnt.toLocaleString(); document.getElementById('m-ax').textContent=(state.ax*180/Math.PI).toFixed(1)+'°'; document.getElementById('m-ay').textContent=(state.ay*180/Math.PI).toFixed(1)+'°'; document.getElementById('m-fov').textContent=state.fov; if(state.auto&&!state.paused){state.ay+=0.004;if(state.mode==='flow'||state.mode==='stream')state.flow+=0.02;} } // FPS const now=performance.now(); state.fc++; if(now-state.last>=1000){state.fps=state.fc;state.fc=0;state.last=now;document.getElementById('fps-val').textContent=state.fps;} requestAnimationFrame(draw); } // Controls document.querySelectorAll('.btn').forEach(b=>{b.addEventListener('click',()=>{document.querySelectorAll('.btn').forEach(btn=>btn.classList.remove('active'));b.classList.add('active');state.mode=b.dataset.m;document.getElementById('m-mode').textContent=b.textContent;if(state.mode==='stream')state.strm=[];log('Режим: '+state.mode.toUpperCase());});}); document.getElementById('slice-slider').addEventListener('input',e=>{state.layer=parseInt(e.target.value);document.getElementById('slice-val').textContent=state.layer;}); document.addEventListener('keydown',e=>{ if(e.key>='1'&&e.key<='5'){const m=['cube','slices','explode','grid','flow'];document.querySelector(`[data-m="${m[parseInt(e.key)-1]}"]`).click();} else if(e.key==='6')document.querySelector('[data-m="stream"]').click(); else if(e.key==='ArrowRight'||e.key==='ArrowDown'){state.layer=(state.layer+1)%LAYERS;document.getElementById('slice-slider').value=state.layer;document.getElementById('slice-val').textContent=state.layer;} else if(e.key==='ArrowLeft'||e.key==='ArrowUp'){state.layer=(state.layer-1+LAYERS)%LAYERS;document.getElementById('slice-slider').value=state.layer;document.getElementById('slice-val').textContent=state.layer;} else if(e.key==='r'||e.key==='R'){state.ax=0.4;state.ay=0.3;state.fov=FOV;log('Сброс вида');} else if(e.key===' '){e.preventDefault();state.paused=!state.paused;log(state.paused?'ПАУЗА':'ПРОДОЛЖЕНИЕ');} }); let drag=false,lM={x:0,y:0}; c.addEventListener('mousedown',e=>{drag=true;lM={x:e.clientX,y:e.clientY};state.auto=false;}); c.addEventListener('mousemove',e=>{if(!drag)return;state.ay+=(e.clientX-lM.x)*0.005;state.ax+=(e.clientY-lM.y)*0.005;lM={x:e.clientX,y:e.clientY};}); c.addEventListener('mouseup',()=>{drag=false;setTimeout(()=>state.auto=true,2000);}); c.addEventListener('wheel',e=>{e.preventDefault();state.fov+=e.deltaY>0?-8:8;state.fov=Math.max(150,Math.min(500,state.fov));}); log('Система готова. ∛1 000 000 = 100 слоёв.','info'); requestAnimationFrame(draw); </script> </body> </html>