var container, renderer, scene, camera; var root, maw, tendrils = [], rings = []; var time = 0, timeStep = (1/60); var tendrilCount = 16, tendrilChildrenCount = 16, childRotation = Math.PI * (1/tendrilCount), innerRadius = tendrilCount / Math.PI * 0.5; function initThree() { container = document.getElementById('container'); renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x000000); camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000); scene = new THREE.Scene(); camera.position.z = 5; camera.position.x = -5; camera.lookAt(scene.position); camera.position.x -= 3; container.appendChild(renderer.domElement); } function createObjects() { root = new THREE.Object3D(); scene.add(root); createBody(); createMaw(); } function createBody() { var geometry = new THREE.SphereGeometry(0.25, 16, 16), material = new THREE.MeshPhongMaterial({color:0xD1DBBD}), ring, mesh; var ringCount = 12; for (var i = 0; i < ringCount; i++) { ring = new THREE.Object3D(); root.add(ring); rings.push(ring); ring.position.z = -(i + 1) * 3; ring.rotation.z = Math.PI / tendrilChildrenCount; for (var j = 0; j < tendrilChildrenCount; j++) { mesh = new THREE.Mesh(geometry, material); ring.add(mesh); var angle = Math.PI * 2 * (j / tendrilCount), angleX = Math.cos(angle), angleY = Math.sin(angle), scl = 1 - (i / ringCount) * 0.9; mesh.position.x = angleX * innerRadius; mesh.position.y = angleY * innerRadius; mesh.scale.set(scl, scl, scl); } } } function createMaw() { var geometry = new THREE.SphereGeometry(0.5, 16, 16, 0, Math.PI), material = new THREE.MeshPhongMaterial({color:0xD1DBBD}), tendrilHolder, tendril, mesh; material.side = THREE.DoubleSide; maw = new THREE.Object3D(); root.add(maw); for (var i = 0; i < tendrilCount; i++) { tendrilHolder = new THREE.Object3D(); tendril = new THREE.Object3D(); var angle = Math.PI * 2 * (i / tendrilCount), angleX = Math.cos(angle), angleY = Math.sin(angle); tendrilHolder.rotation.z = angle; tendrilHolder.position.x = angleX * innerRadius; tendrilHolder.position.y = angleY * innerRadius; tendrilHolder.add(tendril); maw.add(tendrilHolder); tendrils.push(tendril); var prevMesh; for (var j = 0; j < tendrilChildrenCount; j++) { mesh = new THREE.Mesh(geometry, material); if (j === 0) { tendril.add(mesh); } else { var scl = 0.67; mesh.scale.set(scl, scl, scl); mesh.position.x = 0.5 + scl * 0.5; mesh.rotation.y = childRotation; prevMesh.add(mesh); } prevMesh = mesh; } } } function createLights() { var light; light = new THREE.DirectionalLight(0xffffff, 0.5); light.position.set(1, 0.5, 0.5); light.position.normalize(); scene.add(light); light = new THREE.DirectionalLight(0xffffff, 0.2); light.position.set(-1, 0, 0); scene.add(light); light = new THREE.DirectionalLight(0xffffff, 0.05); light.position.set(0, 0, 1); scene.add(light); light = new THREE.PointLight(0x008888, 0.5); light.position.set(0, 0, 2.5) scene.add(light); } function update() { var i = 0; rings.forEach(function(r) { r.position.y = Math.sin(time + i) * 0.5; r.position.x = Math.cos(time) * 0.5; i++; }); maw.position.y = Math.sin(time) * 0.5; tendrils.forEach(function(t) { t.rotation.y += timeStep; }); } function draw() { renderer.render(scene, camera); } function loop() { update(); draw(); time += timeStep; requestAnimationFrame(loop); } window.onload = function() { initThree(); createObjects(); createLights(); window.addEventListener('resize', resizeHandler); requestAnimationFrame(loop); }; function resizeHandler() { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); }