TA159

Notas, resueltos y trabajos practicos de la materia Sistemas Gráficos
Index Commits Files Refs Submodules README LICENSE
tp/src/standalone/rails.js (8468B)
   1 import * as THREE from 'three';
   2 import * as dat from 'dat.gui';
   3 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
   4 
   5 import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';
   6 import { ParametricGeometries } from 'three/examples/jsm/geometries/ParametricGeometries.js';
   7 import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';
   8 
   9 let scene, camera, renderer, container, terrainMaterial, instancedTrees;
  10 let spherePath;
  11 let railsPath;
  12 let railsFoundationShape;
  13 
  14 import tierraUrl     from '../assets/tierra.jpg'
  15 import rocaUrl       from '../assets/roca.jpg'
  16 import pastoUrl      from '../assets/pasto.jpg'
  17 import durmientesUrl from '../assets/durmientes.jpg'
  18 
  19 const textures = {
  20     tierra:     { url: tierraUrl,     object: null },
  21     roca:       { url: rocaUrl,       object: null },
  22     pasto:      { url: pastoUrl,      object: null },
  23     durmientes: { url: durmientesUrl, object: null },
  24 };
  25 
  26 function onResize() {
  27     camera.aspect = container.offsetWidth / container.offsetHeight;
  28     camera.updateProjectionMatrix();
  29     renderer.setSize(container.offsetWidth, container.offsetHeight);
  30 }
  31 
  32 function setupThreeJs() {
  33     scene = new THREE.Scene();
  34     container = document.getElementById('mainContainer');
  35 
  36     renderer = new THREE.WebGLRenderer();
  37     renderer.setClearColor(0x606060);
  38     container.appendChild(renderer.domElement);
  39 
  40     camera = new THREE.PerspectiveCamera(
  41         35, window.innerWidth / window.innerHeight, 0.1, 1000);
  42 
  43     camera.position.set(-10, 15, -10);
  44     camera.lookAt(0, 0, 0);
  45 
  46     const controls = new OrbitControls(camera, renderer.domElement);
  47 
  48     const ambientLight = new THREE.AmbientLight(0xffffff);
  49     scene.add(ambientLight);
  50 
  51     const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x000000, 0.25);
  52     scene.add(hemisphereLight);
  53 
  54     const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  55     directionalLight.position.set(100, 100, 100);
  56     scene.add(directionalLight);
  57 
  58     const gridHelper = new THREE.GridHelper(50, 20);
  59     scene.add(gridHelper);
  60 
  61     const axesHelper = new THREE.AxesHelper(5);
  62     scene.add(axesHelper);
  63 
  64     window.addEventListener('resize', onResize);
  65     onResize();
  66 }
  67 
  68 function onTextureLoaded(key, texture) {
  69     texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  70     textures[key].object = texture;
  71     console.log('Texture `' + key + '` loaded');
  72 }
  73 
  74 function loadTextures(callback) {
  75     const loadingManager = new THREE.LoadingManager();
  76 
  77     loadingManager.onLoad = () => {
  78         console.log('All textures loaded');
  79         callback();
  80     };
  81 
  82     for (const key in textures) {
  83         console.log("Loading textures");
  84         const loader = new THREE.TextureLoader(loadingManager);
  85         const texture = textures[key];
  86         texture.object = loader.load(
  87             texture.url,
  88             onTextureLoaded.bind(this, key),
  89             null,
  90             (error) => {
  91                 console.error(error);
  92             }
  93         );
  94     }
  95 }
  96 
  97 function parametricRailsFoundationFunction(u, v, target) {
  98     const rotMatrix = new THREE.Matrix4();
  99     const translationMatrix = new THREE.Matrix4();
 100     const levelMatrix = new THREE.Matrix4();
 101 
 102     let railsPathPos = railsPath.getPointAt(v);
 103     let railsFoundationShapePos = railsFoundationShape.getPointAt(u);
 104     // TODO: make `railsFoundationShape` smaller and remove this multiplication
 105     railsFoundationShapePos.multiplyScalar(0.5);
 106 
 107     let tangente = new THREE.Vector3();
 108     let binormal = new THREE.Vector3();
 109     let normal = new THREE.Vector3();
 110 
 111     tangente = railsPath.getTangent(v);
 112 
 113     tangente.normalize();
 114     binormal = new THREE.Vector3(0, 1, 0);
 115     normal.crossVectors(tangente, binormal);
 116 
 117     translationMatrix.makeTranslation(railsPathPos);
 118 
 119     rotMatrix.identity();
 120     levelMatrix.identity();
 121 
 122     levelMatrix.makeTranslation(railsPathPos);
 123     rotMatrix.makeBasis(normal, tangente, binormal);
 124     levelMatrix.multiply(rotMatrix);
 125     railsFoundationShapePos.applyMatrix4(levelMatrix);
 126     
 127     const x = railsFoundationShapePos.x;
 128     const y = railsFoundationShapePos.y;
 129     const z = railsFoundationShapePos.z;
 130     target.set(x, y, z);
 131 }
 132 
 133 export function buildRailsFoundation() {
 134     railsFoundationShape = new THREE.CatmullRomCurve3([
 135         new THREE.Vector3( -2.00, 0.00, 0.00),
 136         new THREE.Vector3( -1.00, 0.00, 0.50),
 137         new THREE.Vector3(  0.00, 0.00, 0.55),
 138         new THREE.Vector3(  1.00, 0.00, 0.50),
 139         new THREE.Vector3(  2.00, 0.00, 0.00),
 140     ], false);
 141 
 142     /*
 143     // show rails foundation shape
 144     const points = railsFoundationShape.getPoints(50);
 145     const geometry = new THREE.BufferGeometry().setFromPoints(points);
 146     const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
 147     const curveObject = new THREE.Line(geometry, lineMaterial);
 148     scene.add(curveObject);
 149     */
 150     const pGeometry = new ParametricGeometry(
 151         parametricRailsFoundationFunction, 100, 100);
 152     
 153     textures.durmientes.object.wrapS = THREE.RepeatWrapping;
 154     textures.durmientes.object.wrapT = THREE.RepeatWrapping;
 155     textures.durmientes.object.repeat.set(1, 60);
 156     textures.durmientes.object.anisotropy = 16;
 157 
 158     /*
 159     // load into `map` the example texture
 160     const map = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
 161     map.wrapS = map.wrapT = THREE.RepeatWrapping;
 162     map.repeat.set(1, 30);
 163     map.anisotropy = 16;
 164     // map.rotation = Math.PI/2;
 165     */
 166 
 167     const pMaterial = new THREE.MeshPhongMaterial({
 168         side: THREE.DoubleSide,
 169         transparent: false,
 170         opacity: 1.0,
 171         shininess: 10,
 172         map: textures.durmientes.object
 173     });
 174     const pMesh = new THREE.Mesh(pGeometry, pMaterial);
 175     pMesh.receiveShadow = true;
 176     pMesh.castShadow = true;
 177     scene.add(pMesh);
 178 }
 179 
 180 // `position` es de tipo `THREE.Vector3` y representa la translacion de la
 181 // forma del rail con respecto al origen del sist. de coordenadas de modelado
 182 function getParametricRailsFunction(radius, position) {
 183     return function parametricRails(u, v, target) {
 184         const rotMatrix = new THREE.Matrix4();
 185         const translationMatrix = new THREE.Matrix4();
 186         const levelMatrix = new THREE.Matrix4();
 187 
 188         let railsShape = new THREE.Vector3();
 189 
 190         let railsPathPos = railsPath.getPointAt(v);
 191         let railsShapePos = new THREE.Vector3(
 192             Math.cos(u*6.28) + position.x,
 193             position.y,
 194             Math.sin(u*6.28) + position.z);
 195 
 196         railsShapePos.multiplyScalar(0.1*railsRadius);
 197 
 198         let tangente = new THREE.Vector3();
 199         let binormal = new THREE.Vector3();
 200         let normal = new THREE.Vector3();
 201 
 202         // https://threejs.org/docs/index.html?q=curve#api/en/extras/core/Curve.getTangent
 203         tangente = railsPath.getTangentAt(v);
 204         binormal = new THREE.Vector3(0, 1, 0);
 205         normal.crossVectors(tangente, binormal);
 206 
 207         translationMatrix.makeTranslation(railsPathPos);
 208 
 209         rotMatrix.identity();
 210         levelMatrix.identity();
 211 
 212         levelMatrix.makeTranslation(railsPathPos);
 213         rotMatrix.makeBasis(normal, tangente, binormal);
 214         levelMatrix.multiply(rotMatrix);
 215         railsShapePos.applyMatrix4(levelMatrix);
 216         
 217         const x = railsShapePos.x;
 218         const y = railsShapePos.y;
 219         const z = railsShapePos.z;
 220         target.set(x, y, z);
 221     }
 222 }
 223 
 224 const railsRadius = 0.35;
 225 function buildRails() {
 226     let railsGeometries = [];
 227 
 228     const leftRailGeometryFunction  = getParametricRailsFunction(railsRadius,
 229         new THREE.Vector3( 6, 0, railsRadius+8));
 230 
 231     const rightRailGeometryFunction = getParametricRailsFunction(railsRadius,
 232         new THREE.Vector3(-6, 0, railsRadius+8));
 233 
 234     const leftRailGeometry  = new ParametricGeometry(leftRailGeometryFunction, 100, 500);
 235     const rightRailGeometry = new ParametricGeometry(rightRailGeometryFunction, 100, 500);
 236 
 237     railsGeometries.push(leftRailGeometry);
 238     railsGeometries.push(rightRailGeometry);
 239 
 240     const railsMaterial = new THREE.MeshPhongMaterial({
 241         side: THREE.DoubleSide,
 242         transparent: false,
 243         opacity: 1.0,
 244         shininess: 10,
 245         color: 0xFFFFFF
 246     });
 247 
 248     const railsGeometry = mergeGeometries(railsGeometries);
 249     const rails = new THREE.Mesh(railsGeometry, railsMaterial);
 250     rails.castShadow = true;
 251     scene.add(rails);
 252 }
 253 
 254 function mainLoop() {
 255     requestAnimationFrame(mainLoop);
 256     renderer.render(scene, camera);
 257 }
 258 
 259 function main() {
 260     railsPath = new THREE.CatmullRomCurve3([
 261         new THREE.Vector3(-10, 0,  10),
 262         new THREE.Vector3( 10, 0,  10),
 263         new THREE.Vector3( 10, 0, -10),
 264         new THREE.Vector3(-10, 0, -10),
 265     ], true);
 266 
 267     /*
 268     // muestra la curva utilizada para el camino de `rails`
 269     const railsPathPoints = railsPath.getPoints(50);
 270     const railsPathGeometry = new THREE.BufferGeometry().setFromPoints(railsPathPoints);
 271     const railsPathMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
 272     const railsPathMesh = new THREE.Line(railsPathGeometry, railsPathMaterial);
 273     scene.add(railsPathMesh);
 274     */
 275 
 276     buildRailsFoundation();
 277     buildRails();
 278     mainLoop();
 279 }
 280 
 281 setupThreeJs();
 282 loadTextures(main);