spiral_calendar/view/graphics.js

170 lines
5.3 KiB
JavaScript
Raw Normal View History

2023-11-30 16:19:45 +03:00
import * as THREE from 'three';
2023-11-30 19:31:13 +03:00
import { SpiralSegment } from './spiral.js';
2023-12-05 03:17:38 +03:00
import { SpiralCamera } from './controls.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
2023-11-30 16:19:45 +03:00
2024-02-02 01:31:36 +03:00
2024-01-29 00:57:46 +03:00
const spiralMaterial = new THREE.ShaderMaterial( {
uniforms: {
time: { value: 1.0 },
resolution: { value: new THREE.Vector2() },
position: new THREE.Vector3()
},
// vertexShader: document.getElementById( 'vertexShader' ).textContent,
// fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
vertexShader: `
const float PI = 3.14159;
varying vec4 v_color;
varying float deg;
void main() {
deg = degrees(atan(position.z, position.x)) ;
if (deg <= 0.) deg = 360. + deg;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, position.z, 1.0);
}
`,
fragmentShader: `
const float PI = 3.14159;
varying vec4 v_color;
varying float deg;
varying float toDiscard;
vec4 colors[12] = vec4[12](
vec4(0.202, 0.2406, 0.5922, 1), // jan
vec4(0.0980, 0.4627, 0.8235, 1), // feb
vec4(0.3984, 0.7305, 0.4141, 1), // mar
vec4(0.2188, 0.5547, 0.2344, 1), // apr
vec4(27./256., 94./256., 32./256., 1), // may
vec4(205./256., 220./256., 57./256., 1), // jun
vec4(255./256., 238./256., 88./256., 1), // jul
vec4(251./256., 192./256., 45./256., 1), // aug
vec4(255./256., 160./256., 0, 1), // sep
vec4(245./256., 124./256., 0, 1), // oct
vec4(230./256., 74./256., 25./256., 1), // nov
vec4(144./256., 164./256., 174./256., 1) // dec
);
void main() {
if (int(round(deg)) % 30 == 0) discard;
int month = int((deg / 30.));
vec4 color = mix(colors[month], colors[month + 1], (deg - float(month) * 30.) / 30.);
gl_FragColor = color;
}
`
2024-01-29 00:57:46 +03:00
} );
2023-11-30 16:19:45 +03:00
const segmentHeight = 2;
let segments = [];
let viewingYear = new Date().getFullYear();
let viewDistance = 5;
//setting scene
2023-11-30 16:19:45 +03:00
const scene = new THREE.Scene();
2024-02-02 01:31:36 +03:00
const loader = new THREE.TextureLoader();
const texture = loader.load(
'view/img/space.jpg',
() => {
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.colorSpace = THREE.SRGBColorSpace;
scene.background = texture;
});
//setting canvas
2023-11-30 16:19:45 +03:00
var canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
2023-12-05 03:17:38 +03:00
document.body.appendChild(renderer.domElement);
2023-11-30 16:19:45 +03:00
//setting camera
2023-12-05 03:17:38 +03:00
const camera = (new SpiralCamera(canvas, segmentHeight));
2023-11-30 16:19:45 +03:00
// setting light
2023-12-05 03:17:38 +03:00
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(0, 0, 1);
2023-11-30 16:19:45 +03:00
const ambientLight = new THREE.AmbientLight(0xffffff, 10);
scene.add(pointLight);
scene.add(ambientLight);
//Creating first segments
2023-12-05 03:17:38 +03:00
for (let i = 0; i < viewDistance * 2 + 1; i++) {
segments.push(new SpiralSegment(viewingYear - viewDistance + i, segmentHeight, spiralMaterial));
2023-12-05 03:17:38 +03:00
scene.add(segments[i].getSegment());
2023-12-07 12:56:12 +03:00
scene.add(segments[i].getText());
};
2024-01-24 20:03:41 +03:00
2023-12-05 03:17:38 +03:00
addEventListener("changedViewYear", (e) => {
let newYear = camera.getViewingYear();
if (newYear > viewingYear) { // +
scene.remove(segments[0].getSegment())
2023-12-07 12:56:12 +03:00
scene.remove(segments[0].getText())
2024-01-24 20:03:41 +03:00
segments.shift();
segments.push(new SpiralSegment(newYear + viewDistance, segmentHeight, spiralMaterial));
2024-01-24 20:03:41 +03:00
2023-12-05 03:17:38 +03:00
scene.add(segments[segments.length - 1].getSegment());
2023-12-07 12:56:12 +03:00
scene.add(segments[segments.length - 1].getText());
} else { // -
2023-12-05 03:17:38 +03:00
scene.remove(segments[segments.length - 1].getSegment())
2023-12-07 12:56:12 +03:00
scene.remove(segments[segments.length - 1].getText())
2024-01-24 20:03:41 +03:00
2023-12-05 03:17:38 +03:00
segments.pop();
segments.unshift(new SpiralSegment(newYear - viewDistance, segmentHeight, spiralMaterial))
2024-01-29 00:57:46 +03:00
2023-12-05 03:17:38 +03:00
scene.add(segments[0].getSegment());
2023-12-07 12:56:12 +03:00
scene.add(segments[0].getText());
2023-12-05 03:17:38 +03:00
}
2023-12-01 12:57:41 +03:00
2023-12-05 03:17:38 +03:00
viewingYear = newYear;
});
2023-12-01 12:57:41 +03:00
2024-02-02 01:31:36 +03:00
2023-11-30 16:19:45 +03:00
//main loop
function animate() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
2023-12-05 03:17:38 +03:00
camera.getCamera().aspect = canvas.clientWidth / canvas.clientHeight;
camera.getCamera().updateProjectionMatrix();
2023-11-30 16:19:45 +03:00
}
// moving text along with the camera and spiral
2023-12-05 03:17:38 +03:00
for (let i = 0; i < segments.length; i++) {
segments[i].getSegment().position.y = ((segments[i].year - camera.getViewingYear()) * segmentHeight + camera.getOffset());
2023-12-07 12:56:12 +03:00
segments[i].getText().position.y = segmentHeight / 2 +(segments[i].year - camera.getViewingYear()) * segmentHeight + camera.getOffset();
2024-01-24 20:03:41 +03:00
segments[i].getText().position.x = 2.5*Math.cos(THREE.MathUtils.degToRad(camera.getAngle() + 90)) * 3
segments[i].getText().position.z = 2.5*Math.sin(THREE.MathUtils.degToRad(camera.getAngle() + 90)) * 3
2023-12-07 12:56:12 +03:00
segments[i].getText().lookAt(camera.getCamera().position)
2023-12-05 03:17:38 +03:00
}
camera.getCamera().lookAt(0, 0, 0);
2023-12-01 12:57:41 +03:00
2023-12-05 03:17:38 +03:00
renderer.render(scene, camera.getCamera());
2023-11-30 16:19:45 +03:00
requestAnimationFrame(animate);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) renderer.setSize(width, height, false);
return needResize;
}
animate();