CG实验6 交互与动画

来源:互联网 发布:linux tcpdump 编辑:程序博客网 时间:2024/06/05 18:05

1.实验目的和要求

  • 目的:了解交互与动画的基本思想,掌握交互与动画的常见实现方法;
  • 要求:读懂WebGL交互与动画示范代码,实现简单的交互与动画程序。

2. 实验过程

(1) 示范代码1为交互实例:在鼠标点击的位置上绘制出点;示范代码2为动画实例:三角形按照恒定的速度(45度/秒)旋转。结合示范代码,学习理解交互与动画的基本思想与实现;
(2) 结合示范代码1,将示范代码2改为根据鼠标来控制三角形的旋转;

3.实验结果

示范代码1的结果如下图所示:
TranslatedTriangle
示范代码2如下图所示:
Note

4.实验分析

请根据教材内容、网络资源及示范代码,简单分析下交互与动画的实现原理与方法。

5.实验代码

gl-matrix.js 下载地址:http://oty0nwcbq.bkt.clouddn.com/gl-matrix.js

(1) 鼠标点击交互绘点

(i) ClickedPoints.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html>    <head>        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />        <title>Draw a point with a mouse click</title>    </head>    <script id="vertex-shader" type="x-shader/x-vertex">         attribute vec4 a_Position;           void main() {            gl_Position = a_Position ;            gl_PointSize = 10.0;          }         </script>        <script id="fragment-shader" type="x-shader/x-fragment">             void main() {                 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);              }         </script>    <body onload="startup()">        <canvas id="myGLCanvas" width="600" height="600">        </canvas>    </body>        <script type="text/javascript" src="gl-matrix.js"></script>    <script type="text/javascript" src="ClickedPoints.js"></script></html>

(ii) ClickedPoints.js

var gl;function startup(){    var canvas = document.getElementById('myGLCanvas');//获取<canvas>元素    gl = createGLContext(canvas);    setupShaders();  // // Get the storage location of a_Position var a_Position = gl.getAttribLocation(gl.program, 'a_Position'); if (a_Position < 0) {   console.log('Failed to get the storage location of a_Position');   return; } // Register function (event handler) to be called on a mouse press canvas.onmousedown = function(ev){ click(ev, gl, canvas, a_Position); }; // Specify the color for clearing <canvas> gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear <canvas> gl.clear(gl.COLOR_BUFFER_BIT); } var g_points = []; // The array for the position of a mouse press function click(ev, gl, canvas, a_Position) {   var x = ev.clientX; // x coordinate of a mouse pointer   var y = ev.clientY; // y coordinate of a mouse pointer   var rect = ev.target.getBoundingClientRect() ;   x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);   y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);   // Store the coordinates to g_points array   g_points.push(x); g_points.push(y);   // Clear <canvas>   gl.clear(gl.COLOR_BUFFER_BIT);   var len = g_points.length;   for(var i = 0; i < len; i += 2) {     // Pass the position of a point to a_Position variable     gl.vertexAttrib3f(a_Position, g_points[i], g_points[i+1], 0.0);     // Draw     gl.drawArrays(gl.POINTS, 0, 1);   } }function createGLContext(canvas) {  var names = ["webgl", "experimental-webgl"];  var context = null;  for (var i=0; i < names.length; i++) {    try {      context = canvas.getContext(names[i]); //获取webgl context绘图上下文    } catch(e) {}    if (context) {      break;    }  }  if (context) {    context.viewportWidth = canvas.width;    context.viewportHeight = canvas.height;  } else {    alert("Failed to create WebGL context!");  }  return context;}function setupShaders() {      var vertexShader = loadShader(gl.VERTEX_SHADER, "vertex-shader");  var fragmentShader = loadShader(gl.FRAGMENT_SHADER, "fragment-shader");  var shaderProgram = gl.createProgram();  gl.attachShader(shaderProgram, vertexShader);  gl.attachShader(shaderProgram, fragmentShader);  gl.linkProgram(shaderProgram);  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {    alert("Failed to setup shaders");  }  gl.useProgram(shaderProgram);  gl.program= shaderProgram;}function loadShader(type, ShaderId) {  var shaderScript = document.getElementById( ShaderId );    var shader = gl.createShader(type);    gl.shaderSource( shader, shaderScript.text );    gl.compileShader( shader );  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {      alert("Error compiling shader" + gl.getShaderInfoLog(shader));      gl.deleteShader(shader);         return null;  }  return shader;  }

(2) 三角形旋转动画

(i) RotatingTriangle.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html>    <head>        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />        <title>Continually Rotate A Triangle</title>    </head>    <script id="vertex-shader" type="x-shader/x-vertex">        attribute vec4 a_Position;        uniform mat4 u_ModelMatrix;          void main() {             gl_Position = u_ModelMatrix * a_Position;         }        </script>       <script id="fragment-shader" type="x-shader/x-fragment">            void main() {                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);             }        </script>    <body onload="startup()">        <canvas id="myGLCanvas" width="600" height="600">        </canvas>    </body>    <script type="text/javascript" src="gl-matrix.js"></script>    <script type="text/javascript" src="RotatingTriangle.js">    </script></html>

(ii) RotatingTriangle.js

var gl;// Rotation angle (degrees/second)var ANGLE_STEP = 45.0;var modelMatrixI = mat4.create();function startup(){    var canvas = document.getElementById('myGLCanvas');//获取<canvas>元素    gl = createGLContext(canvas);    setupShaders();   // Write the positions of vertices to a vertex shader  var n = initVertexBuffers(gl);  if (n < 0) {    console.log('Failed to set the positions of the vertices');    return;  }  // Specify the color for clearing <canvas>  gl.clearColor(0.0, 0.0, 0.0, 1.0);  // Get storage location of u_ModelMatrix  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');  if (!u_ModelMatrix) {     console.log('Failed to get the storage location of u_ModelMatrix');    return;  }  // Current rotation angle  var currentAngle = 0.0;  // Model matrix  var modelMatrix = mat4.create();  // Start drawing  var tick = function() {    currentAngle = animate(currentAngle);  // Update the rotation angle    draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle    requestAnimationFrame(tick, canvas); // Request that the browser calls tick  };  tick(); } function initVertexBuffers(gl) {    var vertices = new Float32Array ([      0, 0.5,   -0.5, -0.5,   0.5, -0.5    ]);    var n = 3;   // The number of vertices    // Create a buffer object    var vertexBuffer = gl.createBuffer();    if (!vertexBuffer) {      console.log('Failed to create the buffer object');      return -1;    }    // Bind the buffer object to target    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);    // Write date into the buffer object    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);    // Assign the buffer object to a_Position variable    var 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;    }    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);    // Enable the assignment to a_Position variable    gl.enableVertexAttribArray(a_Position);    return n;  }  function draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {    // Set the rotation matrix    //modelMatrix.setRotate(currentAngle, 0, 0, 1); // Rotation angle, rotation axis (0, 0, 1)    var radian = Math.PI * currentAngle / 180.0; // Convert to radians    mat4.rotate(modelMatrix, modelMatrixI, radian, [0, 0 , 1]);    // Pass the rotation matrix to the vertex shader    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);    // Clear <canvas>    gl.clear(gl.COLOR_BUFFER_BIT);    // Draw the rectangle    gl.drawArrays(gl.TRIANGLES, 0, n);  }  // Last time that this function was called  var g_last = Date.now();  function animate(angle) {    // Calculate the elapsed time    var now = Date.now();    var elapsed = now - g_last;    g_last = now;    // Update the current rotation angle (adjusted by the elapsed time)    var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;    return newAngle %= 360;  }function createGLContext(canvas) {  var names = ["webgl", "experimental-webgl"];  var context = null;  for (var i=0; i < names.length; i++) {    try {      context = canvas.getContext(names[i]); //获取webgl context绘图上下文    } catch(e) {}    if (context) {      break;    }  }  if (context) {    context.viewportWidth = canvas.width;    context.viewportHeight = canvas.height;  } else {    alert("Failed to create WebGL context!");  }  return context;}function setupShaders() {        var vertexShader = loadShader(gl.VERTEX_SHADER, "vertex-shader");    var fragmentShader = loadShader(gl.FRAGMENT_SHADER, "fragment-shader");    var shaderProgram = gl.createProgram();    gl.attachShader(shaderProgram, vertexShader);    gl.attachShader(shaderProgram, fragmentShader);    gl.linkProgram(shaderProgram);    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {      alert("Failed to setup shaders");    }    gl.useProgram(shaderProgram);    gl.program= shaderProgram;  }  function loadShader(type, ShaderId) {    var shaderScript = document.getElementById( ShaderId );      var shader = gl.createShader(type);      gl.shaderSource( shader, shaderScript.text );      gl.compileShader( shader );    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {        alert("Error compiling shader" + gl.getShaderInfoLog(shader));        gl.deleteShader(shader);           return null;    }    return shader;    }
原创粉丝点击