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 de pijltjes toetsen verplaatst de animatie in x of y richting.
De gemapte afbeeldingen komt in textureEquirec (regel 70) en worden op de bol of torus gemeshed in regel 80.
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.
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,
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>