spiegelbal slingers

spiegelbal slingers

 
 
spiegelbal boxen
 
spiegelbal boxen 
   
 
 
spiegelbal fractalstad
spegelbal fractalstad
 
 
spiegeltorus on Amsterdam
 
spiegeltorus in Amsterdam
 
 
 
spiegeltorus in ruimtepuin
 
spiegeltorus in ruimtepuin
 
 
 
spiegelbal boven de wolken
 
spiegelbal boven de wolken
 
 
 
spiegelbal in ruimtestad
 
spiegelbal in ruimtestad
 
 
 
spiegeltorus in ruimtepuin

Spiegelbal en torusknoop.                           terug naar de inleiding                  ga naar de animatie in fullscreen

een animatie met equirectangulaire afbeeldingen en een bal en torusknoop waarin deze afbeeldingen worden gespiegeld.

Met muisbewegingen en li of re muisknop ingedrukt roteer je de  animatie met het muiswiel verplaatst de animatie in z richting.

Met de pijltjes toetsen verplaatst de animatie in x of y richting.

De start animatie wordt geladen in de functie createEquirect. (regel 66 t/m 71)
De afbeeldingen worden in de functie createSpiegebol (regel 73 t/m 82) op een SphereGeometry of een TorusKnotGeometrie geplakt

De gemapte afbeeldingen komt in textureEquirec (regel 70) en worden op de bol of torus gemeshed in regel 80.

In createGUI worden de afbeeldingen geladen en aan de functie createEquirectShader (regel 85) gegeven.
In deze functie is het material een shaderMaterial.  In regel 102 wordt deze shadermaterial als achtergrond gemeshed

op een SphereGeometry (regel 101)

Alle libs zijn javaScript ES6 modules. Dit zijn scripts opgebouwd uit modules wat een forse verbetering van de codeer stijl betekend.

addon lib
De muis en pijltjestoets bewegingen worden gerealiseerd met de addon lib OrbitControls,
zie voor de achtergrond de functie createControl2 (regel 202) en voor de bol en torus de functie createControl regel (197)

De GUI (grafische user interface) wordt gerealiseerd met de addon lib lil-gui-module.min.js  zie de functie createGUI (regel 115)

Voor het overzicht  is alle code in functies gezet die worden aangeroepen in  function init()  (regel 27)

De schets maakt gebruik van twee camera's, een voor de achtergrond en een voor de bol,

De achtergrond beweegd mee met de bol, dit door het telkens copieeren van de camera positie van de bol afbeelding

naar de camerapositie van de achtergrond afbeelding (regel 219).

 
<html>
  <head>
    <title>spiegelbal</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style> body { margin: 0;} </style>
  </head>
 
  <body>
     <script type="importmap">
          {
            "imports": {
              "three": "../build/three.module.js",
              "three/addons/": "../jsm/"
          }  }
      </script>
 
      <script type="module">
          import * as THREE from 'three';
          import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
          import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
     let scene, sceneBol, camera, cameraBol, renderer, controls;
     let textureLoader, textureEquirec, equirectShader, uniforms, gui;
     let bolG, bolMat, bolM, equirectG, equirectMat, equirectM, params, bol_torus;
 
      init();
      play();
 
      function init() {
        scene = new THREE.Scene();
        sceneBol = new THREE.Scene();
        window.addEventListener( 'resize', onWindowResize );
        createCamera();
        createLight();  //deze uitschakelen dan in de bol zwart
        createRenderer();//createRenderen moet altijd boven createControls staan
        createControl();
        createControl2();
        createEquirect(); //Laden van de Equirectangular afbeelding
        createEquirectShader(); //uitschakelen --> witte bol met zwarte achtergrond
        createSpiegelbol(); // uitschakelen dan zie je alleen de omgeving
        createGUI();
        onWindowResize();
    }
 
    function createCamera(){
      cameraBol = new THREE.PerspectiveCamera( 70, window.innerWidth/ window.innerHeight, 1, 100000 );
      cameraBol.position.set( 0, 0, 800 );
      camera = new THREE.PerspectiveCamera( 70, window.innerWidth/ window.innerHeight, 1, 100000 );
      camera.position.set( 0, 0, 400 );
    }
 
     function createLight(){
       let ambient = new THREE.AmbientLight( 0xffffff,2.0 );
       sceneBol.add( ambient );
     }
 
     function createRenderer(){
       renderer = new THREE.WebGLRenderer();
       renderer.autoClear = false;
       renderer.setPixelRatio( window.devicePixelRatio );
       renderer.setSize( window.innerWidth , window.innerHeight );
       document.body.appendChild( renderer.domElement );
     }
 
    function createEquirect(){
      textureLoader = new THREE.TextureLoader();
      textureEquirec = textureLoader.load( '../textures/stenen3.jpg' );
      textureEquirec.colorSpace = THREE.SRGBColorSpace;
      textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
    }
 
    function createSpiegelbol(){
      sceneBol.remove( bolM );
      if (bol_torus) { bolG = new THREE.SphereGeometry( 400.0, 48, 24 );
      bol_torus = false}
      else  { bolG = new THREE.TorusKnotGeometry (200,80,200,20,2,3);
      bol_torus = true}
       //de ommgeving wordt met envMap op de bol gemapt
       bolMat= new THREE.MeshBasicMaterial( { envMap: textureEquirec} );
       bolM = new THREE.Mesh( bolG, bolMat );
       sceneBol.add( bolM );
     }
 
     function createEquirectShader(){
       scene.remove( equirectM );
       equirectShader = THREE.ShaderLib[ 'equirect' ];
       equirectMat = new THREE.ShaderMaterial( {
 
       uniforms: THREE.UniformsUtils.clone( equirectShader.uniforms ),
       fragmentShader: equirectShader.fragmentShader,
       vertexShader: equirectShader.vertexShader,
       depthWrite: false,
      //depthTest: false,
       side: THREE.BackSide
    } );
       equirectMat.uniforms[ 'tEquirect' ].value = textureEquirec;
       Object.defineProperty( equirectMat, 'map', {
       get: function () {return this.uniforms.tEquirect.value;}} );
 
       equirectG = new THREE.SphereGeometry( 1000, 200, 200 );
       equirectM = new THREE.Mesh( equirectG, equirectMat );
       equirectM.geometry.rotateY(Math.PI * 0.25);
       scene.add( equirectM );
    }
 
     function onWindowResize() {
       cameraBol.aspect = window.innerWidth / window.innerHeight;
       cameraBol.updateProjectionMatrix();
       camera.aspect = window.innerWidth / window.innerHeight;
       camera.updateProjectionMatrix();
       renderer.setSize( window.innerWidth , window.innerHeight );
     }
 
    function createGUI() {
      params = {
        fractals_3d: function () {
          textureEquirec = textureLoader.load( '../textures/stenen3.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
        },
        slingers: function () {
          textureEquirec = textureLoader.load( '../textures/texture2.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
      },
        Amsterdam: function () {
          textureEquirec = textureLoader.load( '../textures/brug.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
      },
        boven_de_wolken: function () {
          textureEquirec = textureLoader.load( '../textures/lucht.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
      },
       ruimtepuin: function () {
          textureEquirec = textureLoader.load( '../textures/ruimtepuin.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
      },
       fractalstad: function () {
          textureEquirec = textureLoader.load( '../textures/fractalstad.jpg' );
          textureEquirec.colorSpace = THREE.SRGBColorSpace;
          textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
          createEquirectShader();
          bolMat.envMap = textureEquirec;
          bolMat.needsUpdate = true;
      },
       boxen: function () {
         textureEquirec = textureLoader.load( '../textures/randcubes.jpg' );
         textureEquirec.colorSpace = THREE.SRGBColorSpace;
         textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
         createEquirectShader();
         bolMat.envMap = textureEquirec;
         bolMat.needsUpdate = true;
     },
      ruimtestad: function () {
         textureEquirec = textureLoader.load( '../textures/ruimtestad.jpg' );
         textureEquirec.colorSpace = THREE.SRGBColorSpace;
         textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
         createEquirectShader();
         bolMat.envMap = textureEquirec;
         bolMat.needsUpdate = true;
     },
         bol_in_uitschakelen: true, bol_torus: true
     };
 
       let gui = new GUI({width:180});
       gui.add( params, 'fractals_3d' );
       gui.add( params, 'slingers' );
       gui.add( params, 'Amsterdam' );
       gui.add( params, 'boven_de_wolken' );
       gui.add( params, 'ruimtepuin' );
       gui.add( params, 'fractalstad' );
       gui.add( params, 'boxen' );
       gui.add( params, 'ruimtestad' );
       gui.add( params, 'bol_in_uitschakelen' );
       gui.add( params, 'bol_torus' ).onChange(createSpiegelbol);
       gui.open();
    }
    function createControl()  {
        const controls = new OrbitControls( cameraBol , renderer.domElement);
        controls.listenToKeyEvents( window );
           //als default wordt er naar de pijltjestoetsen geluisterd
    }
    function createControl2()  {
        const controls2 = new OrbitControls( camera , renderer.domElement);
        controls2.listenToKeyEvents( window );
           //als default wordt er naar de pijltjestoetsen geluisterd
    }
 
   function animate() {
     var time = Date.now();
       bolM.position.x = Math.cos( time * 0.0005 ) * 400;
       bolM.position.y = Math.sin( time * 0.0005 ) * 300;
       bolM.position.z = Math.sin( time * 0.0005 ) * 200;
 
       equirectM.position.x = Math.cos( time * 0.0001 ) * 700;
       equirectM.position.y = Math.sin( time * 0.0001 ) * 400;
       equirectM.position.z = Math.sin( time * 0.0001 ) * 400;
 
       cameraBol.lookAt( sceneBol.position );
       camera.rotation.copy( cameraBol.rotation );
       renderer.render( scene, camera );
       renderer.render( sceneBol, cameraBol );
     if (params.bol_in_uitschakelen) {sceneBol.visible = true;}
    else {sceneBol.visible = false;}
   }
 
   function play() {
       renderer.setAnimationLoop( () => {animate()} );
  }
    </script>
  </body>
</html>