// Prénoms, noms et matricule des membres de l'équipe: // - Prénom1 NOM1 (matricule1) // - Prénom2 NOM2 (matricule2) // déclaration d'une structure pour contenir toutes les variables globales var glob = { }; addTransformation(null, "rotation"); addTransformation(null, "translation"); addTransformation(null, "scale"); function addTrans(event) { var div = document.createElement("div"); var text = document.createTextNode("Plopiloup"); var transdiv = document.getElementById("transformations"); div.appendChild(text); transdiv.appendChild(div); } function addTransformation(event, type) { var table = document.getElementById("trans-list"); var glyphClass; switch (type) { case "rotation": glyphClass = "glyphicon-repeat"; break; case "translation": glyphClass = "glyphicon-move"; break; case "scale": glyphClass = "glyphicon-resize-small"; break; default: glyphClass = "glyphicon-alert"; console.log("Unknown transformation type " + type); break; } var tr = table.insertRow(-1); tr.classList.add(type); var span = document.createElement("span"); span.classList.add("glyphicon", glyphClass); var td = tr.insertCell(-1); td.appendChild(span); var param = ["x", "y", "z", "𝜃"]; for (var i in param) { td = tr.insertCell(-1); if (param[i] === "𝜃" && type !== "rotation") break; var input = document.createElement("input"); input.setAttribute("type", "text"); input.setAttribute("value", type === "scale" ? "1" : "0"); input.setAttribute("name", param[i]); input.setAttribute("class", "form-control"); input.addEventListener("change", updateTransformations, false); input.addEventListener("keyup", updateTransformations, false); td.appendChild(input); } var button = document.createElement('button'); button.classList.add("btn", "btn-danger", "btn-sm"); button.setAttribute("type", "button"); button.addEventListener("click", removeTransformation, false); span = document.createElement("span"); span.classList.add("glyphicon", "glyphicon-trash"); button.appendChild(span); tr.insertCell(-1).appendChild(button); } function removeTransformation(event) { var tr = event.target.parentNode.parentNode; tr.parentNode.removeChild(tr); updateTransformations(event); } function updateTransformations(event) { glob.transformations = []; var table = document.getElementById("trans-list"); var x,y,z,𝜃,row,type; for (var i = 1; i < table.rows.length; i++) { row = table.rows[i]; x = row.querySelector('input[name="x"]').value; y = row.querySelector('input[name="y"]').value; z = row.querySelector('input[name="z"]').value; 𝜃 = row.querySelector('input[name="𝜃"]'); if (𝜃 !== null) 𝜃 = 𝜃.value; type = row.className; glob.transformations.push({type: type, x: x, y: y, z: z, 𝜃: 𝜃}); } } function handleMouseDown(event) { glob.mouseDown = true; var rect = glob.canevas.getBoundingClientRect(); glob.positionSourisX = event.clientX - rect.left; glob.positionSourisY = event.clientY - rect.top; } function handleMouseUp(event) { glob.mouseDown = false; glob.positionSourisX = null; glob.positionSourisY = null; } function handleMouseMove(event) { if (!glob.mouseDown) return; var rect = glob.canevas.getBoundingClientRect(); glob.positionSourisX = event.clientX - rect.left; glob.positionSourisY = event.clientY - rect.top; } // // makeRepere // // Create a repere with vertices, normals and texCoords. Create VBOs for each as well as the index array. // Return an object with the following properties: // // normalObject WebGLBuffer object for normals // texCoordObject WebGLBuffer object for texCoords // vertexObject WebGLBuffer object for vertices // indexObject WebGLBuffer object for indices // numIndices The number of indices in the indexObject // function makeRepere(ctx) { // box // v2 // | // | // | // v0 o------v1 // / // v3 // // vertex coords array var vertices = new Float32Array( [ 0, 0, 0, 1, 0, 0, // v0 -> v1 vec X 0, 0, 0, 0, 1, 0, // v0 -> v2 vec Y 0, 0, 0, 0, 0, 1 ]// v0 -> v3 vec Z ); // colors array var colors = new Float32Array( [ 1, 0, 0, 1, 0, 0, // v0 -> v1 vec X 0, 1, 0, 0, 1, 0, // v0 -> v2 vec Y 0, 0, 1, 0, 0, 1 ]// v0 -> v3 vec Z ); // index array var indices = new Uint8Array( [ 0, 1, 2, 3, 4, 5 ] ); var retval = { }; retval.vertexObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject); ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW); retval.colorObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.colorObject); ctx.bufferData(ctx.ARRAY_BUFFER, colors, ctx.STATIC_DRAW); ctx.bindBuffer(ctx.ARRAY_BUFFER, null); retval.indexObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject); ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, indices, ctx.STATIC_DRAW); ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null); retval.numIndices = indices.length; return retval; } function TPchargerTextures() { // Charger une image utilisée comme texture. (Retourne un objet WebGLTexture) //glob.texture1 = loadImageTexture( gl, "images/Brouillard.jpg" ); //glob.texture2 = loadImageTexture( gl, "images/Exploration.jpg" ); //glob.texture3 = loadImageTexture( gl, "images/Modelisation.jpg" ); } function TPcreerModele() { // Créer une boîte. Au retour, 'glob.box' contient une structure avec // les VBOs pour les sommets, normales, coordonnées de texture et connectivité. glob.box = makeRepere( gl ); // Initialiser les attributs pour les sommets, les normales et les coordonnées de texture // (dans le même ordre qu'à l'appel à simpleSetup() dans la fonction TPinitialiser()) gl.enableVertexAttribArray( 0 ); gl.bindBuffer( gl.ARRAY_BUFFER, glob.box.vertexObject ); gl.vertexAttribPointer( 0, 3, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray( 1 ); gl.bindBuffer( gl.ARRAY_BUFFER, glob.box.colorObject ); gl.vertexAttribPointer( 1, 3, gl.FLOAT, false, 0, 0 ); // Lier le tableau de connectivité gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, glob.box.indexObject ); } function TPinitialiser() { // Initialiser webgl var gl = initWebGL( "tp-canevas" ); // L'identificateur du canevas if (!gl) return; glob.program = simpleSetup( gl, // Les identificateurs des deux nuanceurs "nuanceurSommets", "nuanceurFragments", // Les attributs utilisés par les nuanceurs (donnés dans le même ordre que leur indice) [ "vPosition", "vColor" ], // La couleur de fond et la profondeur [ 0x00/255, 0x2b/255, 0x36/255, 1 ], 100); // Les angles courants de rotation glob.angleRotX = 0, glob.angleRotY = 0, glob.angleRotZ = 0; // Les incréments à chaque affichage glob.incrRotX = 0.2; glob.incrRotY = 0.3; glob.incrRotZ = 0.4; // Créer les matrices nécessaires et assigner les assigner dans le programme glob.modelMatrix = mat4.create(); glob.viewMatrix = mat4.create(); glob.modelMatLoc = gl.getUniformLocation( glob.program, "mmodel" ); glob.viewMatLoc = gl.getUniformLocation( glob.program, "mview" ); glob.projMatLoc = gl.getUniformLocation( glob.program, "mproj" ); // terminer l'initialisation TPchargerTextures(); TPcreerModele(); glob.mouseDown = false; glob.positionSourisX = null; glob.positionSourisY = null; glob.canevas.onmousedown = handleMouseDown; glob.canevas.onmouseup = handleMouseUp; glob.canevas.onmousemove = handleMouseMove; glob.transformations = []; // Initialiser les variables uniformes pour les nuanceurs gl.uniform3f( gl.getUniformLocation( glob.program, "lightDir" ), 0, 0, 1 ); gl.uniform1i( gl.getUniformLocation( glob.program, "laTexture" ), 0 ); gl.uniform2f( gl.getUniformLocation( glob.program, "positionSouris" ), glob.positionSourisX, glob.positionSourisY ); return gl; } function TPafficherModele( gl ) { gl.uniform2f( gl.getUniformLocation( glob.program, "positionSouris" ), glob.positionSourisX, glob.canevas.height-glob.positionSourisY ); // Tracer le cube gl.drawElements( gl.LINES, glob.box.numIndices, gl.UNSIGNED_BYTE, 0 ); } function TPafficherScene(gl) { glob.perspectiveMatrix = mat4.create(); glob.perspectiveMatrix = mat4.perspective(glob.perspectiveMatrix, 70. * 3.14159 / 180., glob.canevas.width / glob.canevas.height, 0.01, 10 ); gl.uniformMatrix4fv(glob.projMatLoc, false, glob.perspectiveMatrix); // Effacer le canevas gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); // Définir la clôture 1 gl.viewport( 0, 0, glob.canevas.width, glob.canevas.height ); // Incrémenter les angles de rotation glob.angleRotX += glob.incrRotX; if ( glob.angleRotX >= 360.0 ) glob.angleRotX -= 360.0; glob.angleRotY += glob.incrRotY; if ( glob.angleRotY >= 360.0 ) glob.angleRotY -= 360.0; glob.angleRotZ += glob.incrRotZ; if ( glob.angleRotZ >= 360.0 ) glob.angleRotZ -= 360.0; // Construire la matrice de modélisation mat4.lookAt( glob.viewMatrix, [5, 5, 5], [0, 0, 0], [0, 1, 0] ); gl.uniformMatrix4fv(glob.viewMatLoc, false, glob.viewMatrix); mat4.identity(glob.modelMatrix); gl.uniformMatrix4fv(glob.modelMatLoc, false, glob.modelMatrix); TPafficherModele( gl ); for (var i = 0; glob.transformations.length > i; i++) { var t = glob.transformations[i]; var v = vec3.fromValues(t.x, t.y, t.z); switch(t.type) { case "rotation": mat4.rotate(glob.modelMatrix, glob.modelMatrix, glMatrix.toRadian(t.𝜃), v); break; case "translation": mat4.translate(glob.modelMatrix, glob.modelMatrix, v); break; case "scale": mat4.scale(glob.modelMatrix, glob.modelMatrix, v); break; default: console.log("Unknown transformation type : " + t.type); break; } gl.uniformMatrix4fv(glob.modelMatLoc, false, glob.modelMatrix); TPafficherModele( gl ); } //glob.modelMatrix.rotate( glob.angleRotX, 1.0, 0.0, 0.0 ); //glob.modelMatrix.setUniform(gl, glob.modelMatLoc, false); //TPafficherModele(gl); //glob.modelMatrix.rotate( glob.angleRotY, 0.0, 1.0, 0.0 ); //glob.modelMatrix.setUniform(gl, glob.modelMatLoc, false); //TPafficherModele(gl); //glob.modelMatrix.rotate( glob.angleRotZ, 0.0, 0.0, 1.0 ); //glob.modelMatrix.setUniform(gl, glob.modelMatLoc, false); //TPafficherModele( gl ); } var requestId; function TPdebut() { glob.canevas = document.getElementById('tp-canevas'); //glob.canevas = WebGLDebugUtils.makeLostContextSimulatingCanvas(c); // indiquer de perdre le contexte afin de tester //glob.canevas.loseContextInNCalls(15); glob.canevas.addEventListener('webglcontextlost', handleContextLost, false); glob.canevas.addEventListener('webglcontextrestored', handleContextRestored, false); var gl = TPinitialiser(); if ( !gl ) return; var displayFunc = function() { TPafficherScene(gl); requestId = window.requestAnimFrame( displayFunc, glob.canevas ); }; displayFunc(); function handleContextLost(e) { e.preventDefault(); clearLoadingImages(); if ( requestId !== undefined ) { window.cancelAnimFrame(requestId); requestId = undefined; } } function handleContextRestored() { TPinitialiser(); displayFunc(); } }