Skip to content

Commit

Permalink
Add full project code and improve structure
Browse files Browse the repository at this point in the history
- Implement Three.js wireframe wormhole
- Add camera and orbit controls
- Incorporate post-processing effects (Bloom, RenderPass)
- Create spline and tube geometry for wormhole
- Add animated boxes along the spline
- Include detailed comments and code documentation
  • Loading branch information
dhrypt committed Jun 23, 2024
1 parent 93c2c41 commit 970a28f
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
25 changes: 25 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fly through a Wireframe Wormhole</title>
<style>
body {
margin: 0;
overflow: hidden; /* Prevents scrollbars */
}
</style>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"jsm/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
}
}
</script>
</head>
<body>
<script type="module" src="index.js"></script>
</body>
</html>
101 changes: 101 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as THREE from "three";
import { OrbitControls } from "jsm/controls/OrbitControls.js";
import spline from "./spline.js";
import { EffectComposer } from "jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "jsm/postprocessing/RenderPass.js";
import { UnrealBloomPass } from "jsm/postprocessing/UnrealBloomPass.js";

// Set up scene, camera, and renderer
const w = window.innerWidth;
const h = window.innerHeight;
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.3);
const camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(w, h);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputColorSpace = THREE.SRGBColorSpace;
document.body.appendChild(renderer.domElement);

// Set up orbit controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.03;

// Post-processing setup
const renderScene = new RenderPass(scene, camera);
const bloomPass = new UnrealBloomPass(new THREE.Vector2(w, h), 1.5, 0.4, 100);
bloomPass.threshold = 0.002;
bloomPass.strength = 3.5;
bloomPass.radius = 0;
const composer = new EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(bloomPass);

// Create tube geometry from the spline
const tubeGeo = new THREE.TubeGeometry(spline, 222, 0.65, 16, true);

// Create edges geometry for the tube
const edges = new THREE.EdgesGeometry(tubeGeo, 0.2);
const lineMat = new THREE.LineBasicMaterial({ color: 0xff0000 });
const tubeLines = new THREE.LineSegments(edges, lineMat);
scene.add(tubeLines);

// Create and position boxes along the spline
const numBoxes = 55;
const size = 0.075;
const boxGeo = new THREE.BoxGeometry(size, size, size);
for (let i = 0; i < numBoxes; i += 1) {
const boxMat = new THREE.MeshBasicMaterial({
color: 0xffffff,
wireframe: true,
});
const box = new THREE.Mesh(boxGeo, boxMat);
const p = (i / numBoxes + Math.random() * 0.1) % 1;
const pos = tubeGeo.parameters.path.getPointAt(p);
pos.x += Math.random() - 0.4;
pos.z += Math.random() - 0.4;
box.position.copy(pos);
const rote = new THREE.Vector3(
Math.random() * Math.PI,
Math.random() * Math.PI,
Math.random() * Math.PI
);
box.rotation.set(rote.x, rote.y, rote.z);
const edges = new THREE.EdgesGeometry(boxGeo, 0.2);
const color = new THREE.Color().setHSL(0.7 - p, 1, 0.5);
const lineMat = new THREE.LineBasicMaterial({ color });
const boxLines = new THREE.LineSegments(edges, lineMat);
boxLines.position.copy(pos);
boxLines.rotation.set(rote.x, rote.y, rote.z);
scene.add(boxLines);
}

// Function to update camera position and direction
function updateCamera(t) {
const time = t * 0.1;
const looptime = 10 * 1000;
const p = (time % looptime) / looptime;
const pos = tubeGeo.parameters.path.getPointAt(p);
const lookAt = tubeGeo.parameters.path.getPointAt((p + 0.03) % 1);
camera.position.copy(pos);
camera.lookAt(lookAt);
}

// Animation loop
function animate(t = 0) {
requestAnimationFrame(animate);
updateCamera(t);
composer.render(scene, camera);
controls.update();
}
animate();

// Handle window resize
function handleWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener("resize", handleWindowResize, false);
56 changes: 56 additions & 0 deletions spline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as THREE from "three";

// Curve path data
const curvePath = [
10.136184463414924, -1.374508746897471, 10.384881573913269,
9.1152593889854714, -1.374508746897471, 8.5846792797570011,
9.0669355709754882, -1.0665123466336568, 5.8937771631608156,
10.151040177840205, -0.65913653144937956, 3.4340491740541346,
10.806779203170416, 1.8859391007298545, 0.46855774212986023,
10.761433540147586, 2.8724172201359197, -1.2811838605587311,
9.6195923104445065, 2.8724172201359197, -3.2833099941904766,
6.9763020889151646, 2.7659257976905427, -4.7591958908830172,
6.0461277891353697, 1.0727045302089879, -6.6638740164090482,
7.3472235778544794, -1.8228856326635698, -9.0685043046185623,
7.226367212900791, -1.8228856326635698, -10.499536640855691,
5.8354566696263914, -1.8228856326635698, -12.039219379199908,
3.6532357452141353, -0.20463983570573391, -13.87695442281038,
-0.30169589630131455, 1.5965000671484342, -14.879986418947327,
-2.8925694230502157, 2.2971364614427481, -13.892095587598131,
-4.537672295357936, 4.5863515759659208, -12.140831652074551,
-6.1287913464117594, 5.9653814634119815, -8.9776527318875896,
-6.0120301606452813, 4.4081161943855998, -6.712084358394045,
-5.2138252159038974, 2.820894808418279, -4.4532820412085607,
-2.3424712835109611, 2.2032065005086259, -3.0788773693500198,
-0.0076956453915433265, 1.8931797788880202, -1.6577070662471063,
-0.24767503988481437, 2.8845808465856684, 0.073915859214221724,
-2.2174044353598896, 4.2415524507318576, 2.215992718290742,
-3.4526531678364756, 3.0615192023340851, 4.7922404932096558,
-3.7356278971556445, 1.4054080369354316, 7.8432021841434629,
-3.4003734463804118, 1.1924069108769393, 9.2464090886227073,
-1.8851803760476225, 1.5269331003449989, 10.306083896408374,
0.01071077144031829, 2.1101821577522295, 10.490880699847727,
0.42562058195647001, 2.2759939598834387, 11.613129436580291,
0.096405262182225115, 0.032317784084054391, 16.223455375061565,
2.3458797884520433, 0.38907275257695584, 19.91188266079584,
5.7018400098488771, 1.73337964747396, 20.615481586999959, 7.9720939736751824,
1.73337964747396, 19.303399329816457, 9.8672362721095652,
0.090083018057025177, 16.893338541618121, 11.225959519544134,
-1.374508746897471, 14.279002555560753, 11.288646925965876,
-1.374508746897471, 11.926359497447137, 10.136184463414924,
-1.374508746897471, 10.384881573913269,
];

// Construct tunnel track
const points = [];
const len = curvePath.length;
for (let p = 0; p < len; p += 3) {
points.push(
new THREE.Vector3(curvePath[p], curvePath[p + 1], curvePath[p + 2])
);
}

// Create Catmull-Rom spline from the points
const spline = new THREE.CatmullRomCurve3(points);

export default spline;

0 comments on commit 970a28f

Please sign in to comment.