TA159

Notas, resueltos y trabajos practicos de la materia Sistemas Gráficos
Index Commits Files Refs Submodules README LICENSE
commit 2b123b3c27263bbcef6888c904002e4c1df19002
parent 85ca3cc439eafc03b75d3d12781161974d6de340
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Thu,  4 Jul 2024 18:18:44 -0300

add first person camera movement with keys `WASD`

use raycaster to find the height of the terrain

Diffstat:
Mtp/src/scene.js | 207++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 159 insertions(+), 48 deletions(-)
diff --git a/tp/src/scene.js b/tp/src/scene.js
@@ -24,6 +24,7 @@ let firstPersonControls, orbitControls;
 
 let train, gui;
 let cameras = [];
+let objects = [];
 
 let settings = {
     animationEnable: false,
@@ -32,6 +33,17 @@ let settings = {
     trainSpeed: 1.00
 };
 
+let raycaster;
+
+let moveForward = false;
+let moveBackward = false;
+let moveLeft = false;
+let moveRight = false;
+
+let prevTime = performance.now();
+const velocity = new THREE.Vector3();
+const direction = new THREE.Vector3();
+
 // actualizar la variable global `amplitude` de '/src/track-map/'
 const widthSegments   = 150;
 const heightSegments  = 150;
@@ -134,27 +146,71 @@ function firstPersonCameraHandler(eventName) {
     }
 }
 
-function setupThreeJs() {
-    scene = new THREE.Scene();
-    // container = document.getElementById('mainContainer');
-
-    renderer = new THREE.WebGLRenderer();
-    // renderer.setClearColor(0x606060);
-    // container.appendChild(renderer.domElement);
-    renderer.setPixelRatio( window.devicePixelRatio );
-    renderer.setSize( window.innerWidth, window.innerHeight );
-    document.body.appendChild( renderer.domElement );
-
-    const topView = new THREE.PerspectiveCamera(
-        35, window.innerWidth / window.innerHeight, 0.1, 1000);
-
-    topView.position.set(-50, 60, 50);
-    topView.lookAt(0, 0, 0);
-    topView.name = "topView"
-    cameras.push(topView);
-
-    orbitControls = new OrbitControls(topView, renderer.domElement);
+function keyHandler(event) {
+    // console.log(event);
+    if(event.type == 'keydown') {
+        switch (event.code) {
+            case 'ArrowUp':
+            case 'KeyW':
+                moveForward = true;
+                break;
+            case 'ArrowLeft':
+            case 'KeyA':
+                moveLeft = true;
+                break;
+            case 'ArrowDown':
+            case 'KeyS':
+                moveBackward = true;
+                break;
+            case 'ArrowRight':
+            case 'KeyD':
+                moveRight = true;
+                break;
+            case "KeyC":
+                if(event.shiftKey) {
+                    prevCamera();
+                } else {
+                    nextCamera();
+                }
+                break;
+            case 'Space':
+                // if (firstPersonControls.isLocked === true) {
+                //     console.log(canJump);
+                //     velocity.y += 350;
+                //     break;
+                // }
+                console.log("Toggling train animations");
+                settings.animationEnable = !settings.animationEnable;
+                if(gui != undefined) {
+                    // update gui 'Animations' checkbox
+                    gui.__controllers[0].updateDisplay();
+                }
+                break;
+        }
+    } else {
+        // key up
+        switch (event.code) {
+            case 'ArrowUp':
+            case 'KeyW':
+                moveForward = false;
+                break;
+            case 'ArrowLeft':
+            case 'KeyA':
+                moveLeft = false;
+                break;
+            case 'ArrowDown':
+            case 'KeyS':
+                moveBackward = false;
+                break;
+            case 'ArrowRight':
+            case 'KeyD':
+                moveRight = false;
+                break;
+        }
+    }
+}
 
+function setupFirstPersonControls() {
     const firstPersonCamera = new THREE.PerspectiveCamera(
         50, window.innerWidth / window.innerHeight, 0.1, 1000);
 
@@ -182,6 +238,32 @@ function setupThreeJs() {
     });
     scene.add(firstPersonControls.getObject());
 
+    window.addEventListener('keydown', (event) => {
+        keyHandler(event);
+    });
+
+    window.addEventListener('keyup', (event) => {
+        keyHandler(event);
+    });
+}
+
+function setupThreeJs() {
+    scene = new THREE.Scene();
+    renderer = new THREE.WebGLRenderer();
+    renderer.setPixelRatio( window.devicePixelRatio );
+    renderer.setSize( window.innerWidth, window.innerHeight );
+    document.body.appendChild( renderer.domElement );
+
+    const topView = new THREE.PerspectiveCamera(
+        35, window.innerWidth / window.innerHeight, 0.1, 1000);
+
+    topView.position.set(-50, 60, 50);
+    topView.lookAt(0, 0, 0);
+    topView.name = "topView"
+    cameras.push(topView);
+
+    orbitControls = new OrbitControls(topView, renderer.domElement);
+
     const ambientLight = new THREE.AmbientLight(0xFFFFFF);
     scene.add(ambientLight);
 
@@ -206,25 +288,6 @@ function setupThreeJs() {
 
     textures.sky.object.mapping = THREE.EquirectangularRefractionMapping;
     scene.background = textures.sky.object;
-
-    window.addEventListener('keydown', (event) => {
-        switch (event.key) {
-            case "c":
-                nextCamera();
-                break;
-            case "C":
-                prevCamera();
-                break;
-            case ' ':
-                console.log("Toggling train animations");
-                settings.animationEnable = !settings.animationEnable;
-                if(gui != undefined) {
-                    // update gui 'Animations' checkbox
-                    gui.__controllers[0].updateDisplay();
-                }
-                break
-        }
-    });
 }
 
 function onTextureLoaded(key, texture) {
@@ -283,6 +346,9 @@ function buildBridge() {
 
     scene.add(bridge1);
     scene.add(bridge2);
+
+    objects.push(bridge1);
+    objects.push(bridge2);
 }
 
 // loco -> locomotora/locomotive
@@ -401,6 +467,8 @@ function buildTerrain() {
     terrain.position.set(0, amplitudeBottom, 0);
     scene.add(terrain);
 
+    objects.push(terrain);
+
     console.log('Generating water');
     const waterGeometry = new THREE.PlaneGeometry(width/2, height-1.25);
     const waterMaterial = new THREE.MeshPhongMaterial( {color: 0x12ABFF, side: THREE.DoubleSide} );
@@ -504,22 +572,65 @@ function mainLoop() {
         updateTrainCrankPosition(time*100);
         const trainPos = getRailsPathPosAt(time);
         const railsData = getRailsPathPosAt(time);
-        // [railsPath.getPointAt(t), railsPath.getTangentAt(t)]
 
         let x = railsData[0].x;
         let z = railsData[0].z;
 
-        // translationMatrix.makeTranslation(trainPos);
-        // rotMatrix.identity();
-
-        // translationMatrix.makeTranslation(trainPos);
-        // train.position.set(0, 0, 0);
-        // train.position.set(time*10, 1.9, 0);
         train.position.set(-1+x, 2.25, -1+z);
-        // railsFoundation.position.set(-1, 1.25, -1);
         train.lookAt(railsData[1].x*1000, 1.9, railsData[1].z*1000);
-        // train.lookAt(0, 1.9, 0);
     }
+
+    let time2 = performance.now();
+    const firstPersonCameraHeight = 1.90;
+    if (firstPersonControls.isLocked === true) {
+        raycaster = new THREE.Raycaster();
+        var raycasterPos = new THREE.Vector3();
+        raycasterPos.copy(firstPersonControls.getObject().position)
+        raycasterPos.y += 10;
+        var raycasterDir = new THREE.Vector3(0, -1, 0);
+
+        raycaster.set(raycasterPos, raycasterDir);
+        const intersections = raycaster.intersectObjects(objects);
+        let positionY;
+        if((intersections == undefined) || (intersections[0] == undefined)) {
+            positionY = 0.0;
+        } else {
+            positionY = intersections[0].point.y;
+        }
+
+        const delta = (time2 - prevTime) / 1000;
+
+        velocity.x -= velocity.x * 11.0 * delta;
+        velocity.z -= velocity.z * 11.0 * delta;
+        velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
+
+        direction.z = Number( moveForward ) - Number( moveBackward );
+        direction.x = Number( moveRight ) - Number( moveLeft );
+        direction.normalize(); // this ensures consistent movements in all directions
+
+        if (moveForward || moveBackward) {
+            velocity.z -= direction.z * 100.0 * delta;
+        }
+
+        if (moveLeft || moveRight) {
+            velocity.x -= direction.x * 100.0 * delta;
+        }
+
+        // TODO: terrain limits
+        firstPersonControls.moveRight(-velocity.x * delta);
+        firstPersonControls.moveForward(-velocity.z * delta);
+
+        firstPersonControls.getObject().position.y =
+            positionY < 0.0 ? firstPersonCameraHeight : positionY + firstPersonCameraHeight;
+
+
+        if (firstPersonControls.getObject().position.y < (positionY + firstPersonCameraHeight)) {
+            velocity.y = 0;
+            firstPersonControls.getObject().position.y = firstPersonCameraHeight;
+            // canJump = true;
+        }
+    }
+    prevTime = time2;
 }
 
 function main() {