import * as THREE from "three/build/three.module.js"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; window.THREE = THREE; // Used by APP Scripts. var APP = { Player: function () { var renderer = new THREE.WebGLRenderer({ antialias: true }); var controls; renderer.setPixelRatio(window.devicePixelRatio); // TODO: Use player.setPixelRatio() renderer.outputEncoding = THREE.sRGBEncoding; var loader = new THREE.ObjectLoader(); var camera, scene; var events = {}; var dom = document.createElement("div"); dom.appendChild(renderer.domElement); this.dom = dom; this.width = 500; this.height = 500; this.load = function (json) { var project = json.project; if (project.shadows !== undefined) renderer.shadowMap.enabled = project.shadows; if (project.shadowType !== undefined) renderer.shadowMap.type = project.shadowType; if (project.toneMapping !== undefined) renderer.toneMapping = project.toneMapping; if (project.toneMappingExposure !== undefined) renderer.toneMappingExposure = project.toneMappingExposure; if (project.physicallyCorrectLights !== undefined) renderer.physicallyCorrectLights = project.physicallyCorrectLights; this.setScene(loader.parse(json.scene)); this.setCamera(loader.parse(json.camera)); events = { init: [], start: [], stop: [], keydown: [], keyup: [], pointerdown: [], pointerup: [], pointermove: [], update: [], }; var scriptWrapParams = "player,renderer,scene,camera"; var scriptWrapResultObj = {}; for (var eventKey in events) { scriptWrapParams += "," + eventKey; scriptWrapResultObj[eventKey] = eventKey; } var scriptWrapResult = JSON.stringify(scriptWrapResultObj).replace( /\"/g, "" ); for (var uuid in json.scripts) { var object = scene.getObjectByProperty("uuid", uuid, true); if (object === undefined) { console.warn("APP.Player: Script without object.", uuid); continue; } var scripts = json.scripts[uuid]; for (var i = 0; i < scripts.length; i++) { var script = scripts[i]; var functions = new Function( scriptWrapParams, script.source + "\nreturn " + scriptWrapResult + ";" ).bind(object)(this, renderer, scene, camera); for (var name in functions) { if (functions[name] === undefined) continue; if (events[name] === undefined) { console.warn("APP.Player: Event type not supported (", name, ")"); continue; } events[name].push(functions[name].bind(object)); } } } dispatch(events.init, arguments); }; this.setCamera = function (value) { camera = value; camera.aspect = this.width / this.height; camera.updateProjectionMatrix(); }; this.setScene = function (value) { scene = value; }; this.setPixelRatio = function (pixelRatio) { renderer.setPixelRatio(pixelRatio); }; this.setSize = function (width, height) { this.width = width; this.height = height; if (camera) { camera.aspect = this.width / this.height; camera.updateProjectionMatrix(); } if (renderer) { controls = new OrbitControls(camera, renderer.domElement); controls.target = new THREE.Vector3(0, 0, 0); controls.enableZoom = false; controls.update(); renderer.setSize(width, height); } }; function dispatch(array, event) { for (var i = 0, l = array.length; i < l; i++) { array[i](event); } } var time, startTime, prevTime; function animate() { controls.update(); time = performance.now(); try { dispatch(events.update, { time: time - startTime, delta: time - prevTime, }); } catch (e) { console.error(e.message || e, e.stack || ""); } renderer.render(scene, camera); prevTime = time; } this.play = function () { startTime = prevTime = performance.now(); document.addEventListener("keydown", onKeyDown); document.addEventListener("keyup", onKeyUp); document.addEventListener("pointerdown", onPointerDown); document.addEventListener("pointerup", onPointerUp); document.addEventListener("pointermove", onPointerMove); dispatch(events.start, arguments); renderer.setAnimationLoop(animate); }; this.stop = function () { document.removeEventListener("keydown", onKeyDown); document.removeEventListener("keyup", onKeyUp); document.removeEventListener("pointerdown", onPointerDown); document.removeEventListener("pointerup", onPointerUp); document.removeEventListener("pointermove", onPointerMove); dispatch(events.stop, arguments); renderer.setAnimationLoop(null); }; this.render = function (time) { dispatch(events.update, { time: time * 1000, delta: 0 /* TODO */ }); renderer.render(scene, camera); }; this.dispose = function () { renderer.dispose(); camera = undefined; scene = undefined; }; // function onKeyDown(event) { dispatch(events.keydown, event); } function onKeyUp(event) { dispatch(events.keyup, event); } function onPointerDown(event) { dispatch(events.pointerdown, event); } function onPointerUp(event) { dispatch(events.pointerup, event); } function onPointerMove(event) { dispatch(events.pointermove, event); } }, }; const SEPARATION = 100, AMOUNTX = 50, AMOUNTY = 50; let container; let camera, scene, renderer; let particles, count = 0; let windowHalfX = window.innerWidth / 2; let windowHalfY = window.innerHeight / 2; init(); animate(); function init() { container = document.createElement("div"); const about = document.getElementsByClassName("about")[0]; about.appendChild(container); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 500, 10000 ); camera.position.z = 1000; camera.position.y = 250; scene = new THREE.Scene(); scene.background = new THREE.Color(0x131313); // const numParticles = AMOUNTX * AMOUNTY; const positions = new Float32Array(numParticles * 3); const scales = new Float32Array(numParticles); let i = 0, j = 0; for (let ix = 0; ix < AMOUNTX; ix++) { for (let iy = 0; iy < AMOUNTY; iy++) { positions[i] = ix * SEPARATION - (AMOUNTX * SEPARATION) / 2; // x positions[i + 1] = 0; // y positions[i + 2] = iy * SEPARATION - (AMOUNTY * SEPARATION) / 2; // z scales[j] = 1; i += 3; j++; } } const geometry = new THREE.BufferGeometry(); geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3)); geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1)); const material = new THREE.ShaderMaterial({ uniforms: { color: { value: new THREE.Color(0xffffff) }, }, vertexShader: document.getElementById("vertexshader").textContent, fragmentShader: document.getElementById("fragmentshader").textContent, }); // particles = new THREE.Points(geometry, material); scene.add(particles); // renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight / 2); container.appendChild(renderer.domElement); container.style.touchAction = "none"; // windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); window.addEventListener("resize", onWindowResize); } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // function onPointerMove(event) { if (event.isPrimary === false) return; } // function animate() { requestAnimationFrame(animate); render(); } function render() { //camera.lookAt(scene.position); const positions = particles.geometry.attributes.position.array; const scales = particles.geometry.attributes.scale.array; let i = 0, j = 0; for (let ix = 0; ix < AMOUNTX; ix++) { for (let iy = 0; iy < AMOUNTY; iy++) { positions[i + 1] = Math.sin((ix + count) * 0.3) * 50 + Math.sin((iy + count) * 0.5) * 50; scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 20 + (Math.sin((iy + count) * 0.5) + 1) * 20; i += 3; j++; } } particles.geometry.attributes.position.needsUpdate = true; particles.geometry.attributes.scale.needsUpdate = true; renderer.render(scene, camera); count += 0.1; } var loader = new THREE.FileLoader(); loader.load("brain.json", function (text) { var player = new APP.Player(); player.load(JSON.parse(text)); player.setSize(window.innerWidth, window.innerHeight); player.play(); const hero = document.getElementById("hero"); hero.after(player.dom); window.addEventListener("resize", function () { player.setSize(window.innerWidth, window.innerHeight); }); }); const nav = () => { const burger = document.querySelector(".burger"); const nav = document.querySelector("nav ul"); burger.addEventListener("click", () => { nav.classList.toggle("nav-active"); burger.classList.toggle("toggle"); }); }; nav();