Files
TunnelProofOfConcept/src/index.js
2023-12-14 15:25:30 +01:00

162 lines
4.5 KiB
JavaScript

// inspiration from Etienne Jacob
// https://www.thisiscolossal.com/wp-content/uploads/2018/12/agifcolossaltd2opt.gif
import "./styles.css";
import * as THREE from "three";
// import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import vertex from "./shaders/vertex.glsl";
import fragment from "./shaders/fragment.glsl";
import txt from "./123.png";
let timer = 0;
let mouseIsDown = false;
export default class Sketch {
constructor(options) {
this.clock = new THREE.Clock();
this.time = 0;
this.container = options.domElement;
this.height = this.container.offsetHeight;
this.width = this.container.offsetWidth;
this.camera = new THREE.PerspectiveCamera(
75,
this.width / this.height,
0.1,
1000
);
this.camera.position.set(0, 0, 10);
this.scene = new THREE.Scene();
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setPixelRatio(window.devicePixelRatio * 2);
this.container.appendChild(this.renderer.domElement);
// this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.normal = new THREE.Vector3();
this.binormal = new THREE.Vector3();
this.resize();
this.addObjects();
this.render();
this.setUpResize();
}
addObjects() {
const texture = new THREE.TextureLoader().load(txt, (texture) => {
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
});
this.material = new THREE.ShaderMaterial({
side: THREE.DoubleSide,
// transparent:true,
// wireframe: true,
uniforms: {
time: { type: "f", value: 0 },
uResolution: { type: "v4", value: new THREE.Vector4() },
u_texture: { type: "t", value: texture }
},
vertexShader: vertex,
fragmentShader: fragment
});
class CustomSinCurve extends THREE.Curve {
constructor(scale = 1) {
super();
this.scale = scale;
}
getPoint(t, optionalTarget = new THREE.Vector3()) {
const tx = Math.cos(2 * Math.PI * t);
const ty = Math.sin(2 * Math.PI * t);
const tz = 0.1 * Math.sin(8 * Math.PI * t);
return optionalTarget.set(tx, ty, tz).multiplyScalar(this.scale);
}
}
const path = new CustomSinCurve(10);
this.geometry = new THREE.TubeGeometry(path, 200, 0.5, 20, false);
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.scene.add(this.mesh);
}
render() {
this.time = timer;
// https://threejs.org/examples/webgl_geometry_extrude_splines.html
let looptime = 10 * 1000;
let t = (this.time % looptime) / looptime;
let pos = this.geometry.parameters.path.getPointAt(t);
let segments = this.geometry.tangents.length;
let pickt = t * segments;
let pick = Math.floor(pickt);
let pickNext = (pick + 1) % segments;
this.binormal.subVectors(
this.geometry.binormals[pickNext],
this.geometry.binormals[pick]
);
this.binormal
.multiplyScalar(pickt - pick)
.add(this.geometry.binormals[pick]);
let dir = this.geometry.parameters.path.getTangentAt(t);
let offset = 0;
this.normal.copy(this.binormal).cross(dir);
pos.add(this.normal.clone().multiplyScalar(offset));
this.camera.position.copy(pos);
let lookAt = this.geometry.parameters.path.getPointAt(
(t + 1 / this.geometry.parameters.path.getLength()) % 1
);
this.camera.matrix.lookAt(this.camera.position, lookAt, this.normal);
this.camera.rotation.setFromRotationMatrix(
this.camera.matrix,
this.camera.rotation.order
);
this.material.uniforms.time.value = this.clock.getElapsedTime();
requestAnimationFrame(this.render.bind(this));
this.renderer.render(this.scene, this.camera);
}
resize() {
this.width = this.container.offsetWidth;
this.height = this.container.offsetHeight;
this.renderer.setSize(this.width, this.height);
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
}
setUpResize() {
window.addEventListener("resize", this.resize.bind(this));
}
}
new Sketch({
domElement: document.getElementById("container")
});
window.addEventListener("mousedown", function (e) {
mouseIsDown = true;
});
window.addEventListener("mouseup", function (e) {
mouseIsDown = false;
});
window.addEventListener("mousemove", function (e) {
if (mouseIsDown) {
timer += ((e.clientY / window.innerHeight) * 2 - 1) * 10;
}
if (timer <= 0) {
timer = 0;
}
});
setInterval(() => {
timer += 1
}, 10)