TA159

Notas, resueltos y trabajos practicos de la materia Sistemas Gráficos
Index Commits Files Refs Submodules README LICENSE
commit 75feec0be796b7acbaf721e0f84b7ed2ab63645e
parent 9090d438e9c1aff653fcdd14b5b4b788b4abf526
Author: Martin Klöckner <mjkloeckner@gmail.com>
Date:   Wed, 26 Jun 2024 01:30:18 -0300

add `tunnel` page

Diffstat:
Atp/assets/madera.jpg | 0
Mtp/index.html | 3++-
Atp/src/tunnel.js | 346+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atp/tunnel.html | 18++++++++++++++++++
4 files changed, 366 insertions(+), 1 deletion(-)
diff --git a/tp/assets/madera.jpg b/tp/assets/madera.jpg
Binary files differ.
diff --git a/tp/index.html b/tp/index.html
@@ -28,7 +28,8 @@
             <li><a href="terrain.html">Terreno</a></li>
             <li><a href="trees.html">Arboles</a></li>
             <li><a href="train.html">Tren</a></li>
-            <li><a href="rails.html">Vias</a></li>
+            <li><a href="rails.html">Vias y Terraplen</a></li>
+            <li><a href="tunnel.html">Tunel</a></li>
         </ul>
     </body>
 </html>
diff --git a/tp/src/tunnel.js b/tp/src/tunnel.js
@@ -0,0 +1,346 @@
+import * as THREE from 'three';
+import * as dat from 'dat.gui';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+
+import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';
+import { ParametricGeometries } from 'three/examples/jsm/geometries/ParametricGeometries.js';
+import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';
+
+let scene, camera, renderer, container, terrainMaterial, instancedTrees;
+let spherePath;
+let railsPath;
+let railsFoundationShape;
+
+const textures = {
+    tierra:     { url: '/assets/tierra.jpg', object: null },
+    roca:       { url: '/assets/roca.jpg', object: null },
+    pasto:      { url: '/assets/pasto.jpg', object: null },
+    durmientes: { url: '/assets/durmientes.jpg', object: null },
+    madera:     { url: '/assets/madera.jpg', object: null },
+};
+
+function parametricRailsFoundationInverted(u, v, target) {
+    const rotMatrix = new THREE.Matrix4();
+    const translationMatrix = new THREE.Matrix4();
+    const levelMatrix = new THREE.Matrix4();
+
+    let railsPathPos = railsPath.getPointAt(v);
+    let railsFoundationShapePos = railsFoundationShape.getPointAt(u).multiplyScalar(0.5);
+
+    let tangente = new THREE.Vector3();
+    let binormal = new THREE.Vector3();
+    let normal = new THREE.Vector3();
+
+    tangente = railsPath.getTangent(v);
+
+    tangente.normalize();
+    binormal = new THREE.Vector3(0, 1, 0);
+    normal.crossVectors(tangente, binormal);
+
+    translationMatrix.makeTranslation(railsPathPos);
+
+    rotMatrix.identity();
+    levelMatrix.identity();
+
+    levelMatrix.makeTranslation(railsPathPos);
+    rotMatrix.makeBasis(normal, tangente, binormal);
+    levelMatrix.multiply(rotMatrix);
+    railsFoundationShapePos.applyMatrix4(levelMatrix);
+    
+    const x = railsFoundationShapePos.x;
+    const y = railsFoundationShapePos.y;
+    const z = railsFoundationShapePos.z;
+    target.set(x, y, z);
+}
+
+
+function parametricRailsFoundation(u, v, target) {
+    const rotMatrix = new THREE.Matrix4();
+    const translationMatrix = new THREE.Matrix4();
+    const levelMatrix = new THREE.Matrix4();
+
+    let railsPathPos = railsPath.getPointAt(u);
+    let railsFoundationShapePos = railsFoundationShape.getPointAt(v).multiplyScalar(0.5);
+
+    let tangente = new THREE.Vector3();
+    let binormal = new THREE.Vector3();
+    let normal = new THREE.Vector3();
+
+    tangente = railsPath.getTangent(u);
+
+    tangente.normalize();
+    binormal = new THREE.Vector3(0, 1, 0);
+    normal.crossVectors(tangente, binormal);
+
+    translationMatrix.makeTranslation(railsPathPos);
+
+    rotMatrix.identity();
+    levelMatrix.identity();
+
+    levelMatrix.makeTranslation(railsPathPos);
+    rotMatrix.makeBasis(normal, tangente, binormal);
+    levelMatrix.multiply(rotMatrix);
+    railsFoundationShapePos.applyMatrix4(levelMatrix);
+    
+    const x = railsFoundationShapePos.x;
+    const y = railsFoundationShapePos.y;
+    const z = railsFoundationShapePos.z;
+    target.set(x, y, z);
+}
+
+function onResize() {
+    camera.aspect = container.offsetWidth / container.offsetHeight;
+    camera.updateProjectionMatrix();
+    renderer.setSize(container.offsetWidth, container.offsetHeight);
+}
+
+function setupThreeJs() {
+    scene = new THREE.Scene();
+    container = document.getElementById('mainContainer');
+
+    renderer = new THREE.WebGLRenderer();
+    renderer.setClearColor(0x606060);
+    container.appendChild(renderer.domElement);
+
+    camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 1000);
+    camera.position.set(-50, 60, 50);
+    camera.lookAt(0, 0, 0);
+
+    const controls = new OrbitControls(camera, renderer.domElement);
+
+    const ambientLight = new THREE.AmbientLight(0xffffff);
+    scene.add(ambientLight);
+
+    const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x000000, 0.25);
+    scene.add(hemisphereLight);
+
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+    directionalLight.position.set(100, 100, 100);
+    scene.add(directionalLight);
+
+    const gridHelper = new THREE.GridHelper(50, 20);
+    scene.add(gridHelper);
+
+    const axesHelper = new THREE.AxesHelper(5);
+    scene.add(axesHelper);
+
+    window.addEventListener('resize', onResize);
+    onResize();
+}
+
+function buildScene() {
+    console.log('Building scene');
+}
+
+function onTextureLoaded(key, texture) {
+    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
+    textures[key].object = texture;
+    console.log('Texture `' + key + '` loaded');
+}
+
+function loadTextures(callback) {
+    const loadingManager = new THREE.LoadingManager();
+
+    loadingManager.onLoad = () => {
+        console.log('All textures loaded');
+        callback();
+    };
+
+    for (const key in textures) {
+        console.log("Loading textures");
+        const loader = new THREE.TextureLoader(loadingManager);
+        const texture = textures[key];
+        texture.object = loader.load(
+            texture.url,
+            onTextureLoaded.bind(this, key),
+            null,
+            (error) => {
+                console.error(error);
+            }
+        );
+    }
+}
+
+function buildRailsFoundation() {
+    railsFoundationShape = new THREE.CatmullRomCurve3([
+        new THREE.Vector3( -2.00, 0.00, 0.00),
+        new THREE.Vector3( -1.00, 0.00, 1.00),
+        new THREE.Vector3(  0.00, 0.00, 1.15),
+        new THREE.Vector3(  1.00, 0.00, 1.00),
+        new THREE.Vector3(  2.00, 0.00, 0.00),
+    ], false);
+
+    /*
+    // show rails foundation shape
+    const points = railsFoundationShape.getPoints(50);
+    const geometry = new THREE.BufferGeometry().setFromPoints(points);
+    const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
+    const curveObject = new THREE.Line(geometry, lineMaterial);
+    scene.add(curveObject);
+    */
+
+    /*
+    const pGeometry = new ParametricGeometry(parametricRailsFoundation, 100, 10);
+    */
+    const pGeometry = new ParametricGeometry(parametricRailsFoundationInverted, 100, 100);
+    
+    textures.durmientes.object.wrapS = THREE.RepeatWrapping;
+    textures.durmientes.object.wrapT = THREE.RepeatWrapping;
+    textures.durmientes.object.repeat.set(1, 45);
+    textures.durmientes.object.anisotropy = 16;
+    // textures.durmientes.object.rotation = Math.PI/2;
+
+    /*
+    const pGeometry = new ParametricGeometry(parametricRailsFoundationInverted, 100, 100);
+
+    // load into `map` the examples texture
+    const map = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
+    map.wrapS = map.wrapT = THREE.RepeatWrapping;
+    map.repeat.set(1, 30);
+    map.anisotropy = 16;
+    // map.rotation = Math.PI/2;
+    */
+
+    const pMaterial = new THREE.MeshPhongMaterial({
+        side: THREE.DoubleSide,
+        transparent: false,
+        opacity: 1.0,
+        shininess: 10,
+        map: textures.durmientes.object
+    });
+    const pMesh = new THREE.Mesh(pGeometry, pMaterial);
+    scene.add(pMesh);
+}
+
+const railsRadius = 0.5;
+function buildRails() {
+    let railsGeometries = [];
+
+    const leftRailGeometryFunction  = getParametricRailsFunction(railsRadius,
+        new THREE.Vector3( 6, 0, railsRadius+11.25));
+
+    const rightRailGeometryFunction = getParametricRailsFunction(railsRadius,
+        new THREE.Vector3(-7, 0, railsRadius+11.25));
+
+    const leftRailGeometry  = new ParametricGeometry(leftRailGeometryFunction, 100, 500);
+    const rightRailGeometry = new ParametricGeometry(rightRailGeometryFunction, 100, 500);
+
+    railsGeometries.push(leftRailGeometry);
+    railsGeometries.push(rightRailGeometry);
+
+    const railsMaterial = new THREE.MeshPhongMaterial({
+        side: THREE.DoubleSide,
+        transparent: false,
+        opacity: 1.0,
+        shininess: 10,
+        color: 0xFFFFFF
+    });
+
+    const railsGeometry = mergeGeometries(railsGeometries);
+    const rails = new THREE.Mesh(railsGeometry, railsMaterial);
+    scene.add(rails);
+}
+
+function mainLoop() {
+    requestAnimationFrame(mainLoop);
+    renderer.render(scene, camera);
+}
+
+function main() {
+    /*
+    railsPath = new THREE.CatmullRomCurve3([
+        new THREE.Vector3(-10, 0,  10),
+        new THREE.Vector3( 10, 0,  10),
+        new THREE.Vector3( 10, 0, -10),
+        new THREE.Vector3(-10, 0, -10),
+    ], true);
+
+    const railsPathPoints = railsPath.getPoints(50);
+    const railsPathGeometry = new THREE.BufferGeometry().setFromPoints(railsPathPoints);
+    const railsPathMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
+    const railsPathMesh = new THREE.Line(railsPathGeometry, railsPathMaterial);
+    scene.add(railsPathMesh);
+
+    buildRailsFoundation();
+    buildRails();
+    */
+    const length = 12, width = 8;
+
+    // const shape = new THREE.Shape();
+    // shape.moveTo(0,0);
+    // shape.lineTo(0, width);
+    // shape.lineTo(length, width);
+    // shape.lineTo(length, 0);
+    // shape.lineTo(0, 0);
+    
+    const tunnelHeight        = 20;
+    const tunnelWidth         = 14;
+    const tunnelWallThickness = 0.5;
+
+    const path = new THREE.Path();
+    path.moveTo(-tunnelWidth/2, 0);
+    path.lineTo(-tunnelWidth/2, tunnelHeight*1/3);
+    path.moveTo(-tunnelWidth/2, tunnelHeight*1/3);
+    path.quadraticCurveTo(0, tunnelHeight, tunnelWidth/2, tunnelHeight*1/3);
+    path.moveTo(tunnelWidth/2, 0);
+    path.lineTo(tunnelWidth/2, 0);
+
+
+    // cerramos la curva con otra de la misma forma con una diferencia de
+    // `tunnelWallThickness`
+    path.lineTo(tunnelWidth/2-tunnelWallThickness, 0);
+    path.moveTo(tunnelWidth/2-tunnelWallThickness, 0);
+
+    path.lineTo(tunnelWidth/2-tunnelWallThickness, tunnelHeight*1/3);
+    path.moveTo(tunnelWidth/2-tunnelWallThickness, tunnelHeight*1/3);
+
+    path.quadraticCurveTo(
+        0, tunnelHeight-(tunnelWallThickness*2),
+        -tunnelWidth/2+tunnelWallThickness, tunnelHeight*1/3);
+
+    path.lineTo(-tunnelWidth/2+tunnelWallThickness, 0);
+    path.moveTo(-tunnelWidth/2+tunnelWallThickness, 0);
+
+    path.lineTo(-tunnelWidth/2, 0);
+    path.moveTo(-tunnelWidth/2, 0);
+
+    const points = path.getPoints();
+
+    /*
+    const geometry = new THREE.BufferGeometry().setFromPoints(points);
+    const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
+    const curveObject = new THREE.Line(geometry, lineMaterial);
+    scene.add(curveObject);
+    */
+
+    const shape = new THREE.Shape(points);
+
+    const extrudeSettings = {
+        curveSegments: 24,
+        steps: 50,
+        depth: 26,
+    };
+
+    const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
+
+    textures.madera.object.wrapS = THREE.RepeatWrapping;
+    textures.madera.object.wrapT = THREE.RepeatWrapping;
+    textures.madera.object.repeat.set(100, 100);
+    textures.madera.object.anisotropy = 16;
+
+    const tunnelMaterial = new THREE.MeshPhongMaterial({
+        side: THREE.DoubleSide,
+        transparent: false,
+        opacity: 1.0,
+        shininess: 10,
+        map: textures.madera.object
+    });
+
+    const mesh = new THREE.Mesh(geometry, tunnelMaterial) ;
+    scene.add(mesh);
+
+    mainLoop();
+}
+
+setupThreeJs();
+loadTextures(main);
diff --git a/tp/tunnel.html b/tp/tunnel.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8" />
+        <title>Trabajo Practico Sistemas Graficos | Martin Klöckner</title>
+        <link rel="icon" href="data:,"> <!-- Do not request favicon -->
+        <style>
+            html, body, #mainContainer {
+                padding: 0;
+                margin: 0;
+                height: 100%;
+        </style>
+    </head>
+    <body>
+        <div id="mainContainer"></div>
+        <script type="module" src="/src/tunnel.js"></script>
+    </body>
+</html>