diff --git a/index.html b/index.html index c33902905994c7bbd66866f7810ed3200867aac7..530bc337f539a063e71e5a3e1f79d32597b92ed1 100644 --- a/index.html +++ b/index.html @@ -1,15 +1,57 @@ <!DOCTYPE html> + <html lang="en"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="favicon.svg" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <link rel="stylesheet" href="src/style.css" /> - <title>Computergrafik 3</title> - </head> - <body> - <div id="app"></div> + +<head> + <title>Computergrafik 3</title> + + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="description" content="Computergrafik 3" /> + + <link rel="stylesheet" href="src/style.css" /> + <link rel="icon" type="image/svg+xml" href="favicon.svg" /> + + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap" rel="stylesheet"> +</head> + +<body> + + <div class="scene deactived"> <canvas id="canvas"></canvas> - <script type="module" src="/src/main.ts"></script> - </body> -</html> + </div> + + <div class="main"> + <canvas class="welcome" id="preview"></canvas> + + <nav class="menu"> + + <header> + <h2 class="title-nav">Menu</h2> + </header> + + <ul> + <li><a class="nav-link active-link" href="index.html">Home</a></li> + <li><a class="nav-link" id="bezier"> Bézier Curves </a></li> + <li><a class="nav-link" id="quaternion"> Quaternions </a></li> + <li><a class="nav-link" id="simulation"> Simulation </a></li> + </ul> + + <footer> + <p> + To return to the home page, simply refresh the page. + </p> + </footer> + + + + </nav> + </div> + + + <script type="module" src="/src/init.ts"></script> +</body> + +</html> \ No newline at end of file diff --git a/quaternions.html b/quaternions.html deleted file mode 100644 index a92a91d854a3581bf3b6b99b6c47d338b4a2fbfc..0000000000000000000000000000000000000000 --- a/quaternions.html +++ /dev/null @@ -1,14 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="favicon.svg" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>Computergrafik 3</title> - </head> - <body> - <div id="app"></div> - <canvas id="canvas"></canvas> - <script type="module" src="/src/main.ts"></script> - </body> -</html> diff --git a/src/ambient/RotatingCube.ts b/src/ambient/RotatingCube.ts new file mode 100644 index 0000000000000000000000000000000000000000..893e6b1087f98305fbac1119cedfef3a7287fdc0 --- /dev/null +++ b/src/ambient/RotatingCube.ts @@ -0,0 +1,56 @@ +import * as THREE from 'three'; + +let scene: THREE.Scene, camera: THREE.PerspectiveCamera, renderer: THREE.Renderer, cube: THREE.Mesh; + +const speed = 0.01; + +let WIDTH = window.innerWidth * 0.8; +let HEIGHT = window.innerHeight * 0.50; + +function initCamera() { + camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 10); + camera.position.set(0, 3.5, 5); + camera.lookAt(scene.position); +} + +function initRenderer() { + const target = document.querySelector("#preview") as HTMLCanvasElement; + renderer = new THREE.WebGLRenderer({ canvas: target, antialias: true, alpha: true }); + renderer.setSize(WIDTH, HEIGHT); + + window.addEventListener("resize", () => { + WIDTH = window.innerWidth * 0.8; + HEIGHT = window.innerHeight * 0.50; + renderer.setSize(WIDTH, HEIGHT); + camera.aspect = WIDTH / HEIGHT; + camera.updateProjectionMatrix(); + }); + +} + +function initCube() { + cube = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial( + { wireframe: true, color: 0x000000 })); + scene.add(cube); +} + +function rotateCube() { + cube.rotation.x += speed; + cube.rotation.y += speed; + cube.rotation.z += speed; +} + +export function init() { + scene = new THREE.Scene(); + initCamera(); + initRenderer(); + initCube(); +} + +export function render() { + requestAnimationFrame(render); + rotateCube(); + renderer.render(scene, camera); +} + + diff --git a/src/bezier/BezierDemo.ts b/src/bezier/BezierDemo.ts new file mode 100644 index 0000000000000000000000000000000000000000..b2b4905d16a9a3f7c9c5f2fc50af47ea736a8d97 --- /dev/null +++ b/src/bezier/BezierDemo.ts @@ -0,0 +1,10 @@ +import { RenderManager } from "../uitls/Rendering"; +import { UI } from "../uitls/UI"; + +import { Curve2d } from './Curve2d'; + +export function bezierDemo(render: RenderManager, ui: UI) { + const curve = new Curve2d(); + curve.objects().forEach(obj => { render.add(obj); }); + ui.addModifiable(curve); +} \ No newline at end of file diff --git a/src/init.ts b/src/init.ts new file mode 100644 index 0000000000000000000000000000000000000000..f0c79c7d5752259c6c533ffd781e3e6959941189 --- /dev/null +++ b/src/init.ts @@ -0,0 +1,38 @@ +import * as RotCube from "./ambient/RotatingCube" +import * as Main from "./main" + + +function init() { + const sceneElement = document.querySelector(".scene") as HTMLAnchorElement; + const mainElement = document.querySelector(".main") as HTMLAnchorElement; + + const bezierLink = document.querySelector("#bezier") as HTMLAnchorElement; + const quaternionLink = document.querySelector("#quaternion") as HTMLAnchorElement; + const simulationLink = document.querySelector("#simulation") as HTMLAnchorElement; + + bezierLink.addEventListener("click", () => { + sceneElement.classList.remove("hidden"); + mainElement.classList.add("hidden"); + Main.demos(Main.examples["bezier"]); + }); + + quaternionLink.addEventListener("click", () => { + sceneElement.classList.remove("hidden"); + mainElement.classList.add("hidden"); + Main.demos(Main.examples["quaternion"]); + }); + + simulationLink.addEventListener("click", () => { + sceneElement.classList.add("hidden"); + mainElement.classList.remove("hidden"); + // TODO: add simulation + }); + + + RotCube.init(); + RotCube.render(); +} + +init(); + +export { }; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 7e7c37fa07be70df93c35b7eea518d92825daf76..824547cba33a0b21f7f438b5932c808ddf7bb0f9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,71 +1,25 @@ -import { AmbientLight, GridHelper, Mesh, MeshLambertMaterial, PointLight } from "three"; -import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader"; -import { RotationObject } from "./quaternion/RotationObject"; -import { Curve2d } from "./bezier/Curve2d"; +import { RenderManager } from "./uitls/Rendering"; import { UI } from "./uitls/UI"; -import * as CG from "./uitls/Rendering"; +import { bezierDemo } from "./bezier/BezierDemo"; +import { quaternionDemo } from "./quaternion/QuaternionDemo"; +export const examples : {[key: string]: (render: RenderManager, ui: UI) => void} = { + "bezier": bezierDemo, + "quaternion": quaternionDemo +}; -function demo1(render: CG.RenderManager, ui: UI) { - const curve = new Curve2d(); - curve.objects().forEach(obj => { render.add(obj); }); - ui.addModifiable(curve); -} - -function demo2(render: CG.RenderManager, ui: UI) { - - const rot = new RotationObject(); - - const grid = new GridHelper(10,10); - grid.renderOrder = -1 - - render.add(grid) - - const loader = new OBJLoader(); - loader.setPath("models/"); - loader.load( - "Arrow.obj", - function (obj) { - let tmp = obj.children[0] as Mesh; - tmp.material = new MeshLambertMaterial({ wireframe: false, color: 0xaaaaaa }); - rot.setMesh(tmp); - render.add(tmp); - } - ) - - const ambient = new AmbientLight(0x404040); - render.add(ambient); +export function demos(d: (render: RenderManager, ui: UI) => void) { - const plightx = new PointLight(0xffffff, 1, 100); - plightx.position.set(5, 0, 0); - render.add(plightx); + console.log("demos"); - const plighty = new PointLight(0xffffff, 1, 100); - plighty.position.set(0, 5, 0); - render.add(plighty); + const ui = new UI(); + const render = new RenderManager('#canvas', { near: 0.01, far: 1000, fov: 45, height: 1 }); + ui.addModifiable(render); - const plightz = new PointLight(0xffffff, 1, 100); - plightz.position.set(0, 0, 5); - render.add(plightz); - - rot.objects().forEach(obj => { - render.add(obj); - }); + d(render, ui); render.render(); - ui.addModifiable(rot); } -const ui = new UI(); -const render = new CG.RenderManager('#canvas', { near: 0.01, far: 1000, fov: 45, height: 1 }); -ui.addModifiable(render); - -demo1(render, ui); -// demo2(render, ui); - - -render.render(); - - diff --git a/src/quaternion/QuaternionDemo.ts b/src/quaternion/QuaternionDemo.ts new file mode 100644 index 0000000000000000000000000000000000000000..d63194a1cff3007c1ec788ddd2d8622ea547933d --- /dev/null +++ b/src/quaternion/QuaternionDemo.ts @@ -0,0 +1,50 @@ +import { RenderManager } from "../uitls/Rendering"; +import { UI } from "../uitls/UI"; + +import { AmbientLight, GridHelper, Mesh, MeshLambertMaterial, PointLight } from "three"; +import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader"; +import { RotationObject } from "./RotationObject"; + +export function quaternionDemo(render: RenderManager, ui: UI) { + + const rot = new RotationObject(); + + const grid = new GridHelper(10,10); + grid.renderOrder = -1 + + render.add(grid) + + const loader = new OBJLoader(); + loader.setPath("models/"); + loader.load( + "Arrow.obj", + function (obj) { + let tmp = obj.children[0] as Mesh; + tmp.material = new MeshLambertMaterial({ wireframe: false, color: 0xaaaaaa }); + rot.setMesh(tmp); + render.add(tmp); + } + ) + + const ambient = new AmbientLight(0x404040); + render.add(ambient); + + const plightx = new PointLight(0xffffff, 1, 100); + plightx.position.set(5, 0, 0); + render.add(plightx); + + const plighty = new PointLight(0xffffff, 1, 100); + plighty.position.set(0, 5, 0); + render.add(plighty); + + const plightz = new PointLight(0xffffff, 1, 100); + plightz.position.set(0, 0, 5); + render.add(plightz); + + rot.objects().forEach(obj => { + render.add(obj); + }); + + render.render(); + ui.addModifiable(rot); +} \ No newline at end of file diff --git a/src/style.css b/src/style.css index 05fddd8df691161550f2a5e243a33b02907411f5..5f489db055f6a4452e32eafb52e33a102fb14aac 100644 --- a/src/style.css +++ b/src/style.css @@ -1,3 +1,145 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; +} + +.main.hidden { + display: none; +} + +.scene.hidden { + display: none; +} + +.return { + position: absolute; + top: 1em; + left: 1em; + background: #fff; + z-index: 1; +} + +header { + position: relative; + width: 100%; + height: 6rem; +} + +footer { + position: absolute; + bottom: 0; + left: 12%; + width: 80%; + height: 6rem; + color: #CBCFD3; + font-size: .8em; + display: flex; + justify-content: space-between; + align-items: center; +} + +.welcome { + position: relative; + top: 25vh; + left: 20%; + font-size: 1rem; +} + +.sub { + color: #CBCFD3; +} + +/* MENU */ + +nav { + position: fixed; + width: 25%; + height: 100vh; + left: 0; + top: 0; + background-color: #1e1e1e; + transition: 0.2s; + /* z-index: 1; */ +} + +.title-nav { + position: absolute; + color: white; + bottom: 0; + left: 12%; +} + +nav ul { + position: absolute; + left: 12%; + top: 20%; + height: 55%; + list-style: none; + display: flex; + flex-direction: column; + justify-content: space-around; + +} + +.nav-link { + position: relative; + color: #CBCFD3; + left: 0; + text-decoration: none; + font-size: 1.25rem; + letter-spacing: 0.25rem; + transition: 0.2s; +} + +.nav-link:hover { + color: white; + left: 10%; + transition: 0.5s; + cursor: pointer; +} + +.active-link { + color: white; + font-weight: bold; +} + +.menu-close { + position: absolute; + top: 45vh; + left: 2%; + width: 2rem; + height: 1rem; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: space-around; +} + +.menu-close:hover { + opacity: 0.6; +} + +.menu-close span { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 70%; + height: 2px; + background-color: white; +} + +.menu-close span:nth-child(1) { + transform: translate(-50%, -50%) rotate(45deg); +} + +.menu-close span:nth-child(2) { + transform: translate(-50%, -50%) rotate(-45deg); +} + + canvas { left: 0; top: 0; diff --git a/src/uitls/globals.ts b/src/uitls/globals.ts index 146b3594ad79730b9be0d1778d63fa632f42b254..8b2545bbfbe4e925bea973a7e1b4be18918dd6e9 100644 --- a/src/uitls/globals.ts +++ b/src/uitls/globals.ts @@ -1,5 +1,5 @@ export const colorprime: [number, number, number] = [ - 0xF55600, // red + 0xCC0000, // red 0x5DFF70, // green 0x123FB3 // blue ] diff --git a/src/uitls/rendering.ts b/src/uitls/rendering.ts index 4f6f30f2c91ebef43c744b50204b41eadb74c721..7183b023ac6852bfc871fa9e2afc7b241a14aad6 100644 --- a/src/uitls/rendering.ts +++ b/src/uitls/rendering.ts @@ -20,11 +20,9 @@ class CameraManager { constructor(settings: CameraSettings) { const aspect = window.innerWidth / window.innerHeight; - const s = 3; - this.cameras = [ new PerspectiveCamera(settings.fov, aspect, settings.near, settings.far), - new OrthographicCamera(-aspect * s, aspect * s, 1 * s, -1 * s, settings.near, settings.far) + new OrthographicCamera(-aspect, aspect, 1, -1, settings.near, settings.far) ]; this.active = this.cameras[1]; @@ -71,6 +69,20 @@ export class RenderManager implements Modifiable { this._cameraManager = new CameraManager(settings); this._controls = new OrbitControls(this._cameraManager.camera(), this._renderer.domElement); this._scene = new Scene(); + + window.addEventListener('resize', () => { + this._renderer.setSize(window.innerWidth, window.innerHeight); + let cam = this._cameraManager.camera(); + if (cam instanceof PerspectiveCamera) { + cam.aspect = window.innerWidth / window.innerHeight; + cam.updateProjectionMatrix(); + } else if (cam instanceof OrthographicCamera) { + const aspect = window.innerWidth / window.innerHeight; + cam.left = -aspect; + cam.right = aspect; + cam.updateProjectionMatrix(); + } + }) } @@ -138,6 +150,7 @@ export class RenderManager implements Modifiable { }); } + private _fps: number = 60; private _controls: OrbitControls; private _cameraManager: CameraManager;