← Mike Higgins Home
Custom Code Experiment •

Terrain WF-1

Source Code View HTML / CSS / JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Circular Terrain Animation</title>
    <style>
        html, body {
            border: 0;
            padding: 0;
            margin: 0;
            overflow: hidden;
            height: 100%;
            width: 100%;
            background: #000;
        }
        #container {
            height: 100vh;
            width: 100%;
            overflow: hidden;
        }
    </style>
</head>
<body>
    <div id="container"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
    <script>
        var container = document.getElementById('container');
        var vertexHeight = 8000,
            radialSegments = 80,
            heightSegments = 40,
            radius = 50000,
            background = "#001a33";

        var camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 400000);
        camera.position.y = 35000;
        camera.position.z = 35000;

        var scene = new THREE.Scene();
        scene.fog = new THREE.Fog(background, 1, 300000);

        var light = new THREE.AmbientLight(0x404040);
        scene.add(light);

        var directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
        directionalLight.position.set(0, 1, 0);
        scene.add(directionalLight);

        // Create circular geometry
        var circleGeo = new THREE.Geometry();

        // Generate vertices in a circular pattern
        for (var ring = 0; ring <= heightSegments; ring++) {
            var ringRadius = (ring / heightSegments) * radius;
            for (var seg = 0; seg < radialSegments; seg++) {
                var angle = (seg / radialSegments) * Math.PI * 2;
                var x = Math.cos(angle) * ringRadius;
                var z = Math.sin(angle) * ringRadius;
                var y = 0;
                circleGeo.vertices.push(new THREE.Vector3(x, y, z));
            }
        }

        // Create faces
        for (var ring = 0; ring < heightSegments; ring++) {
            for (var seg = 0; seg < radialSegments; seg++) {
                var v1 = ring * radialSegments + seg;
                var v2 = ring * radialSegments + ((seg + 1) % radialSegments);
                var v3 = (ring + 1) * radialSegments + seg;
                var v4 = (ring + 1) * radialSegments + ((seg + 1) % radialSegments);

                circleGeo.faces.push(new THREE.Face3(v1, v2, v3));
                circleGeo.faces.push(new THREE.Face3(v2, v4, v3));
            }
        }

        var circle = new THREE.Mesh(circleGeo, new THREE.MeshBasicMaterial({
            color: "#ff6b6b",
            wireframe: true
        }));

        scene.add(circle);

        var renderer = new THREE.WebGLRenderer({alpha: false});
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(background, 1);
        container.appendChild(renderer.domElement);

        // Initialize vertex heights
        for (var i = 0; i < circleGeo.vertices.length; i++) {
            circleGeo.vertices[i].y += Math.random() * vertexHeight - vertexHeight / 2;
            circleGeo.vertices[i]._myY = circleGeo.vertices[i].y;
        }

        var count = 0;

        function render() {
            requestAnimationFrame(render);

            // Rotate camera around the center
            var x = camera.position.x;
            var z = camera.position.z;
            camera.position.x = x * Math.cos(0.001) + z * Math.sin(0.001);
            camera.position.z = z * Math.cos(0.001) - x * Math.sin(0.001);
            camera.lookAt(new THREE.Vector3(0, 0, 0));

            // Animate vertices in a circular wave pattern
            for (var i = 0; i < circleGeo.vertices.length; i++) {
                var vertex = circleGeo.vertices[i];
                var distance = Math.sqrt(vertex.x * vertex.x + vertex.z * vertex.z);
                var angle = Math.atan2(vertex.z, vertex.x);

                // Create spiral wave effect
                var wave = Math.sin(distance * 0.0002 + angle * 2 + count * 0.02) *
                          Math.cos(angle * 3 - count * 0.015);

                vertex.y = wave * vertex._myY * 0.8;
            }

            circleGeo.verticesNeedUpdate = true;

            // Color cycling
            var hue = (count * 0.0001) % 1;
            circle.material.color.setHSL(hue, 0.8, 0.5);

            // Rotate light
            var lightAngle = count * 0.01;
            directionalLight.position.x = Math.cos(lightAngle) * 10000;
            directionalLight.position.z = Math.sin(lightAngle) * 10000;

            // Rotate the mesh itself for extra dynamics
            circle.rotation.y += 0.0005;

            count += 0.1;
            renderer.render(scene, camera);
        }

        render();

        window.addEventListener('resize', onWindowResize, false);

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
    </script>
</body>
</html>