From bb15002a38e82d6c42a4f5943b076b043e6219b1 Mon Sep 17 00:00:00 2001 From: leca Date: Tue, 5 Dec 2023 03:17:38 +0300 Subject: [PATCH] Spiral is now infinite --- view/controls.js | 117 +++++++++++++++++++++++++----------- view/graphics.js | 150 ++++++++++++++++++++++++++++------------------- view/spiral.js | 10 ++-- 3 files changed, 179 insertions(+), 98 deletions(-) diff --git a/view/controls.js b/view/controls.js index 6e7afa3..183b4eb 100644 --- a/view/controls.js +++ b/view/controls.js @@ -1,46 +1,93 @@ -import { Euler, MathUtils, Quaternion, Vector3 } from "three"; -import { getDistance, setDistance, getCameraPosition, setCameraPostion, rotateCamera, getCanvasSize, getCameraRotation, getCameraQuaternion } from "./graphics.js"; +import * as THREE from "three"; let isMousePressed = false -let angle = 0; +export class SpiralCamera { + constructor(canvas, segmentHeight) { + // this.camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); + this.camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); + this.angle = 0; + this.distance = 5; + this.canvas = canvas + this.offset = 0; + this.segmentHeight = segmentHeight; + this.viewingYear = new Date().getFullYear(); -const updateCameraPosition = (horizontal, vertical) => { - let ratio = 4 * Math.PI / getCanvasSize().width; - let distance = getDistance(); + console.log(this.canvas) - let alpha = (360 * (horizontal * ratio / (2 * Math.PI))) ; - let betta = MathUtils.degToRad(angle); - let x = Math.cos(betta) * distance; - let z = Math.sin(betta) * distance; + this.camera.position.z = this.distance; + + addEventListener('mousedown', (event) => { + if (event.button == 0) { + isMousePressed = true; + } + }); + + addEventListener('mouseup', (event) => { + if (event.button == 0) { + isMousePressed = false; + } + }); + + addEventListener('mousemove', (event) => { + if (isMousePressed) { + let horizontal = event.movementX; + let vertical = event.movementY; + this.updateCameraPosition(horizontal, vertical); + } + }); + + addEventListener('wheel', (event) => { + this.distance += this.distance / (event.deltaY / 60); + this.updateCameraPosition(0, 0); + }); + + this.changedViewingYear = new CustomEvent("changedViewYear", {}); + } + + updateCameraPosition = (horizontal, vertical) => { + let ratio = 4 * Math.PI / this.canvas.width; + + let alpha = (360 * (horizontal * ratio / (2 * Math.PI))); + let betta = THREE.MathUtils.degToRad(this.angle); + + let z = Math.sin(betta) * this.distance; + let x = Math.cos(betta) * this.distance; + + + this.offset -= vertical * ratio + if (this.offset > this.segmentHeight) { + this.offset = 0; + this.viewingYear--; + dispatchEvent(this.changedViewingYear) + } + if (this.offset < 0) { + this.offset = this.segmentHeight; + this.viewingYear++; + dispatchEvent(this.changedViewingYear) + } + + this.camera.position.x = x; + this.camera.position.z = z; + + this.angle += alpha; + }; + + getCamera = () => { + return this.camera; + }; + + getOffset = () => { + return this.offset; + }; + + getViewingYear = () => { + return this.viewingYear; + }; - setCameraPostion(x, undefined, z); - angle += alpha; } -addEventListener('mousedown', (event) => { - if (event.button == 0) { - isMousePressed = true; - } -}); -addEventListener('mouseup', (event) => { - if (event.button == 0) { - isMousePressed = false; - } -}); -addEventListener('mousemove', (event) => { - if (isMousePressed) { - let horizontal = event.movementX; - let vertical = event.movementY; - updateCameraPosition(horizontal, vertical); - } -}); -addEventListener('wheel', (event) => { - let d = getDistance(); - console.log(d + d / (event.deltaY/60)) - setDistance(d + d / (event.deltaY/60)); - updateCameraPosition(0, 0); -}) \ No newline at end of file + diff --git a/view/graphics.js b/view/graphics.js index 99338e4..eed67b9 100644 --- a/view/graphics.js +++ b/view/graphics.js @@ -1,96 +1,123 @@ import * as THREE from 'three'; import { SpiralSegment } from './spiral.js'; +import { SpiralCamera } from './controls.js'; +import { TextGeometry } from 'three/addons/geometries/TextGeometry.js'; +import { FontLoader } from 'three/addons/loaders/FontLoader.js'; -const spiralHeight = 2; +const segmentHeight = 2; -let spiralMaterial = new THREE.MeshPhongMaterial({color: 0xffffff}); +let spiralMaterial = new THREE.MeshPhongMaterial({ color: 0x0f0f0f }); let distance = 5; const scene = new THREE.Scene(); var canvas = document.querySelector('#canvas'); const renderer = new THREE.WebGLRenderer({ antialias: true, canvas }); -document.body.appendChild( renderer.domElement ); +document.body.appendChild(renderer.domElement); -const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); -camera.position.z = distance; +const camera = (new SpiralCamera(canvas, segmentHeight)); // setting light -const pointLight = new THREE.PointLight( 0xffffff, 1); -pointLight.position.set( 0, 0, 1 ); +const pointLight = new THREE.PointLight(0xffffff, 1); +pointLight.position.set(0, 0, 1); const ambientLight = new THREE.AmbientLight(0xffffff, 10); scene.add(pointLight); scene.add(ambientLight); -let segments = [] +let segments = []; +let viewingYear = new Date().getFullYear(); +let viewDistance = 5; +let verticalOffset = 0; +let switched = true; -for (let i = 0; i < 40; i ++) { +// for (let i = 0; i < 40; i ++) { +// let color = `#${(Math.floor(Math.random() * 16777215)).toString(16)}`; +// let material = new THREE.MeshPhongMaterial({color: color}); +// segments.push(new SpiralSegment(0, i - 20, spiralHeight, material).getSegment()); +// scene.add(segments[i]); +// } + + +// let text = document.createElement('div'); +// text.style.position = 'absolute' +// text.style.width = 100 +// text.style.height = 100 +// text.style.color = "white" +// text.innerHTML = "test" +// text.style.top = 200 + 'px' +// text.style.left = 200 + 'px' +// document.body.appendChild(text) + + + +// const loader = new FontLoader(); + +// loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) { + +// const geometry = new TextGeometry('Hello three.js!', { +// font: font, +// size: 80, +// height: 5, +// curveSegments: 12, +// bevelEnabled: true, +// bevelThickness: 10, +// bevelSize: 8, +// bevelOffset: 0, +// bevelSegments: 5 +// }); + +// const textmesh = new THREE.Mesh(geometry, spiralMaterial); +// // textmesh.scale = new THREE.Vector3(2, 2, 2) +// scene.add(textmesh) +// } ); + +for (let i = 0; i < viewDistance * 2 + 1; i++) { let color = `#${(Math.floor(Math.random() * 16777215)).toString(16)}`; - let material = new THREE.MeshPhongMaterial({color: color}); - segments.push(new SpiralSegment(i - 20, spiralHeight, material).getSegment()); - scene.add(segments[i]); + let material = new THREE.MeshPhongMaterial({ color: color }); + segments.push(new SpiralSegment(viewingYear - viewDistance + i, segmentHeight, material)); + scene.add(segments[i].getSegment()); } -export const rotateCamera = (x, y) => { - camera.rotateX(THREE.MathUtils.degToRad(x)) - camera.rotateY(THREE.MathUtils.degToRad(y)) - console.log(`Rotating camera by (${x};${y})`) -} +addEventListener("changedViewYear", (e) => { + let color = `#${(Math.floor(Math.random() * 16777215)).toString(16)}`; + let material = new THREE.MeshPhongMaterial({ color: color }); + let newYear = camera.getViewingYear(); -export const getCameraRotation = () => { - return camera.rotation -} + if (newYear > viewingYear) { // + + scene.remove(segments[0].getSegment()) + for (let i = 0; i < segments.length; i++) { + if (i < segments.length - 1) segments[i] = segments[i + 1] + else segments[i] = new SpiralSegment(newYear + viewDistance, segmentHeight, material); + } + scene.add(segments[segments.length - 1].getSegment()); + } else { + scene.remove(segments[segments.length - 1].getSegment()) + segments.pop(); + segments.unshift(new SpiralSegment(newYear - viewDistance, segmentHeight, material)) + scene.add(segments[0].getSegment()); + } -export const getCameraQuaternion = () => { - return camera.quaternion -} + viewingYear = newYear; +}); -export const getCameraPosition = () => { - return camera.position -} - -export const setCameraPostion = (x, y ,z) => { - if (x != undefined) camera.position.x = x; - if (y != undefined) camera.position.y = y; - if (z != undefined) camera.position.z = z; - console.log(`Setting camera position to (${x};${y};${z})`) -} - -export const getCanvasSize = () => { - return {width: canvas.width, height: canvas.height} -} - -export const getDistance = () => { - return distance -} - -export const setDistance = (d) => { - distance = d; -} - -// console.log((THREE.MathUtils.radToDeg(camera.rotation._y))); -// camera.rotateY(THREE.MathUtils.degToRad(90)); -// console.log((THREE.MathUtils.radToDeg(camera.rotation._y))); -// camera.rotateY(THREE.MathUtils.degToRad(90)); -// console.log((THREE.MathUtils.radToDeg(camera.rotation._y))); -// camera.rotateY(THREE.MathUtils.degToRad(90)); -// console.log((THREE.MathUtils.radToDeg(camera.rotation._y))); -// camera.rotateY(THREE.MathUtils.degToRad(90)); -// console.log((THREE.MathUtils.radToDeg(camera.rotation._y))); //main loop function animate() { if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; - camera.aspect = canvas.clientWidth / canvas.clientHeight; - camera.updateProjectionMatrix(); + camera.getCamera().aspect = canvas.clientWidth / canvas.clientHeight; + camera.getCamera().updateProjectionMatrix(); } - camera.lookAt(0, 0, 0); + for (let i = 0; i < segments.length; i++) { + segments[i].getSegment().position.y = ((segments[i].year - camera.getViewingYear()) * segmentHeight + camera.getOffset()); + } - renderer.render(scene, camera); + camera.getCamera().lookAt(0, 0, 0); + + renderer.render(scene, camera.getCamera()); requestAnimationFrame(animate); } @@ -106,4 +133,9 @@ function resizeRendererToDisplaySize(renderer) { return needResize; } +const rebuildSpiral = () => { + segments = []; + +} + animate(); \ No newline at end of file diff --git a/view/spiral.js b/view/spiral.js index 397ddf0..bf8053d 100644 --- a/view/spiral.js +++ b/view/spiral.js @@ -17,11 +17,13 @@ export const calculateGeometry = (spiralHeight) => { return new THREE.TubeGeometry(curve, 400, 0.1, 400, false); } +const geom = calculateGeometry(2) + export class SpiralSegment { - constructor(number, height, material) { - this.number = number; - this.segment = new THREE.Mesh(calculateGeometry(height), material); - this.segment.position.y += number * height; + constructor(year, height, material) { + this.year = year; + this.segment = new THREE.Mesh(geom, material); + // this.segment.position.y += number * height; } getSegment() {