three实现三维能量场波动流动连线动画效果代码

代码语言:html

所属分类:三维

代码描述:three实现三维能量场波动流动连线动画效果代码

代码标签: three 三维 能量 波动 连线 动画 流动

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  
  
  
  
<style>
body, html{
  margin: 0;
  height: 100vh;
  background: linear-gradient(-45deg, #333, #000);
  overflow: hidden;
}
canvas{
  display: none;
  border: 3px solid #fff3;
  position: absolute;
  background: #04f1;
  left: 50%;
  top: 50%;
  border-radius: 10px;
  transform: translate(-50%, -50%);
}
canvas:focus{
  outline: none;
}
</style>

  
</head>

<body translate="no">
  <div id="container"></div>
<canvas id=c></canvas>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.160.js"></script>
<script type="module">

  var camera
  let scene, renderer
  let isUserInteracting = false,
      lon = 0, lat = 0,
      phi = 0, theta = 0,
      onPointerDownPointerX = 0,
      onPointerDownPointerY = 0,
      onPointerDownLon = 0,
      onPointerDownLat = 0

  const distance = 1e4-9e3

  var func = navigator.userAgent.toLowerCase().indexOf('firefox') != -1 ? "onwheel" : "onmousewheel"
  window[func]= e => {
    let delta = camera.fov
    delta += e.deltaY/25
    camera.fov = Math.min(140, Math.max(10, delta))
    camera.updateProjectionMatrix()
    
  }

  var material, loadScene, texture, sceneLoaded = false, geometry

  function init(url){
    const container = document.getElementById( 'container' )
    camera = new THREE.PerspectiveCamera( 100, 16/9, .05, 1e6)
    
    loadScene = () =>{
      scene = new THREE.Scene()
      geometry = new THREE.SphereGeometry( 1e4, 64, 240 )
      geometry.scale( - 1, 1, 1 )
      
      texture = new THREE.CanvasTexture(c)
      
      /*
      if(url.toLowerCase().indexOf('.mp4') != -1 ||
         url.toLowerCase().indexOf('.webm') != -1){
        const vid = document.createElement('video')
        vid.muted = true
        vid.loop = true
        vid.crossOrigin = true
        vid.src = url
        vid.play()
        texture = new THREE.VideoTexture( vid )
      }else{
        texture = new THREE.TextureLoader().load(url)
        texture.wrapS = THREE.RepeatWrapping
        texture.wrapT = THREE.RepeatWrapping
        texture.repeat.set( 1, 1 )
      }
      */

      texture.colorSpace = THREE.SRGBColorSpace
      texture.anisotropy = renderer.capabilities.getMaxAnisotropy()
        texture.wrapS = THREE.RepeatWrapping
        texture.wrapT = THREE.RepeatWrapping
        texture.repeat.set( 1, 1 )
      material = new THREE.MeshBasicMaterial( { map: texture } )
      material.map.minFilter = THREE.LinearFilter
      const mesh = new THREE.Mesh( geometry, material )
      scene.add( mesh )
      sceneLoaded = true
    }
    
    renderer = new THREE.WebGLRenderer()
    renderer.setSize( 1920, 1080 )
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setAnimationLoop( animate )
    container.appendChild( renderer.domElement )
    document.addEventListener( 'pointerdown', onPointerDown )
    document.addEventListener( 'pointermove', onPointerMove )
    document.addEventListener( 'pointerup', onPointerUp )
    document.addEventListener( 'touchstart', onPointerDown )
    document.addEventListener( 'touchmove', onPointerMove )
    document.addEventListener( 'touchend', onPointerUp )
    loadScene()
  }

  function onPointerDown( event ) {
    isUserInteracting = true
    onPointerDownPointerX = event.clientX
    onPointerDownPointerY = event.clientY
    onPointerDownLon = lon
    onPointerDownLat = lat
  }

  function onPointerMove( event ) {
    if ( isUserInteracting === true ) {
      var mag = .01 + camera.fov/450
      lon = ( onPointerDownPointerX - event.clientX ) * mag + onPointerDownLon
      lat = ( onPointerDownPointerY - event.clientY ) * mag + onPointerDownLat
    }
  }

  function onPointerUp() {
    isUserInteracting = false
  }

  function animate() {
    if(typeof showRender != 'undefined' && showRender){
      if(!sceneLoaded) loadScene()
      lat = Math.max( - 89.9, Math.min( 89.9, lat ) )
      phi = ( 90 - lat )/180*Math.PI
      theta = lon/180*Math.PI
      camera.position.x = distance * Math.sin( phi ) * Math.cos( theta )
      camera.position.y = distance * Math.cos( phi )
      camera.position.z = distance * Math.sin( phi ) * Math.sin( theta )
      camera.lookAt( 0, 0, 0 )
      renderer.render( scene, camera )
      material.map.needsUpdate = true
    }else{
      sceneLoaded = false
    }
  }

  var url
  var l = location.href.split('url=')
  if(l.length>1){
    url = l[1].split('&')[0]
    init(url)
  }else{
    init('')
  }
</script>
  
      <script id="rendered-js" >
c = document.querySelector('#c');
c.tabIndex = 0;
x_ = c.getContext('2d');
c.width = 1920;
c.height = 1080;

camMode = 'HDRI';
HDRIwidth = c.width;

outputAspectRatio = 16 / 9;
output = document.createElement('canvas');
octx = output.getContext('2d');
output.width = c.width;
output.height = output.width / outputAspectRatio;
showOutput = false; // HDRI view, for recording 
showRender = false; // actual pipe to environment, for render eval etc
showPreview = false; // thumbnail in upper right 
// (only visible in default or HDRI output, not render)

if (showRender) {
  outputAspectRatio = 2;
  showOutput = true;
  showPreview = false;
  c.style.display = 'none';
} else {
  //showPreview = true
  //showOutput = false
  setTimeout(() => {
    c.style.display = 'block';
    c.style.borderRadius = showOutput ? '0' : '10px';
    c.style.border = showOutput ? 'none' : '3px solid #fff3';
    c.style.margin = showOutput ? 0 : 10;
  }, 0);
}

// tempBuffer, needed for optional preview [P]
tempBuffer = document.createElement('canvas');
tempBuffer.width = c.width;
tempBuffer.height = c.height;
tbctx = tempBuffer.getContext('2d');

C = Math.cos;
S = Math.sin;
t = 0;
T = Math.tan;

rsz = window.onresize = () => {
  let b = document.body;
  let margin = showOutput ? 0 : 10;
  let n;
  let d = showOutput ? 1 / outputAspectRatio : .5625;
  c.style.borderRadius = showOutput ? '0' : '10px';
  c.style.border = showOutput ? 'none' : '3px solid #fff3';
  //c.width = 1920 
  c.height = c.width * d;
  output.width = c.width;
  output.height = output.width * d;
  if (b.clientHeight / b.clientWidth > d) {
    c.style.width = `${(n = b.clientWidth) - margin * 2}px`;
    c.style.height = `${n * d - margin * 2}px`;
  } else {
    c.style.height = `${(n = b.clientHeight) - margin * 2}px`;
    c.style.width = `${n / d - margin * 2}px`;
  }
};
rsz();

keyTimer = 0;
keyTimerInterval = .25;
keys = Array(256).fill(false);
window.onkeyup = e => {
  keyTimer = 0;
  keys[e.keyCode] = false;
};

window.onkeydown = e => {
  keys[e.keyCode] = true;
  if (keyTimer <= t) {
    keyTimer = t + keyTimerInterval;
    if (e.keyCode == 72) {
      showOutput = !showOutput;
      if (showRender) {
        if (typeof can != 'undefined') {
          outputAspectRatio = 2;
          showOutput = true;
          showPreview = false;
          can.style.display = 'block';
          c.style.display = 'none';
          rsz2();
        }
      } else {
        showPreview = true;
        if (typeof can != 'undefined') can.style.display = 'none';
        c.style.display = 'block';
        rsz();
      }
    }
    if (e.keyCode == 80) {
      showPreview = !showPreview;
    }
    if (e.keyCode == 82) {
      showRender = !showRender;
      if (showRender) {
        outputAspectRatio = 2;
        showPreview = false;
        showOutput = true;
        can.style.display = 'block';
        c.style.display = 'none';
      } else {
        showPreview = true;
        can.style.display = 'none';
        c.style.display = 'block';
      }
    }
    if (e.keyCode == 70) {
      if (showRender || outputAspectRatio == 16 / 9) {
        outputAspectRatio = 2;
      } else {
        outputAspectRatio = 16 / 9;
      }
      rsz();
    }
  }
};

window.addEventListener('resize', rsz2 = () => {
  can = document.querySelectorAll('canvas')[0];
  if (typeof can != 'undefined') {

    can.tabindex = 0;
    can.focus();

    let b = document.body;
    let margin = 10;
    let n;
    let d = .5625;
    can.style.borderRadius = '10px';
    can.style.border = '3px solid #fff3';
    if (b.clientHeight / b.clientWidth > d) {
      can.style.width = `${(n = b.clientWidth) - margin * 2}px`;
      can.style.height = `${n * d - margin * 2}px`;
    } else {
      can.style.height = `${(n = b.clientHeight) - margin * 2}px`;
      can.style.width = `${n / d - margin * 2}px`;
    }
  }
  if (showRender) {
    showRender = false;
    setTimeout(() => {
      showRender = true;
    }, 0);
  }
});
for (let i = 10; i--;) setTimeout(() => {rsz2(), rsz();}, i * 60);

async function Draw() {
  if (!t) {
    X = Y = Z = 0;
    oX = oY = oZ = 0;
    Rl = Pt = Yw = 0;
    camX = camY = camZ = camD = 0;
    camposX = camposY = camposZ = 0;
    camRl = camPt = camYw = 0;
    Rn = Math.random;

    cls = () => {
      Z = camZ = 1E6;
      x_['globalAlpha'] = 1;
      x_.fillStyle = showOutput && showPreview ? '#0008' : '#000a';
      x_.fillRect(0, 0, 1e5, 1e5, 0, 0, 1e5, 1e5);
      x_.lineJoin = 'roud';
      x_.lineCap = 'roud';
      octx['globalAlpha'] = 1;
      octx.fillStyle = '#000a';
      octx.fillRect(0, 0, 1e5, 1e5, 0, 0, 1e5, 1e5);
      octx.lineJoin = 'roud';
      octx.lineCap = 'roud';
      override = false;
    };

    hoff = .5; // horizontal offset of HDRI output, note it wraps
    invertY = true;
    x = (func, ...vals) => {
      let p = 0,q = 0,d,ox,oy,oz,ox1,oy1,oz1,X1,Y1,Z1,X2,Y2,Z2,X3,Y3,Z3,X4,Y4,Z4;
      let ox2, oy2, oz2, s, s2, split, onscreen1, onscreen2;
      switch (func) {

        // assignments
        case 'strokeStyle':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'fillText':
          if (Z > 0 && (!showOutput || showPreview || override)) x_[func](vals[0], vals[1], vals[2]);
          if (showOutput || showPreview) {
            let text = vals[0];
            ox = camX - camposX;
            oy = camY - camposY;
            oz = camZ - camposZ;
            p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
            d = Math.hypot(ox, oy, oz) + .0001;
            q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
            ox1 = p * output.width;
            oy1 = q * output.height;
            X1 = ox1 + vals[3];
            Y1 = oy1 + vals[4];
            octx[func](text, X1, Y1);
            if (X1 < 0) octx[func](text, X1 + output.width, Y1);
            if (X1 + X2 > output.width) octx[func](text, X1 - output.width, Y1);
          }
          break;
        case 'textAlign':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'globalCompositeOperation':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'lineWidth':
          if (vals.length) {
            x_[func] = vals[0];
            ox = camX - camposX;
            oy = camY - camposY;
            oz = camZ - camposZ;
            p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
            d = Math.hypot(ox, oy, oz) + .0001;
            q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
            //modsize = .4+Math.abs(.5 - q)*2
            modsize = .5 + (2 * Math.abs(.5 - q) * 1.5) ** 2 / 1.5;
            octx[func] = Math.min(250, vals[1] * modsize);
          } else {
            return [x_[func], octx[func]];
          }
          break;
        case 'fillStyle':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'globalAlpha':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals.length > 1 ? vals[1] : vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'font':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals.length > 1 ? vals[1] : vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'lineJoin':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;
        case 'lineCap':
          if (vals.length) {
            x_[func] = vals[0];
            octx[func] = vals[0];
          } else {
            return x_[func];
          }
          break;

        // function calls
        default:
          if (vals.length) {
            switch (func) {
              case 'lineTo':
                if (Z > 0 && (!showOutput || showPreview || override)) x_[func](...vals);
                if (showOutput || showPreview) {
                  ox = camX - camposX;
                  oy = camY - camposY;
                  oz = camZ - camposZ;
                  p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
                  if (op_ != -1) {
                    if (op_ > .75 && p < .25) p += 1;
                    if (op_ < .25 && p > .75) p -= 1;
                  }
                  op_ = p;
                  d = Math.hypot(ox, oy, oz) + .0001;
                  q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
                  HDRIqueue = [...HDRIqueue, [p * output.width, q * output.height]];
                }
                break;
              case 'clearRect':
                if (Z > 0 && (!showOutput || showPreview)) x_[func](vals[0], vals[1], vals[2], vals[3]);

                if (showOutput || showPreview || override) {
                  ox = camX - camposX;
                  oy = camY - camposY;
                  oz = camZ - camposZ;
                  p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
                  d = Math.hypot(ox, oy, oz) + .01;
                  q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
                  ox1 = p * output.width;
                  oy1 = q * output.height;
                  modsize = 1;
                  octx[func](ox1 - vals[6] * modsize / 2, oy1 - vals[7] * modsize / 2, vals[6] * modsize, vals[7] * modsize);
                }
                break;
              case 'fillRect':case 'strokeRect':
                if (Z > 0 && (!showOutput || showPreview)) x_[func](vals[0], vals[1], vals[2], vals[3]);

                if (showOutput || showPreview || override) {
                  ox = camX - camposX;
                  oy = camY - camposY;
                  oz = camZ - camposZ;
                  p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
                  d = Math.hypot(ox, oy, oz) + .0001;
                  q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
                  ox1 = p * output.width;
                  oy1 = q * output.height;
                  modsize = 1 + (2 * Math.abs(.5 - q) * 1.28) ** 11;
                  X1 = ox1 - vals[6] * modsize / 4;
                  Y1 = oy1 - vals[7] / 4;
                  X2 = vals[6] * modsize / 2;
                  Y2 = vals[7] / 2;
                  octx[func](X1, Y1, X2, Y2);
                  if (X1 < 0) octx[func](X1 + output.width, Y1, X2, Y2);
                  if (X1 + X2 > output.width) octx[func](X1 - output.width, Y1, X2, Y2);
                }
                break;
              case 'drawImage':
                if (Z > 0 && (!showOutput || showPreview || override)) x_[func](vals[0], vals[1], vals[2], vals[3], vals[4]);
                if (showOutput || showPreview) {
                  ox = camX - camposX;
                  oy = camY - camposY;
                  oz = camZ - camposZ;
                  vals[7] /= 1;
                  vals[8] /= 1;
                  p = ((Math.atan2(ox, oz) + Math.PI * 2) / Math.PI / 2 + hoff) % 1;
                  d = Math.hypot(ox, oy, oz) + .0001;
                  q = invertY ? 1 - Math.acos(oy / d) / Math.PI : Math.acos(oy / d) / Math.PI;
                  ox1 = p * output.width;
                  oy1 = q * output.height;
                  modsize = 1 + (2 * Math.abs(.5 - q) * 1.28) ** 11;
                  X1 = ox1 - vals[7] * modsize / 4;
                  Y1 = oy1 - vals[8] / 4;
                  X2 = vals[7] * modsize / 2;
                  Y2 = vals[8] / 2;
                  octx[func](vals[0], X1, Y1, X2, Y2);
                  if (X1 < 0) octx[func](vals[0], X1 + output.width, Y1, X2, Y2);
                  if (X1 + X2 > output.width) octx[func](vals[0], X1 - output.width, Y1, X2, Y2);
                }
                break;
              default:
                if (!showOutput || showPreview || override) x_[func](...vals);
                if (showOutput || showPreview || override) octx[func](...vals);
                break;}

          } else {
            switch (func) {
              case 'beginPath':
                if (!showOutput || showPreview || override) x_[func]();
                if (showOutput || showPreview || override) {
                  octx[func]();
                  HDRIqueue = [];
                  op_ = -1;
                }
                break;
              case 'stroke':
                if (!showOutput || showPreview || override) x_[func]();
                if (showOutput || showPreview || override) {
                  for (let m = 3; m--;) {
                    let ofx;
                    switch (m) {
                      case 0:ofx = -output.width;break;
                      case 1:ofx = 0;break;
                      case 2:ofx = output.width;break;}

                    polyOnBorder = false;
                    onLeft = false;
                    onRight = false;
                    outsized = false;
                    HDRIqueue.map((v, i) => {
                      if (!outsized) {
                        l1 = i;
                        l2 = (i + 1) % HDRIqueue.length;
                        el1 = HDRIqueue[l1];
                        el2 = HDRIqueue[l2];
                        if (Math.hypot(el2[0] + ofx - (el1[0] + ofx), el2[1] - el1[1]) > output.width / 1.1) {
                          outsized = true;
                        } else {
                          if (el1[0] + ofx >= 0 && el2[0] + ofx < 0 || el1[0] + ofx >= output.width && el2[0] + ofx < output.width) polyOnBorder = true;
                        }
                        X = v[0] + ofx;
                        Y = v[1];
                        if (X >= output.width) onRight = true;
                        if (X < 0) onLeft = true;
                      }
                    });
                    if (!outsized && (polyOnBorder || !(onRight || onLeft))) {
                      octx.beginPath();
                      HDRIqueue.map((v, i) => {
                        octx.lineTo(v[0] + ofx, v[1]);
                      });
                      octx.stroke();
                    }
                  }
                }
                break;
              case 'fill':
                if (!showOutput || showPreview || override) x_[func]();
                if (showOutput || showPreview || override) {
                  for (let m = 3; m--;) {
                    let ofx;
                    switch (m) {
                      case 0:ofx = -output.width;break;
                      case 1:ofx = 0;break;
                      case 2:ofx = output.width;break;}

                    polyOnBorder = false;
                    onLeft = false;
                    onRight = false;
                    outsized = false;
                    HDRIqueue.map((v, i) => {
                      if (!outsized) {
                        l1 = i;
                        l2 = (i + 1) % HDRIqueue.length;
                        el1 = HDRIqueue[l1];
                        el2 = HDRIqueue[l2];
                        if (Math.hypot(el2[0] + ofx - (el1[0] + ofx), el2[1] - el1[1]) > output.width / 1.1) {
                          outsized = true;
                        } else {
                          if (el1[0] + ofx >= 0 && el2[0] + ofx < 0 || el1[0] + ofx >= output.width && el2[0] + ofx < output.width) polyOnBorder = true;
                        }
                        X = v[0] + ofx;
                        Y = v[1];
                        if (X >= output.width) onRight = true;
                        if (X < 0) onLeft = true;
                      }
                    });
                    if (!outsized && (polyOnBorder || !(onRight || onLeft))) {
                      octx.beginPath();
                      HDRIqueue.map((v, i) => {
                        octx.lineTo(v[0] + ofx, v[1]);
                      });
                      octx.fill();
                    }
                  }
                }
                break;
              default:
                if (!showOutput || showPreview) x_[func]();
                if (showOutput || showPreview) octx[func]();
                break;}

          }
          break;}

      return [p, q];
    };

    R = (Rl, Pt, Yw, m) => {
      M = Math;
      A = M.atan2;
      H = M.hypot;

      let X0_ = X;
      let Y0_ = Y;
      let Z0_ = Z;
      let p, d;

      // MAIN
      if (m) {
        //X -= oX
        //Y -= oY
        //Z -= oZ
      }
      X = S(p = A(X, Y) + Rl) * (d = H(X, Y));
      Y = C(p) * d;
      X = S(p = A(X, Z) + (Yw + .0000)) * (d = H(X, Z));
      Z = C(p) * d;
      Y = S(p = A(Y, Z) + Pt) * (d = H(Y, Z));
      Z = C(p) * d;
      if (m) {
        X += oX;
        Y += oY;
        Z += oZ;
      }
      let X1_ = X;
      let Y1_ = Y;
      let Z1_ = Z;

      // CAM
      X = X0_;
      Y = Y0_;
      Z = Z0_;
      if (m) {
        //X -= camposX
        //Y -= camposY
        //Z -= camposZ
      }
      let mod = Rl == 0 && Pt == 0 && Yw == 0 ? 0 : 1;
      X = S(p = A(X, Y) + camRl * mod) * (d = H(X, Y));
      Y = C(p) * d;
      X = S(p = A(X, Z) + (camYw + .00001) * mod) * (d = H(X, Z));
      Z = C(p) * d;
      Y = S(p = A(Y, Z) + camPt * mod) * (d = H(Y, Z));
      Z = C(p) * d;
      if (m) {
        X += camposX;
        Y += camposY;
        Z += camposZ;
      }
      if (camMode == 'HDRI') {
        camD = H(X, Y, Z);
        X = camposX + X / camD;
        Y = camposY + Y / camD;
        Z = camposZ + Z / camD;
      }
      camX = X;
      camY = Y;
      camZ = Z;
      //camD += Z

      X = X1_;
      Y = Y1_;
      Z = Z1_;
    };

    HSVFromRGB = (R, G, B) => {
      let R_ = R / 255;
      let G_ = G / 255;
      let B_ = B / 255;
      let Cmin = Math.min(R_, G_, B_);
      let Cmax = Math.max(R_, G_, B_);
      let val = Cmax; //(Cmax+Cmin) / 2
      let delta = Cmax - Cmin;
      let sat = Cmax ? delta / Cmax : 0;
      let min = Math.min(R, G, B);
      let max = Math.max(R, G, B);
      let hue = 0;
      if (delta) {
        if (R >= G && R >= B) hue = (G - B) / (max - min);
        if (G >= R && G >= B) hue = 2 + (B - R) / (max - min);
        if (B >= G && B >= R) hue = 4 + (R - G) / (max - min);
      }
      hue *= 60;
      while (hue < 0) hue += 360;
      while (hue >= 360) hue -= 360;
      return [hue, sat, val];
    };

    R3 = (Rl, Pt, Yw, m = false) => {
      M = Math;
      A = M.atan2;
      H = M.hypot;
      if (m) {
        X -= oX;
        Y -= oY;
        Z -= oZ;
      }
      X = S(p = A(X, Y) + Rl) * (d = H(X, Y));
      Y = C(p) * d;
      Y = S(p = A(Y, Z) + Pt) * (d = H(Y, Z));
      Z = C(p) * d;
      X = S(p = A(X, Z) + Yw) * (d = H(X, Z));
      Z = C(p) * d;
    };

    Q = () => [c.width / 2 + X / (Z + .01) * 700, c.height / 2 + Y / (Z + .01) * 700,
    output.width / 2 + camX / (camZ + .01) * 700, output.height / 2 + camY / (camZ + .01) * 700];
    Q2 = () => [c.width / 2 + X * 75, c.height / 2 + Y * 75,
    output.width / 2 + camX * 75, output.height / 2 + camY * 75];

    I = (A, B, M, D, E, F, G, H) => (K = ((G - E) * (B - F) - (H - F) * (A - E)) / (J = (H - F) * (M - A) - (G - E) * (D - B))) >= 0 && K <= 1 && (L = ((M - A) * (B - F) - (D - B) * (A - E)) / J) >= 0 && L <= 1 ? [A + K * (M - A), B + K * (D - B)] : 0;

    spawnTunnel = (
    tx, ty, tz,
    rw, cl, sp = 1, rad = .5,
    theta1 = 0, theta2 = 0,
    theta1ModFreq = 0,
    theta1ModMag = 0,
    theta2ModFreq = 0,
    theta2ModMag = 0,
    theta1Offset = 0,
    theta2Offset = 0,
    radModFreq = 0,
    radModMag = 0,
    radModOffset = 0,
    showLine = false) =>
    {
      let X_ = X = tx;
      let Y_ = Y = ty;
      let Z_ = Z = tz;
      let ret = [];
      let p2a, p2, p2a1, ls;
      if (showLine) x('beginPath');
      for (let i = cl + 1; i--;) {
        let p1 = theta1 + C(Math.PI * 2 / cl * i * theta1ModFreq + theta1Offset) * theta1ModMag;
        let p2 = theta2 + C(Math.PI * 2 / cl * i * theta2ModFreq + theta2Offset) * theta2ModMag;
        let p2a1 = theta2 + C(Math.PI * 2 / cl * (i + 1) * theta2ModFreq + theta2Offset) * theta2ModMag;
        let lsa = rad + C(Math.PI * 2 / cl * i * radModFreq + radModOffset) * rad / 2 * radModMag;
        let lsb = rad + C(Math.PI * 2 / cl * (i + 1) * radModFreq + radModOffset) * rad / 2 * radModMag;
        if (i == cl) {
          p2a = p2;
          ls = lsa;
        } else if (i == 0) {
          p2a = p2a1;
          ls = lsb;
        } else {
          p2a = (p2 + p2a1) / 2;
          ls = (lsa + lsb) / 2;
        }
        let a = [];
        for (let j = rw + 1; j--;) {
          p = Math.PI * 2 / rw * j + Math.PI / rw;
          X = S(p) * ls;
          Y = 0;
          Z = C(p) * ls;
          R(-p2a + Math.PI / 2, 0, 0);
          R(0, 0, -p1);
          a = [...a, [X + X_, Y + Y_, Z + Z_]];
        }

        ret = [...ret, a];

        if (showLine) {
          X = X_;
          Y = Y_;
          Z = Z_;
          motionPath = [...motionPath, [X, Y, Z]];
          R(Rl, Pt, Yw, 1);
          x('lineTo', ...Q());
        }

        vx = C(p1) * C(p2) * sp;
        vy = S(p2) * sp;
        vz = S(p1) * C(p2) * sp;
        X_ += vx;
        Y_ += vy;
        Z_ += vz;
      }
      //if(showLine) stroke('#f00', '', 2, false)
      a = [];
      ret.map((v, i) => {
        if (i) {
          let s1 = ret[i];
          let s2 = ret[i - 1];
          for (let j = rw; j--;) {
            b = [];
            let l1_ = (j + 0) % rw;
            let l2_ = (j + 1) % rw;
            X = s1[l1_][0];
            Y = s1[l1_][1];
            Z = s1[l1_][2];
            b = [...b, [X, Y, Z]];
            X = s1[l2_][0];
            Y = s1[l2_][1];
            Z = s1[l2_][2];
            b = [...b, [X, Y, Z]];
            X = s2[l2_][0];
            Y = s2[l2_][1];
            Z = s2[l2_][2];
            b = [...b, [X, Y, Z]];
            X = s2[l1_][0];
            Y = s2[l1_][1];
            Z = s2[l1_][2];
            b = [...b, [X, Y, Z]];
            a = [...a, b];
          }
        }
      });
      return a;
    };


    Normal = (facet, autoFlipNormals = false, X1 = 0, Y1 = 0, Z1 = 0) => {
      let ax = 0,ay = 0,az = 0;
      facet.map(q_ => {ax += q_[0], ay += q_[1], az += q_[2];});
      ax /= facet.length, ay /= facet.length, az /= facet.length;
      let b1 = facet[2][0] - facet[1][0],b2 = facet[2][1] - facet[1][1],b3 = facet[2][2] - facet[1][2];
      let c1 = facet[1][0] - facet[0][0],c2 = facet[1][1] - facet[0][1],c3 = facet[1][2] - facet[0][2];
      crs = [b2 * c3 - b3 * c2, b3 * c1 - b1 * c3, b1 * c2 - b2 * c1];
      d = Math.hypot(...crs) + .001;
      let nls = 1; //normal line length
      crs = crs.map(q => q / d * nls);
      let X1_ = ax,Y1_ = ay,Z1_ = az;
      let flip = 1;
      if (autoFlipNormals) {
        let d1_ = Math.hypot(X1_ - X1, Y1_ - Y1, Z1_ - Z1);
        let d2_ = Math.hypot(X1 - (ax + crs[0] / 99), Y1 - (ay + crs[1] / 99), Z1 - (az + crs[2] / 99));
        flip = d2_ > d1_ ? -1 : 1;
      }
      let X2_ = ax + (crs[0] *= flip),Y2_ = ay + (crs[1] *= flip),Z2_ = az + (crs[2] *= flip);
      return [X1_, Y1_, Z1_, X2_, Y2_, Z2_];
    };

    async function loadOBJ(url, scale, tx, ty, tz, rl, pt, yw, recenter = true) {
      let res;
      await fetch(url, res => res).then(data => data.text()).then(data => {
        a = [];
        data.split("\nv ").map(v => {
          a = [...a, v.split("\n")[0]];
        });
        a = a.filter((v, i) => i).map(v => [...v.split(' ').map(n => +n.replace("\n", ''))]);
        ax = ay = az = 0;
        a.map(v => {
          v[1] *= -1;
          if (recenter) {
            ax += v[0];
            ay += v[1];
            az += v[2];
          }
        });
        ax /= a.length;
        ay /= a.length;
        az /= a.length;
        a.map(v => {
          X = (v[0] - ax) * scale;
          Y = (v[1] - ay) * scale;
          Z = (v[2] - az) * scale;
          R2(rl, pt, yw, 0);
          v[0] = X;
          v[1] = Y * (url.indexOf('bug') != -1 ? 2 : 1);
          v[2] = Z;
        });
        maxY = -6e6;
        a.map(v => {
          if (v[1] > maxY) maxY = v[1];
        });
        a.map(v => {
          v[1] -= maxY - oY;
          v[0] += tx;
          v[1] += ty;
          v[2] += tz;
        });

        b = [];
        data.split("\nf ").map(v => {
          b = [...b, v.split("\n")[0]];
        });
        b.shift();
        b = b.map(v => v.split(' '));
        b = b.map(v => {
          v = v.map(q => {
            return +q.split('/')[0];
          });
          v = v.filter(q => q);
          return v;
        });

        res = [];
        b.map(v => {
          e = [];
          v.map(q => {
            e = [...e, a[q - 1]];
          });
          e = e.filter(q => q);
          res = [...res, e];
        });
      });
      return res;
    }

    reflect = (a, n) => {
      let d1 = Math.hypot(...a) + .0001;
      let d2 = Math.hypot(...n) + .0001;
      a[0] /= d1;
      a[1] /= d1;
      a[2] /= d1;
      n[0] /= d2;
      n[1] /= d2;
      n[2] /= d2;
      let dot = -a[0] * n[0] + -a[1] * n[1] + -a[2] * n[2];
      let rx = -a[0] - 2 * n[0] * dot;
      let ry = -a[1] - 2 * n[1] * dot;
      let rz = -a[2] - 2 * n[2] * dot;
      return [-rx * d1, -ry * d1, -rz * d1];
    };

    geoSphere = (mx, my, mz, iBc, size) => {
      let collapse = 0,mind;
      let B = Array(iBc).fill().map(v => {
        X = Rn() - .5;
        Y = Rn() - .5;
        Z = Rn() - .5;
        return [X, Y, Z];
      });
      for (let m = 32; m--;) {
        B.map((v, i) => {
          X = v[0];
          Y = v[1];
          Z = v[2];
          B.map((q, j) => {
            if (j != i) {
              X2 = q[0];
              Y2 = q[1];
              Z2 = q[2];
              d = 1 + (Math.hypot(X - X2, Y - Y2, Z - Z2) * (3 + iBc / 40) * 3) ** 3;
              X += (X - X2) * 9 / d;
              Y += (Y - Y2) * 9 / d;
              Z += (Z - Z2) * 9 / d;
            }
          });
          d = Math.hypot(X, Y, Z);
          v[0] = X / d;
          v[1] = Y / d;
          v[2] = Z / d;
          if (collapse) {
            d = 25 + Math.hypot(X, Y, Z);
            v[0] = (X - X / d) / 1.1;
            v[1] = (Y - Y / d) / 1.1;
            v[2] = (Z - Z / d) / 1.1;
          }
        });
      }
      mind = 6e6;
      B.map((v, i) => {
        X1 = v[0];
        Y1 = v[1];
        Z1 = v[2];
        B.map((q, j) => {
          X2 = q[0];
          Y2 = q[1];
          Z2 = q[2];
          if (i != j) {
            d = Math.hypot(a = X1 - X2, b = Y1 - Y2, e = Z1 - Z2);
            if (d < mind) mind = d;
          }
        });
      });
      a = [];
      B.map((v, i) => {
        X1 = v[0];
        Y1 = v[1];
        Z1 = v[2];
        B.map((q, j) => {
          X2 = q[0];
          Y2 = q[1];
          Z2 = q[2];
          if (i != j) {
            d = Math.hypot(X1 - X2, Y1 - Y2, Z1 - Z2);
            if (d < mind * 2) {
              if (!a.filter(q => q[0] == X2 && q[1] == Y2 && q[2] == Z2 && q[3] == X1 && q[4] == Y1 && q[5] == Z1).length) a = [...a, [X1 * size, Y1 * size, Z1 * size, X2 * size, Y2 * size, Z2 * size]];
            }
          }
        });
      });
      B.map(v => {
        v[0] *= size / 1.3333;
        v[1] *= size / 1.3333;
        v[2] *= size / 1.3333;
        v[0] += mx;
        v[1] += my;
        v[2] += mz;
      });
      return [mx, my, mz, size, B, a];
    };

    /*
    burst = new Image()
    url = "https://srmcgann.github.io/temp/burst.png"
    await fetch(url).then(res=>res.blob()).then(data=> burst.src = URL.createObjectURL(data))
     //burst1 = new Image()
    //burst1.src = "https://srmcgann.github.io/temp/burst1.png"
    burst2 = new Image()
    url = "https://srmcgann.github.io/temp/burst2.png"
    await fetch(url).then(res=>res.blob()).then(data=> burst2.src = URL.createObjectURL(data))
    burst3 = new Image()
    url = "https://srmcgann.github.io/temp/burst3.png"
    await fetch(url).then(res=>res.blob()).then(data=> burst3.src = URL.createObjectURL(data))
    burst4 = new Image()
    url = "https://srmcgann.github.io/temp/burst4.png"
    await fetch(url).then(res=>res.blob()).then(data=> burst4.src = URL.createObjectURL(data))
    burstz = [ burst, burst2, burst3, burst4]
     sphere0 = new Image()
    url = 'https://srmcgann.github.io/ultratemp6/sphere_colorful.png'
    await fetch(url).then(res=>res.blob()).then(data=> sphere0.src = URL.createObjectURL(data))
     sphere1 = new Image()
    url = 'https://srmcgann.github.io/temp13/sphere_colorful_1.png'
    await fetch(url).then(res=>res.blob()).then(data=> sphere1.src = URL.createObjectURL(data))
    sphere2 = new Image()
    url = 'https://srmcgann.github.io/temp13/sphere_colorful_2.png'
    await fetch(url).then(res=>res.blob()).then(data=> sphere2.src = URL.createObjectURL(data))
    sphere3 = new Image()
    url = 'https://srmcgann.github.io/temp13/sphere_colorful_3.png'
    await fetch(url).then(res=>res.blob()).then(data=> sphere3.src = URL.createObjectURL(data))
    sphere4 = new Image()
    url = 'https://srmcgann.github.io/temp13/sphere_colorful_4.png'
    await fetch(url).then(res=>res.blob()).then(data=> sphere4.src = URL.createObjectURL(data))
    spherez = [ sphere1, sphere2, sphere3, sphere4 ]
    */





    star1 = new Image();
    url = "https://srmcgann.github.io/stars/star1.png";
    await fetch(url).then(res => res.blob()).then(data => star1.src = URL.createObjectURL(data));

    star2 = new Image();
    url = "https://srmcgann.github.io/stars/star2.png";
    await fetch(url).then(res => res.blob()).then(data => star2.src = URL.createObjectURL(data));

    star3 = new Image();
    url = "https://srmcgann.github.io/stars/star3.png";
    await fetch(url).then(res => res.blob()).then(data => star3.src = URL.createObjectURL(data));

    star4 = new Image();
    url = "https://srmcgann.github.io/stars/star4.png";
    await fetch(url).then(res => res.blob()).then(data => star4.src = URL.createObjectURL(data));

    star5 = new Image();
    url = "https://srmcgann.github.io/stars/star5.png";
    await fetch(url).then(res => res.blob()).then(data => star5.src = URL.createObjectURL(data));

    star6 = new Image();
    url = "https://srmcgann.github.io/stars/star6.png";
    await fetch(url).then(res => res.blob()).then(data => star6.src = URL.createObjectURL(data));

    star7 = new Image();
    url = "https://srmcgann.github.io/stars/star7.png";
    await fetch(url).then(res => res.blob()).then(data =&g.........完整代码请登录后点击上方下载按钮下载查看

网友评论0