From b09cbc7526eb3a073494a41813aab3e6da4d3f0c Mon Sep 17 00:00:00 2001
From: "jorge.josegonc" <jorge.jose-goncalves@etu.hesge.ch>
Date: Thu, 26 Nov 2020 16:12:03 +0100
Subject: [PATCH] refonte du labo a cause des normals

---
 lab3/src/lab3.js | 876 ++++++++++++++++++-----------------------------
 1 file changed, 329 insertions(+), 547 deletions(-)

diff --git a/lab3/src/lab3.js b/lab3/src/lab3.js
index 70f08bb..0fd18b5 100644
--- a/lab3/src/lab3.js
+++ b/lab3/src/lab3.js
@@ -2,691 +2,473 @@
 Author : Jorge José Goncalves
 */
 
-// Vertex shader program
-const VSHADER_SOURCE =
+var eyeX = 2;
+var eyeY = 4;
+var eyeZ = 6;
+const STEP = 0.1;
+var lightDirectionnalX = 0.5;
+var lightDirectionnalY = 3.0;
+var lightDirectionnalZ = 4.0;
+var lightPositionX = 2.3;
+var lightPositionY = 4.0;
+var lightPositionZ = 3.5;
+
+var VSHADER_SOURCE_DIRECTIONNAL_LIGHT =
   'attribute vec4 a_Position;\n' +
   'attribute vec4 a_Color;\n' +
   'attribute vec4 a_Normal;\n' +
-  'varying vec4 v_Color;\n' +
-  'uniform mat4 mView;\n' +
-  'uniform mat4 mModel;\n' +
-  'uniform mat4 mProjection;\n' +
-  'uniform vec3 u_LightColor;\n' +
-  'uniform vec3 u_LightDirection;\n' +
+  'uniform mat4 u_MvpMatrix;\n' +
   'uniform mat4 u_NormalMatrix;\n' +
+  'uniform vec3 u_LightDirection;\n' +
+  'uniform vec3 u_LightColor;\n' +
+  'varying vec4 v_Color;\n' +
   'void main() {\n' +
-  '  gl_Position = mProjection * mView * mModel * a_Position ;\n' +
-  '  vec3 normal = normalize(a_Normal.xyz);\n' +
-  '  float nDotL = max(dot(u_LightDirection, normal), 0.0);\n' +
-  '  vec3 diffuse = u_LightColor * a_Color.rgb * nDotL;\n' +
-  '  v_Color = vec4(diffuse, a_Color.a);\n' +
+  '  gl_Position = u_MvpMatrix * a_Position;\n' +
+  '  vec4 normal = u_NormalMatrix * a_Normal;\n' +
+  '  float nDotL = max(dot(normalize(normal.xyz), u_LightDirection), 0.0);\n' +
+  '  v_Color = vec4(a_Color.xyz * nDotL, a_Color.a);\n' +
   '}\n';
 
-// Fragment shader program
-const FSHADER_SOURCE =
+var FSHADER_SOURCE_DIRECTIONNAL_LIGHT =
   '#ifdef GL_ES\n' +
   'precision mediump float;\n' +
   '#endif\n' +
   'varying vec4 v_Color;\n' +
-
   'void main() {\n' +
   '  gl_FragColor = v_Color;\n' +
   '}\n';
 
-
-// Vertex shader program
-const VSHADER_SOURCE_2 =
-'attribute vec4 a_Position;\n' +
+var VSHADER_SOURCE_PONCTUAL_LIGHT =
+  'attribute vec4 a_Position;\n' +
   'attribute vec4 a_Color;\n' +
   'attribute vec4 a_Normal;\n' +
+  'uniform mat4 u_MvpMatrix;\n' +
+  'uniform mat4 u_ModelMatrix;\n' +    // Model matrix
+  'uniform mat4 u_NormalMatrix;\n' +   // Coordinate transformation matrix of the normal
+  'uniform vec3 u_LightColor;\n' +     // Light color
+  'uniform vec3 u_LightPosition;\n' +  // Position of the light source
+  'uniform vec3 u_AmbientLight;\n' +   // Ambient light color
   'varying vec4 v_Color;\n' +
-  'uniform mat4 mView;\n' +
-  'uniform mat4 mModel;\n' +
-  'uniform mat4 mProjection;\n' +
-  'uniform vec3 u_LightColor;\n' +
-  'uniform vec3 u_LightDirection;\n' +
-  'uniform vec3 u_LightPosition;\n' +
-  'uniform vec3 u_AmbientLight;\n' +
-  'uniform mat4 u_NormalMatrix;\n' +
-  'uniform mat4 u_ModelMatrix;\n' +
   'void main() {\n' +
-  '  gl_Position = mProjection * mView * mModel * a_Position ;\n' +
+  '  gl_Position = u_MvpMatrix * a_Position;\n' +
+  // Recalculate the normal based on the model matrix and make its length 1.
   '  vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
+  // Calculate world coordinate of vertex
   '  vec4 vertexPosition = u_ModelMatrix * a_Position;\n' +
+  // Calculate the light direction and make it 1.0 in length
   '  vec3 lightDirection = normalize(u_LightPosition - vec3(vertexPosition));\n' +
-  '  float nDotL = max(dot(lightDirection, normal), 0.0);\n' +
+  // Calculate the dot product of the normal and light direction
+  '  float nDotL = max(dot(normal, lightDirection), 0.0);\n' +
+  // Calculate the color due to diffuse reflection
   '  vec3 diffuse = u_LightColor * a_Color.rgb * nDotL;\n' +
+  // Calculate the color due to ambient reflection
   '  vec3 ambient = u_AmbientLight * a_Color.rgb;\n' +
-  '  v_Color = vec4(diffuse + ambient, a_Color.a);\n' + 
+  // Add the surface colors due to diffuse reflection and ambient reflection
+  '  v_Color = vec4(diffuse + ambient, a_Color.a);\n' +
   '}\n';
 
 // Fragment shader program
-const FSHADER_SOURCE_2 =
+var FSHADER_SOURCE_PONCTUAL_LIGHT =
   '#ifdef GL_ES\n' +
-	'precision mediump float;\n' +
-	'#endif\n' +
-	'varying vec4 v_Color;\n' +
-
-	'void main() {\n' +
-	'  gl_FragColor = v_Color;\n' +
-	'}\n';
+  'precision mediump float;\n' +
+  '#endif\n' +
+  'varying vec4 v_Color;\n' +
+  'void main() {\n' +
+  '  gl_FragColor = v_Color;\n' +
+  '}\n';
 
 function main() {
-  light_directional();
-  light_ponctual();
-}
-
-function light_directional() {
-  // Retrieve <canvas> element
-  const canvas = document.getElementById('my-canvas');
-
-  // Get the rendering context for WebGL
-  const gl = getWebGLContext(canvas);
-  if (!gl) {
-    console.log('Failed to get the rendering context for WebGL');
-    return;
-  }
-
-  // Initialize shaders
-  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
-    console.log('Failed to intialize shaders.');
-    return;
-  }
-
-  // Get the storage location of mView
-  var mView = gl.getUniformLocation(gl.program, 'mView');
-  if (!mView) {
-    console.log('Failed to get the storage locations of mView');
-    return;
-  }
-
-  // Get the storage location of mModel
-  var mModel = gl.getUniformLocation(gl.program, 'mModel');
-  if (!mModel) {
-    console.log('Failed to get the storage locations of mModel');
-    return;
-  }
-
-  // Get the storage location of mProjection
-  var mProjection = gl.getUniformLocation(gl.program, 'mProjection');
-  if (!mProjection) {
-    console.log('Failed to get the storage locations of mProjection');
-    return;
-  }
-
-  // Get the storage location of u_LightColor
-  var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
-  if (!u_LightColor) {
-    console.log('Failed to get the storage locations of u_LightColor');
-    return;
-  }
-
-  // Get the storage location of u_LightDirection
-  var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
-  if (!u_LightDirection) {
-    console.log('Failed to get the storage locations of u_LightDirection');
-    return;
-  }
-
-  // Color of light = white
-  gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
-
-  var x_light_dir = 0.5;
-  var y_light_dir = 0.5;
-  var z_light_dir = 0.5;
-  // Set coordinate of the light direction
-  var lightDirection = new Vector3([x_light_dir, y_light_dir, z_light_dir]);
-  lightDirection.normalize();     // Normalize
-  gl.uniform3fv(u_LightDirection, lightDirection.elements);
-
-  // Set the projection
-  var mProjPerspective = new Matrix4();
-  mProjPerspective.setPerspective(100, gl.canvas.clientWidth / gl.canvas.clientHeight, 1, 100);
-  gl.uniformMatrix4fv(mProjection, false, mProjPerspective.elements);
-
-  // Set camera
-  var mViewLook = new Matrix4();
-  mViewLook.setLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
-
-  // Set the view matrix
-  gl.uniformMatrix4fv(mView, false, mViewLook.elements);
-
-  // Specify the color for clearing <canvas>
-  gl.clearColor(0, 0, 0, 1);
-  gl.clearDepth(1.0);
-
-  gl.enable(gl.DEPTH_TEST); // Enable the depth test (processing after fragment shader)
-  gl.depthFunc(gl.LEQUAL); // Passes if the fragment's depth value is less than or equal to the stored depth value.
-
-  // Clear <canvas> of all buffers
-  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-  draw_plain_base(gl, mModel);
-  draw_hourglass(gl, mModel);
-
-  var mViewRotate = new Matrix4();
-  var do_nothing = true;
-  // Control camera with arrows keys
+  directionnal_light();
+  ponctual_light();
+  // Control camera or lights
   document.addEventListener("keydown", (event) => {
-    // Rotate in x or y axes
     switch (event.key) {
       case 'a':
-        do_nothing = false
-        mViewRotate.setRotate(1, 0, 1, 0);
+        eyeX -= STEP;
         break;
       case 'd':
-        do_nothing = false
-        mViewRotate.setRotate(-1, 0, 1, 0);
+        eyeX += STEP;
         break;
       case 's':
-        do_nothing = false
-        mViewRotate.setRotate(1, 1, 0, 0);
+        eyeY -= STEP;
         break;
       case 'w':
-        do_nothing = false
-        mViewRotate.setRotate(-1, 1, 0, 0);
+        eyeY += STEP;
+        break;
+      case 'r':
+        eyeZ -= STEP;
+        break;
+      case 'f':
+        eyeZ += STEP;
         break;
       case 'ArrowRight':
-        do_nothing = false
-        x_light_dir += 0.1;
+        lightDirectionnalX += STEP;
+        lightPositionX += STEP;
         break;
       case 'ArrowLeft':
-        do_nothing = false
-        x_light_dir -= 0.1;
+        lightDirectionnalX -= STEP;
+        lightPositionX -= STEP;
         break;
       case 'ArrowDown':
-        do_nothing = false
-        y_light_dir -= 0.1;
+        lightDirectionnalY -= STEP;
+        lightPositionY -= STEP;
         break;
       case 'ArrowUp':
-        do_nothing = false
-        y_light_dir += 0.1;
+        lightDirectionnalY += STEP;
+        lightPositionY += STEP;
         break;
       case 'z':
-        do_nothing = false
-        z_light_dir += 0.1;
+        lightDirectionnalZ += STEP;
+        lightPositionZ += STEP;
         break;
       case 'h':
-        do_nothing = false
-        z_light_dir -= 0.1;
+        lightDirectionnalZ -= STEP;
+        lightPositionZ -= STEP;
         break;
       default:
-        do_nothing = true
         break;
     }
-
-    // other key can't activate
-    if (!do_nothing) {
-      // Multiply model matrix to final view matrix
-      var mViewFinal = mViewLook.multiply(mViewRotate);
-
-      // Set the view matrix
-      gl.uniformMatrix4fv(mView, false, mViewFinal.elements);
-
-      // Clear <canvas> of all buffers
-      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-      // Set coordinate of the light direction
-      var lightDirection = new Vector3([x_light_dir, y_light_dir, z_light_dir]);
-      lightDirection.normalize();     // Normalize
-      gl.uniform3fv(u_LightDirection, lightDirection.elements);
-
-      draw_plain_base(gl, mModel);
-      draw_hourglass(gl, mModel);
-    }
   });
 }
 
-function light_ponctual() {
-  // Retrieve <canvas> element
-  const canvas = document.getElementById('my-canvas2');
+function directionnal_light() {
+  var canvas = document.getElementById('my-canvas');
 
   // Get the rendering context for WebGL
-  const gl = getWebGLContext(canvas);
+  var gl = getWebGLContext(canvas);
   if (!gl) {
     console.log('Failed to get the rendering context for WebGL');
     return;
   }
 
-  // Initialize shaders
-  if (!initShaders(gl, VSHADER_SOURCE_2, FSHADER_SOURCE_2)) {
+  // Initialize shaders for light directionnal
+  if (!initShaders(gl, VSHADER_SOURCE_DIRECTIONNAL_LIGHT, FSHADER_SOURCE_DIRECTIONNAL_LIGHT)) {
     console.log('Failed to intialize shaders.');
     return;
   }
 
-  // Get the storage location of mView
-  var mView = gl.getUniformLocation(gl.program, 'mView');
-  if (!mView) {
-    console.log('Failed to get the storage locations of mView');
-    return;
-  }
+  // Set the clear color and enable the depth test
+  gl.clearColor(0, 0, 0, 1);
+  gl.enable(gl.DEPTH_TEST);
 
-  // Get the storage location of mModel
-  var mModel = gl.getUniformLocation(gl.program, 'mModel');
-  if (!mModel) {
-    console.log('Failed to get the storage locations of mModel');
+  // Get the storage locations of uniform variables and so on
+  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
+  var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
+  var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
+  if (!u_MvpMatrix || !u_NormalMatrix || !u_LightDirection) {
+    console.log('Failed to get the storage location');
     return;
   }
 
-  // Get the storage location of mProjection
-  var mProjection = gl.getUniformLocation(gl.program, 'mProjection');
-  if (!mProjection) {
-    console.log('Failed to get the storage locations of mProjection');
-    return;
-  }
+  var vpMatrix = new Matrix4();   // View projection matrix
 
-  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
-  if (!u_ModelMatrix) {
-    console.log('Failed to get the storage locations of u_ModelMatrix');
-    return;
-  }
+  var tick = function () {
+    // Set perspective and camera
+    vpMatrix.setPerspective(50, canvas.width / canvas.height, 1, 100);
+    vpMatrix.lookAt(eyeX, eyeY, eyeZ, 0, 0, 0, 0, 1, 0);
 
-  var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
-  if (!u_NormalMatrix) {
-    console.log('Failed to get the storage locations of u_NormalMatrix');
-    return;
-  }
+    // Set the light direction (in the world coordinate)
+    var lightDirection = new Vector3([lightDirectionnalX, lightDirectionnalY, lightDirectionnalZ]);
+    lightDirection.normalize();     // Normalize
+    gl.uniform3fv(u_LightDirection, lightDirection.elements);
 
-  var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
-  if (!u_LightColor) {
-    console.log('Failed to get the storage locations of u_LightColor');
-    return;
-  }
+    // Clear color and depth buffer
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
-  var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
 
-  if (!u_LightPosition) {
-    console.log('Failed to get the storage locations of u_LightPosition');
-    return;
-  }
+    drawHourGlass(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, null, false);
+    drawPlaneBase(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, null, false);
 
-  var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
+    requestAnimationFrame(tick, canvas);
+  };
+  tick();
+}
 
-  if (!u_AmbientLight) {
-    console.log('Failed to get the storage locations of u_AmbientLight');
+function ponctual_light() {
+  var canvas = document.getElementById('my-canvas2');
+  // Get the rendering context for WebGL
+  var gl = getWebGLContext(canvas);
+  if (!gl) {
+    console.log('Failed to get the rendering context for WebGL');
     return;
   }
 
-  x_position_light = 2.3;
-  y_position_light = 4.0;
-  z_position_light = 3.5;
-
-  gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
-  gl.uniform3f(u_LightPosition, x_position_light, y_position_light, z_position_light);
-  gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);
-
-  var modelMatrix = new Matrix4();
-  // Calculate the model matrix
-  modelMatrix.setRotate(90, 0, 1, 0); // Rotate around the y-axis
-  // Pass the model matrix to u_ModelMatrix
-  gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
-
-  // Pass the matrix to transform the normal based on the model matrix to u_NormalMatrix
-  var normalMatrix = new Matrix4();
-  normalMatrix.setInverseOf(modelMatrix);
-  normalMatrix.transpose();
-  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
-
-  // Set the projection
-  var mProjPerspective = new Matrix4();
-  mProjPerspective.setPerspective(100, gl.canvas.clientWidth / gl.canvas.clientHeight, 1, 100);
-  gl.uniformMatrix4fv(mProjection, false, mProjPerspective.elements);
-
-  // Set camera
-  var mViewLook = new Matrix4();
-  mViewLook.setLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
-
-  // Set the view matrix
-  gl.uniformMatrix4fv(mView, false, mViewLook.elements);
+  // Initialize shaders
+  if (!initShaders(gl, VSHADER_SOURCE_PONCTUAL_LIGHT, FSHADER_SOURCE_PONCTUAL_LIGHT)) {
+    console.log('Failed to intialize shaders.');
+    return;
+  }
 
-  // Specify the color for clearing <canvas>
+  // Set the clear color and enable the depth test
   gl.clearColor(0, 0, 0, 1);
-  gl.clearDepth(1.0);
+  gl.enable(gl.DEPTH_TEST);
 
-  gl.enable(gl.DEPTH_TEST); // Enable the depth test (processing after fragment shader)
-  gl.depthFunc(gl.LEQUAL); // Passes if the fragment's depth value is less than or equal to the stored depth value.
+  // Get the storage locations of uniform variables and so on
+  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
+  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
+  var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
+  var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
+  var u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
+  var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');
+  if (!u_MvpMatrix || !u_NormalMatrix || !u_LightColor || !u_LightPosition || !u_AmbientLight || !u_ModelMatrix) { 
+    console.log('Failed to get the storage location');
+    return;
+  }
 
-  // Clear <canvas> of all buffers
-  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  var vpMatrix = new Matrix4();   // View projection matrix
 
-  draw_plain_base(gl, mModel);
-  draw_hourglass(gl, mModel);
+  var tick = function () {
+    // Set perspective and camera
+    vpMatrix.setPerspective(50, canvas.width / canvas.height, 1, 100);
+    vpMatrix.lookAt(eyeX, eyeY, eyeZ, 0, 0, 0, 0, 1, 0);
 
-  var mViewRotate = new Matrix4();
-  var do_nothing = true;
-  // Control camera with arrows keys
-  document.addEventListener("keydown", (event) => {
-    // Rotate in x or y axes
-    switch (event.key) {
-      case 'a':
-        do_nothing = false
-        mViewRotate.setRotate(1, 0, 1, 0);
-        break;
-      case 'd':
-        do_nothing = false
-        mViewRotate.setRotate(-1, 0, 1, 0);
-        break;
-      case 's':
-        do_nothing = false
-        mViewRotate.setRotate(1, 1, 0, 0);
-        break;
-      case 'w':
-        do_nothing = false
-        mViewRotate.setRotate(-1, 1, 0, 0);
-        break;
-      case 'ArrowRight':
-        do_nothing = false
-        x_position_light += 0.1;
-        break;
-      case 'ArrowLeft':
-        do_nothing = false
-        x_position_light -= 0.1;
-        break;
-      case 'ArrowDown':
-        do_nothing = false
-        y_position_light -= 0.1;
-        break;
-      case 'ArrowUp':
-        do_nothing = false
-        y_position_light += 0.1;
-        break;
-      case 'z':
-        do_nothing = false
-        z_position_light += 0.1;
-        break;
-      case 'h':
-        do_nothing = false
-        z_position_light -= 0.1;
-        break;
-      default:
-        do_nothing = true
-        break;
-    }
+    // Set the light color (white)
+    gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
+    // Set the light direction (in the world coordinate)
+    gl.uniform3f(u_LightPosition, lightPositionX, lightPositionY, lightPositionZ);
+    // Set the ambient light
+    gl.uniform3f(u_AmbientLight, 0, 0, 0);
 
-    // other key can't activate
-    if (!do_nothing) {
-      // Multiply model matrix to final view matrix
-      var mViewFinal = mViewLook.multiply(mViewRotate);
+    // Clear color and depth buffer
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
-      // Set the view matrix
-      gl.uniformMatrix4fv(mView, false, mViewFinal.elements);
 
-      // Clear <canvas> of all buffers
-      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-      gl.uniform3f(u_LightPosition, x_position_light, y_position_light, z_position_light);
-      draw_plain_base(gl, mModel);
-      draw_hourglass(gl, mModel);
-    }
-  });
+    drawHourGlass(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, u_ModelMatrix, true);
+    drawPlaneBase(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, u_ModelMatrix, true);
+
+    requestAnimationFrame(tick, canvas);
+  };
+  tick();
 }
 
-function draw_plain_base(gl, mModel) {
-  // Write the positions of vertices to a vertex shader
-  const n = initVertexBuffersPlainBase(gl);
+function drawPlaneBase(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, u_ModelMatrix, isPonct) {
+  var n = initVertexBuffersPlaneBase(gl);
   if (n < 0) {
-    console.log('Failed to set the positions of the vertices');
+    console.log('Failed to set the vertex information');
     return;
   }
 
-  // Draw base
-  var modelMatrix = new Matrix4();
-  modelMatrix.setTranslate(0, -0.001, 0);
-  gl.uniformMatrix4fv(mModel, false, modelMatrix.elements);
-  gl.drawArrays(gl.TRIANGLES, 0, n);
-}
+  var modelMatrixTranslate = new Matrix4();
+  var mvpMatrix = new Matrix4();
+  var normalMatrix = new Matrix4();
 
-function draw_hourglass(gl, mModel) {
-  // Write the positions of vertices to a vertex shader
-  const n = initVertexBuffers(gl);
-  if (n < 0) {
-    console.log('Failed to set the positions of the vertices');
-    return;
-  }
 
-  // Get the storage location of mView
-  var mView = gl.getUniformLocation(gl.program, 'mView');
-  if (!mView) {
-    console.log('Failed to get the storage locations of mView');
-    return;
+  modelMatrixTranslate.setTranslate(0, -0.001, 0);
+  if (isPonct) {
+    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrixTranslate.elements);
   }
+  mvpMatrix.set(vpMatrix).multiply(modelMatrixTranslate);
+  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
+  normalMatrix.setInverseOf(modelMatrixTranslate);
+  normalMatrix.transpose();
+  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
 
-  // Draw first frustum
-  var modelMatrix = new Matrix4();
-  gl.uniformMatrix4fv(mModel, false, modelMatrix.elements);
-  gl.drawArrays(gl.TRIANGLES, 0, n);
-
-  // Draw second frustum
-  modelMatrix.setRotate(180, 1, 0, 0);
-
-  var translateMatrix = new Matrix4();
-  translateMatrix.setTranslate(0, -2.0, 0);
-  var scaleMatrix = new Matrix4();
-  scaleMatrix.setScale(-1, 1, -1);
-  var finalMatrix = modelMatrix.multiply(translateMatrix).multiply(scaleMatrix);
-  gl.uniformMatrix4fv(mModel, false, finalMatrix.elements);
-  gl.drawArrays(gl.TRIANGLES, 0, n);
+  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
 }
 
-function initVertexBuffersPlainBase(gl) {
-  // Model of big base red
-  const vertices_base = new Float32Array([
-    // x  y     z     R     G     B
-    -1.0, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-    -1.0, -0.5, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-    1.0, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-
-    1.0, -0.5, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-    -1.0, -0.5, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-    1.0, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-  ]);
-
-  const n = vertices_base.length / 9;
-
-  // Create a WebGL buffer object
-  const vertexBuffer = gl.createBuffer();
-  if (!vertexBuffer) {
-    console.log('Failed to create the buffer object');
-    return -1;
+function drawHourGlass(gl, vpMatrix, u_MvpMatrix, u_NormalMatrix, u_ModelMatrix, isPonct) {
+  var n = initVertexBuffersHourglass(gl);
+  if (n < 0) {
+    console.log('Failed to set the vertex information');
+    return;
   }
 
-  // Bind the created buffer object
-  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
-
-  // Write data into the buffer object
-  gl.bufferData(gl.ARRAY_BUFFER, vertices_base, gl.STATIC_DRAW);
+  var modelMatrixRotate = new Matrix4();  // Model matrix
+  var modelMatrixTranslate = new Matrix4();
+  var modelMatrixScale = new Matrix4();
+  var mvpMatrix = new Matrix4();    // Model view projection matrix
+  var normalMatrix = new Matrix4(); // Transformation matrix for normals
 
-  var FSIZE = vertices_base.BYTES_PER_ELEMENT;
+  // First frustrum
+  modelMatrixRotate.setRotate(0, 0, 1, 0); // Rotate around the y-axis
 
-  // Get the storage location of a_Position
-  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
-  if (a_Position < 0) {
-    console.log('Failed to get the storage location of a_Position');
-    return -1;
-  }
-  // Assign the buffer object to a_Position variable
-  gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 9, 0);
-  // Enable the assignment to a_Position variable
-  gl.enableVertexAttribArray(a_Position);
-
-  // Get the storage location of a_Color, assign buffer and enable
-  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
-  if (a_Color < 0) {
-    console.log('Failed to get the storage location of a_Color');
-    return -1;
+  if (isPonct) {
+    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrixRotate.elements);
   }
 
-  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 9, FSIZE * 3);
-  gl.enableVertexAttribArray(a_Color);
+  mvpMatrix.set(vpMatrix).multiply(modelMatrixRotate);
+  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
+  normalMatrix.setInverseOf(modelMatrixRotate);
+  normalMatrix.transpose();
+  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
 
-  // Get the storage location of a_Color, assign buffer and enable
-  var a_Normal = gl.getAttribLocation(gl.program, 'a_Normal');
-  if (a_Normal < 0) {
-    console.log('Failed to get the storage location of a_Normal');
-    return -1;
+  
+  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
+
+  // Second frustrum
+  modelMatrixRotate.setRotate(180, 1, 0, 0);
+  modelMatrixTranslate.setTranslate(0, -2.0, 0);
+  modelMatrixScale.setScale(-1, 1, -1);
+  var finalModelMatrix = modelMatrixRotate.multiply(modelMatrixTranslate).multiply(modelMatrixScale);
+  if (isPonct) {
+    console.log("ENTER")
+    gl.uniformMatrix4fv(u_ModelMatrix, false, finalModelMatrix.elements);
   }
+  mvpMatrix.set(vpMatrix).multiply(finalModelMatrix)
+  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
+  normalMatrix.setInverseOf(finalModelMatrix);
+  normalMatrix.transpose();
+  gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
 
-  gl.vertexAttribPointer(a_Normal, 3, gl.FLOAT, false, FSIZE * 9, 0);
-  gl.enableVertexAttribArray(a_Normal);
+  
 
-  return n;
+  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
 }
 
-function initVertexBuffers(gl) {
-  // This are models
-
-  // Model of big base red
-  const vertices_base = new Float32Array([
-    // x  y     z     R     G     B     normals
-    -0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
-    -0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
-    0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
-
-    0.5, -0.5, -0.5, 1.0, 0.0, 0.0,  1.0, 0.0, 0.0,
-    -0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
-    0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
+function initVertexBuffersPlaneBase(gl) {
+  var vertices_position = new Float32Array([
+    -1.0, -0.5, -1.0, 1.0, -0.5, 1.0, -1.0, -0.5, 1.0, 1.0, -0.5, -1.0
   ]);
 
-  // Model of one face in green
-  const vertices_face = new Float32Array([
-    // x  y     z     R     G     B     normals
-    -0.5, -0.5, 0.5, 1.0, 0.0, 0.0,  1.0, 0.0, 0.0,
-    -0.25, 1.0, 0.25, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
-    0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
+  // Colors only white for this tp
+  var colors = new Float32Array([
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  ]);
 
-    -0.25, 1.0, 0.25, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
-    0.25, 1.0, 0.25, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
-    0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
+  var normals = new Float32Array([
+    0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0
   ]);
 
-  // Create the rest of face and little base with differents colors
-  const vertices_face_two = duplicate_object(vertices_face, -180, 0, 0, true, 1, 0, 0)
-  const vertices_face_three = duplicate_object(vertices_face, 90, 0, 0, true, 1, 0, 0)
-  const vertices_face_four = duplicate_object(vertices_face, -90, 0, 0, true, 1, 0, 0)
-  const vertices_little_base = duplicate_object(vertices_base, 0, 2, 1.0, false, 1, 0, 0)
+  var indices = new Uint8Array([
+    0, 1, 2, 0, 1, 3
+  ]);
 
-  // Create Fustrum
-  const vertices_totals = create_fusion_object([vertices_base,
-    vertices_face, vertices_face_two, vertices_face_three,
-    vertices_face_four, vertices_little_base], vertices_base.length * 2 + vertices_face.length * 4)
+  // Write the vertex property to buffers (positions, colors and normals)
+  if (!initArrayBuffer(gl, 'a_Position', vertices_position, 3, gl.FLOAT)) return -1;
+  if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1;
+  if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;
 
-  const n = vertices_totals.length / 9;
+  // Unbind the buffer object
+  gl.bindBuffer(gl.ARRAY_BUFFER, null);
 
-  // Create a WebGL buffer object
-  const vertexBuffer = gl.createBuffer();
-  if (!vertexBuffer) {
+  // Write the indices to the buffer object
+  var indexBuffer = gl.createBuffer();
+  if (!indexBuffer) {
     console.log('Failed to create the buffer object');
-    return -1;
+    return false;
   }
+  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
 
-  // Bind the created buffer object
-  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
-
-  // Write data into the buffer object
-  gl.bufferData(gl.ARRAY_BUFFER, vertices_totals, gl.STATIC_DRAW);
+  return indices.length;
+}
 
-  var FSIZE = vertices_totals.BYTES_PER_ELEMENT;
+function initVertexBuffersHourglass(gl) {
+  var vertices_position = new Float32Array([
+    -0.25, 1.0, 0.25, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.25, 1.0, 0.25, // front face
+    0.25, 1.0, 0.25, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.25, 1.0, -0.25,// right face
+    -0.25, 1.0, -0.25, 0.25, 1.0, 0.25, -0.25, 1.0, 0.25, 0.25, 1.0, -0.25, // Up face 
+    -0.25, 1, -0.25, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.25, 1.0, 0.25,	 // left face
+    -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, // down face
+    0.25, 1.0, -0.25, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.25, 1.0, -0.25 // back face
+  ]);
 
-  // Get the storage location of a_Position
-  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
-  if (a_Position < 0) {
-    console.log('Failed to get the storage location of a_Position');
-    return -1;
-  }
-  // Assign the buffer object to a_Position variable
-  gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 9, 0);
-  // Enable the assignment to a_Position variable
-  gl.enableVertexAttribArray(a_Position);
-
-  // Get the storage location of a_Color, assign buffer and enable
-  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
-  if (a_Color < 0) {
-    console.log('Failed to get the storage location of a_Color');
-    return -1;
-  }
+  // Colors only red for this tp
+  var colors = new Float32Array([
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
+    1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0
+  ]);
 
-  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 9, FSIZE * 3);
-  gl.enableVertexAttribArray(a_Color);
+  /*var normals = [];
+
+  for(let i = 0; i < vertices_position.length - 12; i += 12){
+    // calculate normal for each triangle (3 point vector/9 values)
+    let normal = calculateNormalSurface(
+      vertices_position[i],
+      vertices_position[i + 1],
+      vertices_position[i + 2],
+      vertices_position[i + 3],
+      vertices_position[i + 4],
+      vertices_position[i + 5],
+      vertices_position[i + 6],
+      vertices_position[i + 7],
+      vertices_position[i + 8]
+    )
+    // Store normal for 4 points
+    for(let k = 0; k < 4; k++){
+      normals.push(normal[0]);
+      normals.push(normal[1]);
+      normals.push(normal[2]);
+    }
+  }*/
+  
+  var normals = new Float32Array([
+    0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,  // front face
+    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,  // right face
+    0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,  // up face
+    -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,  // left face
+    0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,  // down face
+    0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0   // back face
+  ]);
 
-  // Get the storage location of a_Color, assign buffer and enable
-  var a_Normal = gl.getAttribLocation(gl.program, 'a_Normal');
-  if (a_Normal < 0) {
-    console.log('Failed to get the storage location of a_Normal');
-    return -1;
-  }
+  var indices = new Uint8Array([
+    0, 1, 2, 0, 1, 3,    // front Face
+    4, 5, 6, 4, 5, 7,	// right face
+    8, 9, 10, 8, 9, 11,	// up face
+    12, 13, 14, 12, 13, 15, // left face
+    16, 17, 18, 16, 17, 19, // down face
+    20, 21, 22, 20, 21, 23 // back face
 
-  gl.vertexAttribPointer(a_Normal, 3, gl.FLOAT, false, FSIZE * 9, 0);
-  gl.enableVertexAttribArray(a_Normal);
+  ]);
 
-  return n;
-}
+  // Write the vertex property to buffers (positions, colors and normals)
+  if (!initArrayBuffer(gl, 'a_Position', vertices_position, 3, gl.FLOAT)) return -1;
+  if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1;
+  if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;
 
-// Can duplicate object with a rotation in axe x or scale in x and z and change color
-function duplicate_object(original_object, angle, scale, transform_y, isFace, r, g, b) {
-  const new_object = new Float32Array(original_object.length)
-  var etat = -1; // etat = 0 : position, etat = 1 : color, etat = 2 : normal
-  for (var i = 0; i < new_object.length; i++) {
-    // Every 3 values can be the color or position
-    if (i % 3 == 0) {
-      etat += 1;
-
-      if (etat == 3) {
-        etat = 0;
-      }
-    }
+  // Unbind the buffer object
+  gl.bindBuffer(gl.ARRAY_BUFFER, null);
 
-    // Change position or color
-    if (etat == 0) {
-      // Change rotation in axe y when is a face
-      if (isFace) {
-        switch (i % 3) {
-          case 0:
-            new_object[i] = Math.cos((angle * (Math.PI / 180))) * original_object[i] + Math.sin((angle * (Math.PI / 180))) * original_object[i + 2]
-            break;
-          case 1:
-            new_object[i] = original_object[i]
-            break;
-          case 2:
-            new_object[i] = -1 * Math.sin((angle * (Math.PI / 180))) * original_object[i - 2] + Math.cos((angle * (Math.PI / 180))) * original_object[i]
-            break;
-        }
-      }
-      else {
-        // Change scaLe and transform when is a base
-        switch (i % 3) {
-          case 0:
-            new_object[i] = original_object[i] / scale
-            break;
-          case 1:
-            new_object[i] = transform_y
-            break;
-          case 2:
-            new_object[i] = original_object[i] / scale
-            break;
-        }
-      }
-    }
-    else if (etat == 1) {
-      if (i % 3 == 0) {
-        new_object[i] = r
-      }
-      else if (i % 3 == 1) {
-        new_object[i] = g
-      }
-      else {
-        new_object[i] = b
-      }
-    }
+  // Write the indices to the buffer object
+  var indexBuffer = gl.createBuffer();
+  if (!indexBuffer) {
+    console.log('Failed to create the buffer object');
+    return false;
   }
+  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
 
-  return new_object
+  return indices.length;
 }
 
-// create a object by fusion of others objects
-function create_fusion_object(all_objects, length_fusion_object) {
-  const fusion_object = new Float32Array(length_fusion_object);
-  var index_actual = 0
-  for (var i = 0; i < all_objects.length; i++) {
-    fusion_object.set(all_objects[i], index_actual);
-    index_actual = index_actual + all_objects[i].length;
+function initArrayBuffer(gl, attribute, data, num, type) {
+  // Create a buffer object
+  var buffer = gl.createBuffer();
+  if (!buffer) {
+    console.log('Failed to create the buffer object');
+    return false;
+  }
+  // Write date into the buffer object
+  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
+  // Assign the buffer object to the attribute variable
+  var a_attribute = gl.getAttribLocation(gl.program, attribute);
+  if (a_attribute < 0) {
+    console.log('Failed to get the storage location of ' + attribute);
+    return false;
   }
-  return fusion_object
+  gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
+  // Enable the assignment of the buffer object to the attribute variable
+  gl.enableVertexAttribArray(a_attribute);
+
+  return true;
+}
+
+// Calculate a surface normal by the pseudo code khronos.org
+function calculateNormalSurface(ax, ay, az, bx, by, bz, cx, cy, cz) {
+  let x = 0;
+  let y = 1;
+  let z = 2;
+
+  let u = [bx - ax, by - ay, bz - az];
+  let v = [cx - ax, cy - ay, cz - az];
+  return [
+      u[y] * v[z] - u[z] * v[y],
+      u[z] * v[x] - u[x] * v[z],
+      u[x] * v[y] - u[y] * v[x]
+  ];
 }
-- 
GitLab