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>