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