You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
784 lines
24 KiB
784 lines
24 KiB
4 years ago
|
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
|
||
|
let lastClick = undefined;
|
||
|
let animating = true;
|
||
|
let flags = 0x0;
|
||
|
var uTime = 0, startTime = Date.now();
|
||
|
let lastTime = Date.now(), rotTime = 0;
|
||
|
var lastFrameTime = 0;
|
||
|
let oldDocument;
|
||
|
let fullscreen = false, btntoggled = false;
|
||
|
let movescene = true;
|
||
|
let oldparents = {};
|
||
|
var tr, div;
|
||
|
let canvas_originalsize;
|
||
|
let Sph = [];
|
||
|
let SphTr = [];
|
||
|
let SphDletaR = [];
|
||
|
let selected = false, selection = -1, dragging = false;
|
||
|
let overall_trans = matrix_identity(), overall_ground;
|
||
|
let rebuild = true, presentation = true, sRotation = matrix_identity();
|
||
|
let facing = 1, running = 0;
|
||
|
let curr_mouse_pos = [-10, -10];
|
||
|
schema.height=screen.height*.9;
|
||
|
for(let i = 0; i < ns; ++i)
|
||
|
{
|
||
|
SphTr[i]=matrix_identity();
|
||
|
SphDletaR[i] = 0;
|
||
|
}
|
||
|
function ev_supersample(e){
|
||
|
let multiplier = insamp.value;
|
||
|
let w = parseInt(canvas1.style.width)*multiplier;
|
||
|
let h = parseInt(canvas1.style.height)*multiplier;
|
||
|
canvas1.height = h;
|
||
|
canvas1.width = w;
|
||
|
gl.viewport(0, 0, w, h);
|
||
|
//gl.clearRect(0, 0, w, h);
|
||
|
}
|
||
|
function toggleFullscreen(element){
|
||
|
if(fullscreen)
|
||
|
{
|
||
|
if (document.exitFullscreen)
|
||
|
document.exitFullscreen();
|
||
|
else if (document.webkitExitFullscreen)
|
||
|
document.webkitExitFullscreen();
|
||
|
else if (document.mozCancelFullScreen)
|
||
|
document.mozCancelFullScreen();
|
||
|
else if (document.msExitFullscreen)
|
||
|
document.msExitFullscreen();
|
||
|
fullscreen = false;
|
||
|
bnfs.innerText = "Fullscreen";
|
||
|
}
|
||
|
else{
|
||
|
if(element.requestFullscreen)
|
||
|
element.requestFullscreen();
|
||
|
else if (element.webkitRequestFullscreen)
|
||
|
element.webkitRequestFullscreen();
|
||
|
else if(element.msRequestFullscreen)
|
||
|
element.msRequestFullscreen();
|
||
|
fullscreen = true;
|
||
|
bnfs.innerText = "Exit Fullscreen";
|
||
|
}
|
||
|
}
|
||
|
bnfs.onclick = function(e){
|
||
|
if(e === "no")
|
||
|
;
|
||
|
else
|
||
|
btntoggled = true;
|
||
|
if(fullscreen){
|
||
|
oldparents[controls].appendChild(controls);
|
||
|
oldparents[canvas1].appendChild(canvas1);
|
||
|
canvas1.style.width = canvas_originalsize[0];
|
||
|
canvas1.style.height = canvas_originalsize[1];
|
||
|
howitworks.hidden = false;
|
||
|
}else{
|
||
|
div = document.createElement("div");
|
||
|
tr = document.createElement("table").insertRow();
|
||
|
tr.style.backgroundColor="white";
|
||
|
let size = Math.min(screen.availHeight, screen.availWidth);
|
||
|
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
|
||
|
canvas1.style.height = canvas1.style.width = size;
|
||
|
howitworks.hidden=true;
|
||
|
oldparents[controls] = controls.parentNode;
|
||
|
oldparents[canvas1] = canvas1.parentNode;
|
||
|
|
||
|
let td1 = tr.insertCell();
|
||
|
td1.appendChild(canvas1);
|
||
|
let td2;
|
||
|
td2 = tr.insertCell();
|
||
|
td2.style.verticalAlign="top";
|
||
|
td2.appendChild(controls);
|
||
|
|
||
|
div.appendChild(tr);
|
||
|
document.body.appendChild(div);
|
||
|
}
|
||
|
toggleFullscreen(div);
|
||
|
ev_supersample();
|
||
|
}
|
||
|
mov.onclick=function(_){
|
||
|
movescene = !movescene;
|
||
|
if(!movescene)
|
||
|
{
|
||
|
mov.innerText= "Move Scene";
|
||
|
mov.style.width = "170px";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mov.innerText = "Move Lighting";
|
||
|
mov.style.width = "180px";
|
||
|
}
|
||
|
}
|
||
|
document.addEventListener("webkitfullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
|
||
|
document.addEventListener("fullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
|
||
|
clrsel.onclick=function(_){
|
||
|
setUniform("1i", "sel", -1);
|
||
|
selected = false;
|
||
|
selection = -1;
|
||
|
}
|
||
|
reset.onclick = function(_){
|
||
|
clrsel.onclick();
|
||
|
if(!animating)
|
||
|
pause_resume();
|
||
|
flags = 0;
|
||
|
moving = false;
|
||
|
mousedx = mousedy = mousedz = 0;
|
||
|
positionsupdated = true;
|
||
|
for(let i = 0; i < ns; ++i)
|
||
|
{
|
||
|
SphTr[i]=matrix_identity();
|
||
|
SphDletaR[i] = 0;
|
||
|
}
|
||
|
rtx.src='./RTXon.svg';
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
}
|
||
|
bns.onclick=function(e){
|
||
|
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
|
||
|
{
|
||
|
cns = ins.value;
|
||
|
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
|
||
|
if(typeof canvas1.setShaders === "function")
|
||
|
canvas1.setShaders(vs, editor.getSession().getValue());
|
||
|
}
|
||
|
}
|
||
|
bnsamp.onclick=ev_supersample;
|
||
|
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
|
||
|
ace.require("ace/ext/language_tools");
|
||
|
var editor = ace.edit("ace", {
|
||
|
mode:"ace/mode/glsl",
|
||
|
theme:"ace/theme/crimson_editor"
|
||
|
});
|
||
|
editor.setOptions({
|
||
|
enableBasicAutocompletion: true,
|
||
|
enableSnippets: true,
|
||
|
enableLiveAutocompletion: true,
|
||
|
fontSize: 14,
|
||
|
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
|
||
|
fixedWidthGutter: true,
|
||
|
showGutter: true,
|
||
|
showPrintMargin: false,
|
||
|
});
|
||
|
editor.setAutoScrollEditorIntoView(true);
|
||
|
if(fs != undefined)
|
||
|
editor.getSession().setValue(fs);
|
||
|
editor.session.on('change', function(delta) {
|
||
|
if(typeof canvas1.setShaders === "function")
|
||
|
{
|
||
|
canvas1.setShaders(vs, editor.getSession().getValue());
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
}
|
||
|
});
|
||
|
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
|
||
|
delete editor.KeyBinding;
|
||
|
|
||
|
|
||
|
let pause_resume = function(){
|
||
|
if(animating)
|
||
|
lastTime = Date.now();
|
||
|
else
|
||
|
startTime += Date.now() - lastTime;
|
||
|
animating = !animating;
|
||
|
};
|
||
|
canvas1.addEventListener('click',function(ev){
|
||
|
if(!(shift && alt) && lastClick&& Date.now()-lastClick<200)
|
||
|
pause_resume();
|
||
|
lastClick = Date.now();
|
||
|
});
|
||
|
pause.onclick = pause_resume;
|
||
|
canvas1.addEventListener('mouseover', function(e){
|
||
|
over = true;
|
||
|
if(e.offsetX >0 && e.offsetY > 0)
|
||
|
curr_mouse_pos = [2*e.offsetX/ parseInt(canvas1.style.width)-1,
|
||
|
1-2*e.offsetY/ parseInt(canvas1.style.height), -1];
|
||
|
else over = false;
|
||
|
});
|
||
|
canvas1.addEventListener('mousedown', function(e){
|
||
|
moving = true;
|
||
|
rotTime = uTime;
|
||
|
presentation = false;
|
||
|
mouselastX = mouselastY = undefined;
|
||
|
let i = hitTest([2*e.offsetX/ parseInt(canvas1.style.width)-1,
|
||
|
1-2*e.offsetY/ parseInt(canvas1.style.height), -1]);
|
||
|
if(i >= 0)
|
||
|
{
|
||
|
dragging = true;
|
||
|
selected = true;
|
||
|
setUniform("1i", "sel", i);
|
||
|
selection = i;
|
||
|
}
|
||
|
else if(selected = true){
|
||
|
dragging = false;
|
||
|
selected = false;
|
||
|
setUniform("1i", "sel", i);
|
||
|
selection = i;
|
||
|
}
|
||
|
});
|
||
|
canvas1.addEventListener('mousemove', function(e){
|
||
|
curr_mouse_pos = [2*e.offsetX/ parseInt(canvas1.style.width)-1,
|
||
|
1-2*e.offsetY/ parseInt(canvas1.style.height), -1];
|
||
|
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
|
||
|
let dx = (mouselastX - e.offsetX),
|
||
|
dy = (mouselastY - e.offsetY);
|
||
|
if(movescene){
|
||
|
sRotation = matrix_multiply(sRotation, matrix_rotateY(-dy/60));
|
||
|
sRotation = matrix_multiply(sRotation, matrix_rotateX(-dx/60));
|
||
|
|
||
|
}
|
||
|
else if(!selected)
|
||
|
{
|
||
|
mousedx -= dx/60;
|
||
|
mousedy -= dy/60;
|
||
|
positionsupdated = true;
|
||
|
}else if(dragging){
|
||
|
let m = matrix_rotateY(-mousedx);
|
||
|
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||
|
let dv = matrix_multiply(m, [2*-dx/ parseInt(canvas1.style.width),
|
||
|
2*dy/ parseInt(canvas1.style.height), 0, 1]).slice(0,3);
|
||
|
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
mouselastX = e.offsetX;
|
||
|
mouselastY = e.offsetY;
|
||
|
});
|
||
|
canvas1.addEventListener('mouseup', function(e){
|
||
|
moving = false;
|
||
|
dragging = false;
|
||
|
});
|
||
|
canvas1.addEventListener('mouseout', function(e){
|
||
|
const mask = 0x8;
|
||
|
flags &= !mask;
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
over = false;
|
||
|
moving = false;
|
||
|
});
|
||
|
canvas1.addEventListener('wheel', function(e){
|
||
|
if(!selected){
|
||
|
mousedz += e.wheelDelta/600;
|
||
|
positionsupdated = true;
|
||
|
}
|
||
|
else{
|
||
|
SphDletaR[selection] += e.wheelDelta / 800;
|
||
|
}
|
||
|
});
|
||
|
canvas1.scroll(function(e) {e.stopPropagation();});
|
||
|
rtx.style.cursor="pointer";
|
||
|
let rtswitch = function(){
|
||
|
alert('Ray Tracing is off for now. I\'ll try to add it back as some sort of background or texture later.')
|
||
|
rtx.src='./RTXon.svg';
|
||
|
}
|
||
|
rtx.addEventListener('click', rtswitch);
|
||
|
var requestAnimationFrame = window.requestAnimationFrame ||
|
||
|
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
|
||
|
let fpscounter = function(time){
|
||
|
if (start === undefined)
|
||
|
start = time;
|
||
|
else
|
||
|
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
|
||
|
start = time;
|
||
|
if(fpson)
|
||
|
;//requestAnimationFrame(fpscounter);
|
||
|
else{
|
||
|
start = undefined;
|
||
|
fps.innerHTML = '';
|
||
|
}
|
||
|
};
|
||
|
document.addEventListener('keydown',(e)=>{
|
||
|
if(e.code.startsWith('Shift'))
|
||
|
shift = true;
|
||
|
if(e.code.startsWith('Control'))
|
||
|
ctrl = true;
|
||
|
if(e.code.startsWith('Alt'))
|
||
|
alt = true;
|
||
|
else if(ctrl && alt && e.code == 'KeyT'){
|
||
|
const mask = 0x1;
|
||
|
flags = flags&!mask | (!(flags&mask)?mask:0);
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
}
|
||
|
else if (ctrl &&e.code == 'KeyS'){
|
||
|
let a = document.createElement('a');
|
||
|
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
|
||
|
a.download = 'shader.frag';
|
||
|
a.click();
|
||
|
}
|
||
|
else if(ctrl && alt&&e.code == 'KeyR')
|
||
|
rtswitch();
|
||
|
else if(ctrl && alt&&e.code == 'KeyN')
|
||
|
{
|
||
|
reset.onclick();
|
||
|
}
|
||
|
else if(ctrl && alt&&e.code == 'KeyP')
|
||
|
pause_resume();
|
||
|
else if(ctrl && alt&&e.code == 'KeyF')
|
||
|
if(!fpson)
|
||
|
{
|
||
|
fpson = true;
|
||
|
requestAnimationFrame(fpscounter);
|
||
|
}
|
||
|
else
|
||
|
fpson = false;
|
||
|
|
||
|
if(e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code =='ArrowLeft'
|
||
|
||e.code == 'ArrowRight' || e.code =='KeyW'||e.code =='KeyS')
|
||
|
{
|
||
|
switch(e.code){
|
||
|
case 'ArrowUp':
|
||
|
facing = -2;
|
||
|
break;
|
||
|
case 'ArrowDown':
|
||
|
facing = 2;
|
||
|
break;
|
||
|
case 'ArrowLeft':
|
||
|
facing = -1;
|
||
|
break;
|
||
|
case 'ArrowRight':
|
||
|
facing = 1;
|
||
|
break;
|
||
|
case 'KeyW':
|
||
|
break;
|
||
|
case 'KeyS':
|
||
|
break;
|
||
|
}
|
||
|
running = 50;
|
||
|
rebuild = true;
|
||
|
}
|
||
|
if(fullscreen && selected ){
|
||
|
if(e.code =='KeyF'||e.code =='KeyB'){
|
||
|
let m = matrix_rotateY(-mousedx);
|
||
|
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||
|
m = const_multiply((fl + 1 + mousedz)/(fl+1), m);
|
||
|
|
||
|
switch(e.code){
|
||
|
case 'KeyB':
|
||
|
var dv = matrix_multiply(m, [0,0, -0.1, 1]).slice(0,3);
|
||
|
m = matrix_translate(dv[0], dv[1], dv[2]);
|
||
|
break;
|
||
|
case 'KeyF':
|
||
|
var dv = matrix_multiply(m, [0,0, 0.1, 1]).slice(0,3);
|
||
|
m = matrix_translate(dv[0], dv[1], dv[2]);
|
||
|
break;
|
||
|
}
|
||
|
SphTr[selection] = matrix_multiply(SphTr[selection], m);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
});
|
||
|
|
||
|
document.addEventListener('keyup',(e)=>{
|
||
|
if(e.code.startsWith('Control'))
|
||
|
ctrl = false;
|
||
|
if(e.code.startsWith('Alt'))
|
||
|
alt = false;
|
||
|
if(e.code.startsWith('Shift'))
|
||
|
shift = false;
|
||
|
});
|
||
|
let squareMesh = new Float32Array([ -1,-1,1,0,0,0,1,-1, 1,1,0,0,0,1,-1, -1,-1,0,0,0,1, -1,1,-1,0 ,0,0,1]);
|
||
|
let sphereMesh = createMesh(32, 32, uvToSphere);
|
||
|
let tubeMesh = createMesh(32, 2, uvToTube,0,1);
|
||
|
let diskMesh = createMesh(32, 2, uvToDisk,0,1);
|
||
|
let tubeMesh2 = createMesh(32, 2, uvToTube,0,2);
|
||
|
let diskNMesh2 = createMesh(32, 2, uvToDisk, -1,2);
|
||
|
let diskPMesh2 = createMesh(32, 2, uvToDisk, 1,2);
|
||
|
let tubeMesh3 = createMesh(32, 2, uvToTube,0,3);
|
||
|
let diskNMesh3 = createMesh(32, 2, uvToDisk, -1,3);
|
||
|
let diskPMesh3 = createMesh(32, 2, uvToDisk, 1,3);
|
||
|
let diskNMesh = createMesh(32, 2, uvToDisk, -1,1);
|
||
|
let diskPMesh = createMesh(32, 2, uvToDisk, 1,1);
|
||
|
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);
|
||
|
let cylinderMesh2 = glueMeshes(glueMeshes(tubeMesh2, diskPMesh2), diskNMesh2);
|
||
|
let cylinderMesh3 = glueMeshes(glueMeshes(tubeMesh3, diskPMesh3), diskNMesh3);
|
||
|
let torusMash = createMesh(32, 32, uvToTorus, 1, 5);
|
||
|
let head = createCube(1.5,1,1, 4);
|
||
|
|
||
|
let objects = [];
|
||
|
let addObject = (obj, mat) => {
|
||
|
objects.push([obj, mat]);
|
||
|
};
|
||
|
let clearObject = () => {delete objects; objects = [];};
|
||
|
|
||
|
let delta_height = 0, delta_l = [0,0];
|
||
|
class State{
|
||
|
constructor() {
|
||
|
this.leg = true;
|
||
|
this.progress = 0;
|
||
|
this.rh = this.lh = .5*pi;
|
||
|
this.lf = this.rf = 0;
|
||
|
}
|
||
|
initialize(){
|
||
|
this.leg = true;
|
||
|
this.progress = 0;
|
||
|
}
|
||
|
next(){
|
||
|
//return this.presentation();
|
||
|
if(running <= 0)
|
||
|
return {rh:.5*pi, lh:.5*pi, rf:0, lf:0, dh:0,dl:0}
|
||
|
running --;
|
||
|
const steps = 100;
|
||
|
let dl = 0;
|
||
|
if(this.progress >= steps/2)
|
||
|
{
|
||
|
this.progress = 0;
|
||
|
this.leg = !this.leg;
|
||
|
}
|
||
|
let delta = [-pi/5, 0.5*pi, 0.44*pi, 0.55*pi];
|
||
|
for (let i = 0; i < 4; ++i) delta[i] /= steps;
|
||
|
if(this.leg)
|
||
|
{
|
||
|
if(this.progress < steps/4)
|
||
|
{
|
||
|
this.lh += delta[0];
|
||
|
this.rh += delta[3];
|
||
|
this.lf += delta[1];
|
||
|
this.rf += delta[2];
|
||
|
}
|
||
|
else{
|
||
|
this.lh -= delta[0];
|
||
|
this.rh -= delta[3];
|
||
|
this.lf -= delta[1];
|
||
|
this.rf-= delta[2];
|
||
|
}
|
||
|
}
|
||
|
else{
|
||
|
if(this.progress < steps/4)
|
||
|
{
|
||
|
this.lh += delta[3];
|
||
|
this.rh += delta[0];
|
||
|
this.lf += delta[2];
|
||
|
this.rf += delta[1];
|
||
|
}
|
||
|
else{
|
||
|
this.lh -= delta[3];
|
||
|
this.rh -= delta[0];
|
||
|
this.lf -= delta[2];
|
||
|
this.rf-= delta[1];
|
||
|
}
|
||
|
}
|
||
|
let delta_h = Math.max((1-cos(abs(this.lh - pi/2)))*.5+(1-cos(abs(this.lf)))*.6,(1-cos(abs(this.rh - pi/2)))*.5+(1-cos(abs(this.rf)))*.6);
|
||
|
this.progress++;
|
||
|
return {lh:this.lh, lf:this.lf, rh:this.rh,rf:this.rf, dh:delta_h, dl:1.8522/steps};
|
||
|
}
|
||
|
// presentation(){
|
||
|
// return {lh:.4*pi, lf:pi/6,rh:.7*pi, rf:pi/8, dh:0};
|
||
|
// }
|
||
|
};
|
||
|
|
||
|
let star1 = [], star = [];
|
||
|
let sakura = [], stars = [], nstars = 25;
|
||
|
let star2=[], newstar, star4;
|
||
|
const curvex = matrix_multiply(hermiteMat, [-.3,.8,.6,.5]);
|
||
|
const curvey = matrix_multiply(hermiteMat, [-.2,.5,.7,.2]);
|
||
|
const curvez = matrix_multiply(hermiteMat, [-.5,.2,.3,.8]);
|
||
|
let adt = [];
|
||
|
|
||
|
let build_objects = (state)=>{
|
||
|
if(running === 0)
|
||
|
rebuild = false;
|
||
|
let {lh, lf, rh, rf, dh, dl} = state.next();
|
||
|
delta_l[abs(facing)-1] += Math.sign(facing) * dl;
|
||
|
delta_height = dh;
|
||
|
clearObject();
|
||
|
M.save();
|
||
|
M.save();
|
||
|
M.rotateX(pi/2);
|
||
|
M.scale(0.5, 0.5, 1);
|
||
|
addObject(cylinderMesh, M.value());
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0,1,0);
|
||
|
addObject(head, M.value());
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0.5, 0.2, 0.3);
|
||
|
M.rotateX(pi/4);
|
||
|
M.translate(0,0,.5);
|
||
|
M.save();
|
||
|
M.translate(0,0,.4);
|
||
|
M.rotateX(-0.53*pi);
|
||
|
M.scale(0.2, 0.2, 0.4);
|
||
|
M.translate(0,0,1);
|
||
|
addObject(cylinderMesh2, M.value());
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(cylinderMesh2, M.value());
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-0.5, 0.2, 0.3);
|
||
|
M.rotateX(pi/4);
|
||
|
M.translate(0,0,.5);
|
||
|
M.save();
|
||
|
M.translate(0,0,.4);
|
||
|
M.rotateX(-0.55*pi);
|
||
|
M.scale(0.2, 0.2, 0.4);
|
||
|
M.translate(0,0,1);
|
||
|
addObject(cylinderMesh2, M.value());
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(cylinderMesh2, M.value());
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0.3, -1, 0.);
|
||
|
M.rotateX(lh);
|
||
|
M.translate(0,0,.5);
|
||
|
M.save();
|
||
|
M.translate(0,0,.45);
|
||
|
M.rotateX(lf);
|
||
|
M.scale(0.2, 0.2, 0.6);
|
||
|
M.translate(0,0,1);
|
||
|
addObject(cylinderMesh3, M.value());
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(cylinderMesh3, M.value());
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-0.3, -1, 0.);
|
||
|
M.rotateX(rh);
|
||
|
M.translate(0,0,.5);
|
||
|
M.save();
|
||
|
M.translate(0,0,.45);
|
||
|
M.rotateX(rf);
|
||
|
M.scale(0.2, 0.2, 0.6);
|
||
|
M.translate(0,0,1);
|
||
|
addObject(cylinderMesh3, M.value());
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(cylinderMesh3, M.value());
|
||
|
M.restore();
|
||
|
M.restore();
|
||
|
if(running < 0)
|
||
|
rebuild = false;
|
||
|
};
|
||
|
|
||
|
let build_splines = ()=>{
|
||
|
star = [], star1 = [], star2 = [], star4 = [], newstar = [], adt = [], sakura = [];
|
||
|
var n = 11, innerN = Math.ceil((paths[0].length*n)/paths[1].length);
|
||
|
for(let j = 0; j < paths[0].length; ++j)
|
||
|
{
|
||
|
let xf = paths[0][j][0], yf = paths[0][j][1];
|
||
|
for(var k = 0; k <= n; ++k){
|
||
|
let t = k/n;
|
||
|
star1.push([7,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
0,0,0,1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for(let j = 13; j >=0; j--)
|
||
|
{
|
||
|
let xf = paths[1][j][0], yf = paths[1][j][1];
|
||
|
for(var k = innerN-1; k >=0 ; --k){
|
||
|
let t = k/(innerN-1);
|
||
|
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
0,0,0,1]);
|
||
|
}
|
||
|
}
|
||
|
for(let j = paths[1].length-1; j >12; --j)
|
||
|
{
|
||
|
let xf = paths[1][j][0], yf = paths[1][j][1];
|
||
|
for(var k = innerN; k >=0 ; --k){
|
||
|
let t = k/innerN;
|
||
|
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
0,0,0,1]);
|
||
|
}
|
||
|
}
|
||
|
for(let i = 0; i < star1.length; ++i){
|
||
|
concat(star, star1[i]);
|
||
|
concat(star, star2[i]);
|
||
|
}
|
||
|
n = 25;
|
||
|
for(let l = 2; l < 6; ++l)
|
||
|
{
|
||
|
adt[l - 2] = [];
|
||
|
for(let j = 0; j < paths[l].length; ++j)
|
||
|
{
|
||
|
let xf = paths[l][j][0], yf = paths[l][j][1];
|
||
|
for(var k = 0; k <= n; ++k){
|
||
|
let t = k/n;
|
||
|
adt[l-2].push(10+l,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
-dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
0,0,0,1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
n = 20;
|
||
|
for(let l = 6; l < 13; ++l)
|
||
|
{
|
||
|
sakura[l-6] = [];
|
||
|
for(let j = 0; j < paths[l].length; ++j)
|
||
|
{
|
||
|
let xf = paths[l][j][0], yf = paths[l][j][1];
|
||
|
for(var k = 0; k <= n; ++k){
|
||
|
let t = k/n;
|
||
|
sakura[l-6].push(10,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
0,0,0,1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
star4 = star.slice();
|
||
|
newstar = star.slice()
|
||
|
for(let i = 0; i < star.length; i+=7)
|
||
|
{
|
||
|
star4[i] = 9;
|
||
|
newstar[i] = 8;
|
||
|
}
|
||
|
for(let i = 0; i < nstars; ++i){
|
||
|
stars.push(star.slice());
|
||
|
startz.push(.6*Math.random());
|
||
|
random_rot.push(0);
|
||
|
random_rot_pos.push(0);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
let state = new State();
|
||
|
var M = new Matrix();
|
||
|
var buildsplines = true;
|
||
|
let magician = false, magician_neck = false,
|
||
|
magician_houki = false, body = false,
|
||
|
leg = false, hand = false ;
|
||
|
let sa2 = [
|
||
|
1.6,0.4, .9, 1., .3,.2, -.4,.8,
|
||
|
-.8, -.1, -1.4, .5, -1.6, -.5
|
||
|
], fsa2 = [[matrix_multiply(bezierMat,[sa2[0], sa2[2], sa2[4], sa2[6]]),
|
||
|
matrix_multiply(bezierMat,[sa2[1], sa2[3], sa2[5], sa2[7]])],
|
||
|
[matrix_multiply(bezierMat,[sa2[6], sa2[8], sa2[10], sa2[12]]),
|
||
|
matrix_multiply(bezierMat,[sa2[7], sa2[9], sa2[11], sa2[13]])]],
|
||
|
random_rot = [0,0,0,0,0,0,0], random_rot_pos = [0,0,0,0,0,0,0], startz = [];
|
||
|
|
||
|
let division = -1;
|
||
|
let changeID = (id, obj) => {for(let i = 0; i < obj.length; i+=7) obj[i] = id;}
|
||
|
function animate(gl) {
|
||
|
buildsplines &&= build_splines();
|
||
|
magician = magician?magician:createMeshFromSpline( 13, 32, 4, 4, 0, (i,_,oid) => {
|
||
|
if (oid == 4 && i == 10) return 3;
|
||
|
else if (oid == 3 && i ==16) return 2;
|
||
|
else if(oid == 2 && i == 23) return 1;
|
||
|
});
|
||
|
magician_neck = magician_neck?magician_neck:createMeshFromSpline( 14, 32, 4, 5, -.2);
|
||
|
magician_houki = magician_houki?magician_houki:createMeshFromSpline( 15, 32, 4, 6);
|
||
|
body = body?body:createMeshFromSpline( 16, 32, 4, 7, 0, (i, tmp)=>{if(division < 0 && i == 25) division = tmp.length;});
|
||
|
leg = leg?leg:createMeshFromSpline(17, 32, 4, 8);
|
||
|
hand = hand?hand:createMeshFromSpline(18, 32, 4, 9,.015);
|
||
|
|
||
|
if(animating)
|
||
|
{
|
||
|
uTime = (Date.now() - startTime) / 1000;
|
||
|
setUniform('1f', 'uTime', uTime);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uTime = (lastTime - startTime) / 1000;
|
||
|
setUniform('1f', 'uTime', uTime);
|
||
|
}
|
||
|
let curve = [];
|
||
|
let n = 8;
|
||
|
// for(let j = 0; j < paths[13].length; ++j)
|
||
|
// {
|
||
|
// let xf = paths[13][j][0], yf = paths[13][j][1];
|
||
|
// for(var k = 0; k <= n; ++k){
|
||
|
// let t = k/n;
|
||
|
// concat(curve, [7,dot(xf, [t*t*t, t*t, t, 1]),
|
||
|
// -dot(yf, [t*t*t, t*t, t, 1]),
|
||
|
// 0,0,0,1]);
|
||
|
// }
|
||
|
// }
|
||
|
// M.save()
|
||
|
// M.scale(0.3);
|
||
|
// setM(matrix_multiply(sRotation, M.value()));
|
||
|
// drawMesh(leg);
|
||
|
// M.restore();
|
||
|
// return;
|
||
|
M.save()
|
||
|
if(presentation){
|
||
|
M.rotateX(uTime/12);
|
||
|
M.rotateY(uTime/3);
|
||
|
M.rotateZ(uTime/6);
|
||
|
} else {
|
||
|
M.rotateX(rotTime/12);
|
||
|
M.rotateY(rotTime/3);
|
||
|
M.rotateZ(rotTime/6);
|
||
|
}
|
||
|
M.scale(0.6);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(body.slice(0, division));
|
||
|
drawMesh(body.slice(division - 7), gl.LINE_LOOP);
|
||
|
M.save();
|
||
|
M.translate(0,0,-1.05);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0,0,-.53);
|
||
|
M.scale(.1);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician_neck);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-1,0,0);
|
||
|
M.scale(2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician_houki);
|
||
|
M.restore();
|
||
|
M.save()
|
||
|
M.translate(-.06,0,.85);
|
||
|
M.rotateY(0.02);
|
||
|
M.scale(1.2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(leg);
|
||
|
M.restore();
|
||
|
M.save()
|
||
|
M.translate(.06,0,.85);
|
||
|
M.rotateY(-0.02);
|
||
|
M.scale(1.2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(leg);
|
||
|
M.restore();
|
||
|
M.save()
|
||
|
M.translate(-.35,0,-.1);
|
||
|
M.rotateY(-pi/6);
|
||
|
M.scale(.82);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(hand);
|
||
|
M.restore();
|
||
|
M.save()
|
||
|
M.translate(.35,0,-.1);
|
||
|
M.rotateY(pi/6);
|
||
|
M.scale(.82);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(hand);
|
||
|
M.restore();
|
||
|
M.restore();
|
||
|
for(let i = 0; i < nstars; ++ i)
|
||
|
{M.save()
|
||
|
let f_idx = (uTime/(abs(sin(i*1234))*8 + 10))%2,
|
||
|
t = f_idx - Math.floor(f_idx);
|
||
|
f_idx -=t;
|
||
|
let curr_mat = [t*t*t, t*t, t, 1];
|
||
|
M.translate(1.2*sin(sin(uTime/(i+2)+i + 8)*.9 + dot(fsa2[f_idx][0], curr_mat)*5 + startz[Math.floor(2*startz[i]*nstars)%nstars]), 1.2*cos(i + sin(uTime/(i/2+18)+12)*.1 + startz[nstars-i-1] + dot(fsa2[f_idx][1], curr_mat)*startz[(nstars + i)%nstars]*.4 + i * sin(random_rot_pos[i]/30)/pi), .65*startz[i] + .3*sin(random_rot_pos[i]/20));
|
||
|
let epsilon = 1/(i*2+20);
|
||
|
let random = () => {
|
||
|
var u = 0, v = 0;
|
||
|
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
|
||
|
while(v === 0) v = Math.random();
|
||
|
return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )/pi;
|
||
|
}
|
||
|
if((window.performance.now() + i*(2+abs(random()))) %69 <2){
|
||
|
changeID(Math.ceil(Math.random()*20)-5,stars[i])
|
||
|
}
|
||
|
random_rot[i] += random()*epsilon;
|
||
|
random_rot_pos[i] += .5 + abs(random())/(pi+i);
|
||
|
//setM(M.value);
|
||
|
M.rotateZ(sin(random_rot_pos[i]/10)*pi);
|
||
|
M.rotateX(.1*sin(random_rot_pos[i]/(i+50))*pi);
|
||
|
M.rotateY(.1*sin(random_rot_pos[i]/(i*2+50))*pi);
|
||
|
|
||
|
M.scale(0.2 + startz[i]*.2);
|
||
|
setM(M.value());
|
||
|
drawMesh(new Float32Array(stars[i]));
|
||
|
M.restore();}
|
||
|
|
||
|
if(over);
|
||
|
}
|
||
|
|
||
|
requestAnimationFrame(fpscounter);
|
||
|
//pjsk.play();
|