diff --git a/index.html b/index.html index c559a99..3e978f9 100644 --- a/index.html +++ b/index.html @@ -3,362 +3,6 @@ - + \ No newline at end of file diff --git a/main.js b/main.js index fb79e17..552962f 100644 --- a/main.js +++ b/main.js @@ -1,11 +1,24 @@ -// Global variables -const MAXC = 20; -const MAXV = 100; -let courbe = new Array(MAXC).fill().map(() => new Array(MAXV).fill(0)); -let valmin = new Array(MAXC).fill(0); -let valmax = new Array(MAXC).fill(0); -let nc = 0; +// Mapping function +function map(smin, smax, val, omin, omax) { + const percent = (val - smin) / (smax - smin); + return (omax - omin) * percent + omin; +} + +/*======= Creating a canvas =========*/ + +var canvas = document.getElementById('my_Canvas'); +var gl = canvas.getContext('webgl'); + +/*======= Filling values =========*/ +var nc = 3; // Number of curves +var courbe = [ + [5, 0.1, 0.4, 0.7, 0.9, 1.0], // Example data + [5, 0.2, 0.3, 0.6, 0.8, 0.95], + [5, 0.05, 0.15, 0.5, 0.75, 0.85], +]; +var valmin = [0.1, 0.2, 0.05]; +var valmax = [1.0, 0.95, 0.85]; // Drawing modes const HORIZONTAL = 0; @@ -18,138 +31,324 @@ const LIGNE_AXES = 1; const HISTOGRAMME = 2; let mode_affichage = HORIZONTAL; -let type_dessin = LIGNE; - -// WebGL setup -function initWebGL() { - const canvas = document.getElementById("glCanvas"); - const gl = canvas.getContext("webgl"); - - if (!gl) { - console.error("Unable to initialize WebGL."); - return null; - } - - return gl; -} - -// Mapping function -function map(smin, smax, val, omin, omax) { - const percent = (val - smin) / (smax - smin); - return (omax - omin) * percent + omin; -} - -// Draw axes -function drawAxes(gl, x1, x2, y1, y2) { - gl.lineWidth(1); - gl.strokeStyle = "#FF8080"; - gl.beginPath(); - gl.moveTo(x1, y2); - gl.lineTo(x2, y2); - gl.lineTo(x2, y1); - gl.stroke(); -} - -// Draw curve -function drawCurve(gl, index, hgx, hgy, bdx, bdy) { - if (index >= nc) { - console.error("Invalid curve index"); - return; - } - - gl.strokeStyle = "#FFFFFF"; // Set line color to white +let type_dessin = LIGNE_AXES; +function toVertices(index) +{ const size = courbe[index][0]; + var vertices = new Array(size*3).fill(0); - gl.beginPath(); + let j = 0; for (let i = 1; i <= size; i++) { - let posX = map(0, size - 1, i - 1, hgx, bdx); - let posY = map(valmin[index], valmax[index], courbe[index][i], bdy, hgy); + vertices[j] = map(1, size, i, -1, 1); - if (mode_affichage === VERTICAL) { - // Swap x and y for vertical mode - [posX, posY] = [posY, posX]; - } - - if (i === 1) { - gl.moveTo(posX, posY); - } else { - gl.lineTo(posX, posY); - } - } - gl.stroke(); -} - -// Draw histogram -function drawHistogram(gl, index, hgx, hgy, bdx, bdy) { - if (index >= nc) { - console.error("Invalid curve index"); - return; - } - - gl.fillStyle = "#FFFFFF"; // Set fill color to white - - const size = courbe[index][0]; - for (let i = 1; i <= size; i++) { - let gauche = map(0, size, i - 1, hgx, bdx); - let droite = map(0, size, i, hgx, bdx); - let haut = map(valmin[index], valmax[index], courbe[index][i], bdy, hgy); - let bas = bdy; - - if (mode_affichage === VERTICAL) { - [gauche, haut] = [haut, droite]; - [droite, bas] = [bas, gauche]; - } - - gl.fillRect(gauche, haut, droite - gauche, bas - haut); - } -} - -// Display function (main rendering function) -function display(gl) { - gl.clearColor(0.0, 0.0, 0.0, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - if (mode_affichage === HORIZONTAL) { - for (let i = 0; i < nc; i++) { - console.log(i); - let haut = map(0, nc, i, 1.0, -1.0); - let bas = map(0, nc, i + 1, 1.0, -1.0); - if (type_dessin === LIGNE || type_dessin === LIGNE_AXES) { - console.log("drawCurve"); - drawCurve(gl, i, -1.0, haut, 1.0, bas); - console.log("drawCurve"); - } else if (type_dessin === HISTOGRAMME) { - drawHistogram(gl, i, -1.0, haut, 1.0, bas); + if(mode_affichage == SUPERPOSER) + { + vertices[j+1] = map(valmin[index], valmax[index], courbe[index][i], -1, 1); + }else + { + var start = map(0, nc, index, -1, 1); + var end = map(0, nc, index+1, -1, 1); + vertices[j+1] = map(valmin[index], valmax[index], courbe[index][i], start, end); + if(mode_affichage == VERTICAL) + { + [vertices[j], vertices[j+1]] = [vertices[j+1], vertices[j]]; } } + + vertices[j+2] = 0; + j += 3; + } + return vertices; +} + +function getCurveVertices(index) +{ + const size = courbe[index][0]; + var vertices = toVertices(index); + + // Create an empty buffer object + var vertex_buffer = gl.createBuffer(); + + // Bind appropriate array buffer to it + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + // Pass the vertex data to the buffer + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + + // Unbind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + //console.log(vertices); + + return vertex_buffer; + +} + +/*=================== Shaders ====================*/ +function setShader(red) +{ + // Vertex shader source code + var vertCode = + 'attribute vec3 coordinates;' + + 'void main(void) {' + + ' gl_Position = vec4(coordinates, 1.0);' + + '}'; + +// Create a vertex shader object +var vertShader = gl.createShader(gl.VERTEX_SHADER); + +// Attach vertex shader source code +gl.shaderSource(vertShader, vertCode); + +// Compile the vertex shader +gl.compileShader(vertShader); + +// Fragment shader source code +var fragCode = ""; +if(red == false) +{ + var fragCode = + 'void main(void) {' + + 'gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);' + + '}'; +}else{ + var fragCode = + 'void main(void) {' + + 'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + + '}'; +} +// Create fragment shader object +var fragShader = gl.createShader(gl.FRAGMENT_SHADER); + +// Attach fragment shader source code +gl.shaderSource(fragShader, fragCode); + +// Compile the fragmentt shader +gl.compileShader(fragShader); + +// Create a shader program object to store +// the combined shader program +var shaderProgram = gl.createProgram(); + +// Attach a vertex shader +gl.attachShader(shaderProgram, vertShader); + +// Attach a fragment shader +gl.attachShader(shaderProgram, fragShader); + +// Link both the programs +gl.linkProgram(shaderProgram); + +// Use the combined shader program object +gl.useProgram(shaderProgram); + +return shaderProgram; +} + +var shaderProgramRed = setShader(true); +var shaderProgram = setShader(false); + +function draw(index) +{ + var vertex_buffer = getCurveVertices(index); + + // Bind vertex buffer object + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + // Get the attribute location + var coord = gl.getAttribLocation(shaderProgram, "coordinates"); + + // Point an attribute to the currently bound VBO + gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); + + // Enable the attribute + gl.enableVertexAttribArray(coord); + + // Set the view port + gl.viewport(0,0,canvas.width,canvas.height); + + // Draw the triangle + gl.drawArrays(gl.LINE_STRIP, 0, courbe[index][0]); +} + +function axe(index, ax) +{ + const size = courbe[index][0]; + + x_start = -1.0; + x_end = map(1, size, ax+1, -1, 1); + + y_start = -1; + y_end = map(valmin[index], valmax[index], courbe[index][ax+1], -1, 1); + if(mode_affichage != SUPERPOSER) + { + y_start = map(0, nc, index, -1, 1); + var end = map(0, nc, index+1, -1, 1); + y_end = map(valmin[index], valmax[index], courbe[index][ax+1], y_start, end); + } + + if(mode_affichage == VERTICAL) + { + [x_start, y_start] = [y_start, x_start]; + [x_end, y_end] = [y_end, x_end]; + } + + var vertices = [ + x_start, y_end, 0.0, + x_end, y_end, 0.0, + x_end, y_end, 0.0, + x_end, y_start, 0.0, + ] + + return vertices; +} + +function drawAxes(index) +{ + const size = courbe[index][0]; + var vertices = []; + for(let i = 1; i < size; i++) + { + let v = axe(index, i); + vertices.push(...v); + } + + //console.log(vertices); + + // Create an empty buffer object + var vertex_buffer = gl.createBuffer(); + + // Bind appropriate array buffer to it + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + // Pass the vertex data to the buffer + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + + // Get the attribute location + var coord = gl.getAttribLocation(shaderProgram, "coordinates"); + + // Point an attribute to the currently bound VBO + gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); + + // Enable the attribute + gl.enableVertexAttribArray(coord); + + // Set the view port + gl.viewport(0,0,canvas.width,canvas.height); + + gl.useProgram(shaderProgramRed); + + // Draw the triangle + gl.drawArrays(gl.LINES, 0, (courbe[index][0]-1) * 4); + + gl.useProgram(shaderProgram); +} + +function square(index, squ) +{ + const size = courbe[index][0]; + + x_start = map(1, size, squ, -1, 1); + x_end = map(1, size, squ+1, -1, 1); + + y_start = -1; + y_end = map(valmin[index], valmax[index], courbe[index][squ], -1, 1); + if(mode_affichage != SUPERPOSER) + { + y_start = map(0, nc, index, -1, 1); + var end = map(0, nc, index+1, -1, 1); + y_end = map(valmin[index], valmax[index], courbe[index][squ], y_start, end); + } + + if(mode_affichage == VERTICAL) + { + [x_start, y_start] = [y_start, x_start]; + [x_end, y_end] = [y_end, x_end]; + } + + var vertices = [ + x_start, y_start, 0, + x_end, y_start, 0, + x_end, y_end, 0, + x_start, y_end, 0 + ] + + return vertices; +} + +function drawHisto(index) +{ + const size = courbe[index][0]; + for(let i = 1; i < size; i++) + { + var vertices = square(index, i); + + //console.log(i); + //console.log(vertices); + + indices = [0, 2, 1, 0, 3, 2]; + + // Create an empty buffer object to store vertex buffer + var vertex_buffer = gl.createBuffer(); + + // Bind appropriate array buffer to it + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + // Pass the vertex data to the buffer + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + + // Unbind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + // Create an empty buffer object to store Index buffer + var Index_Buffer = gl.createBuffer(); + + // Bind appropriate array buffer to it + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); + + // Pass the vertex data to the buffer + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); + + // Unbind the buffer + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + + // Bind vertex buffer object + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + + // Bind index buffer object + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); + + // Get the attribute location + var coord = gl.getAttribLocation(shaderProgram, "coordinates"); + + // Point an attribute to the currently bound VBO + gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); + + // Enable the attribute + gl.enableVertexAttribArray(coord); + + // Set the view port + gl.viewport(0,0,canvas.width,canvas.height); + + // Draw the triangle + gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0); + } + +} + +gl.clearColor(0, 0, 0, 0.5); +gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); +for(var i = 0; i < nc; i++) +{ + if(type_dessin == HISTOGRAMME) + { + drawHisto(i); + }else{ + draw(i); + if(type_dessin == LIGNE_AXES) + { + drawAxes(i); + } } } - -// Load the data from file (simulated in JavaScript) -function loadFile() { - nc = 3; // Number of curves - courbe = [ - [5, 0.1, 0.4, 0.7, 0.9, 1.0], // Example data - [5, 0.2, 0.3, 0.6, 0.8, 0.95], - [5, 0.05, 0.15, 0.5, 0.75, 0.85], - ]; - valmin = [0.1, 0.2, 0.05]; - valmax = [1.0, 0.95, 0.85]; -} - -// Initialize everything and run -function main() { - const gl = initWebGL(); - if (!gl) return; - - loadFile(); // Load example data - - console.log(courbe); - console.log(nc); - - display(gl); // Render the curves -} - -// Run the WebGL program -window.onload = main;