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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Pendulum</title>


    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Barlow&display=swap" rel="stylesheet">

    <style>
        body {
            overflow: hidden;
            background-color: midnightblue;
            color: white;
            font-family: 'Barlow', 'Roboto', 'Source Sans Pro', 'Open Sans', 'Lato', Helvetica, Arial, sans-serif;
        }

        #header {
            position: absolute;
            padding-left: 2rem;
        }

        #footer {
            position: absolute;
            bottom: 0;
            padding-left: 2rem;
        }

        a {
            color: white;
        }
    </style>

    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.164.0/build/three.module.js"
            }
        }
    </script>

</head>

<body>

    <div id="header">
        <h1>3D PENDULUM</h1>

        <p>Left-click-drag to rotate view, right-click-drag to pan, mousewheel to zoom.</p>
        <p><a href="code.html" target="_blank">Code</a>, <a href="pendulum.glb">Model</a></p>
    </div>

    <div id="footer">
        <p><a href="https://jamesstorey.co.nz">jamesstorey.co.nz</a></p>
    </div>

    <script type="module">

        import * as THREE from 'three';

        import { OrbitControls } from 'https://unpkg.com/three@0.164.0/examples/jsm/controls/OrbitControls.js';
        import { GLTFLoader } from 'https://unpkg.com/three@0.164.0/examples/jsm/loaders/GLTFLoader.js';
        import { RGBELoader } from 'https://unpkg.com/three@0.164.0/examples/jsm/loaders/RGBELoader.js';

        var renderer, scene, camera;

        var mixer, clock;

        function init() {

            // renderer
            renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.toneMapping = THREE.ACESFilmicToneMapping;
            renderer.toneMappingExposure = 0.8;
            document.body.appendChild(renderer.domElement);


            // scene
            scene = new THREE.Scene();

            // camera
            camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.set(-10, 10, -20);
            
            scene.add(camera);

            // controls
            var controls = new OrbitControls(camera, renderer.domElement);
            controls.target.set(0,4,0);
            controls.update();
            controls.addEventListener('change', render);
            controls.minDistance = 3;
            controls.maxDistance = 50;

            clock = new THREE.Clock();

            //hdri lighting
            //https://discourse.threejs.org/t/how-to-add-hdri-background/53675/4

            const pmremGenerator = new THREE.PMREMGenerator( renderer );

            const hdriLoader = new RGBELoader()
            //hdri image sourced from
            //https://hdri-haven.com/hdri/decorated-photography-atelier
            hdriLoader.load( 'christmas_photo_studio_06_1k.hdr', function ( texture ) {
                const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
                texture.dispose();
                pmremGenerator.dispose();
                scene.environment = envMap
            } );


            // load the model

            var loader = new GLTFLoader();

            loader.load('pendulum.glb', function (gltf) {

                scene.add(gltf.scene);

                    //https://stackoverflow.com/questions/60704912/play-a-gltf-animation-three-js
                mixer = new THREE.AnimationMixer(gltf.scene);

                gltf.animations.forEach((clip) => {

                    mixer.clipAction(clip).play();

                });

            });


            // handle window resize events
            window.addEventListener('resize', onWindowResize, false);

        }

        function onWindowResize() {

            renderer.setSize(window.innerWidth, window.innerHeight);

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            render();

        }


        function render() {

            renderer.render(scene, camera);

        }


        function animate() {
            requestAnimationFrame(animate);
            var delta = clock.getDelta();

            if (mixer) mixer.update(delta);

            render();
        }


        init();

        animate();


    </script>

</body>

</html>