阅读 169

WebGL创建鼠标事件控制的旋转立方体

通过鼠标事件,来控制立方体的旋转。通过鼠标点击事件来控制立方体是否旋转,通过键盘键码值来控制立方体的运动方向。 所以在立方体的绘制的demo里。添加如下代码就行。

1、常规方式实现旋转

  • init方法中添加键盘事件,通过键盘事件来控制立方体向左、向右、向下和向上运动。
let rotate = false;
let xaxis = 0, yaxis = 0;
function init() {
    ...
    document.addEventListener('keydown', (event) => {
        const keyCode = event.keyCode;
        switch (keyCode) {
            case 38:
                //向上旋转
                xaxis = 1;
                yaxis=0;
                break;
            case 40:
                //向下旋转
                xaxis = -1;
                yaxis=0;
                break;
            case 37:
                //想左旋转
                yaxis = -1;
                xaxis = 0;
                break;
            case 39:
                //想右旋转
                yaxis = 1;
                xaxis = 0;
                break;
        }
    })
    document.addEventListener('click',()=>{
        rotate=!rotate;
        render(gl,program);
    })
}
复制代码
  • render函数中添加动画
function render(gl, program, count = 36) {
    tranlate(gl, program);
    //设置清屏颜色为黑色。
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, 0);
    if(!rotate) return;
    requestAnimationFrame(() => {
        render(gl, program, count);
    })
}
复制代码
  • 在旋转函数中修改旋转角度
let angley = 30.0, anglex = 30;;
function tranlate(gl, program, unit = 1) {
    const radx = anglex * Math.PI / 180;
    const cosx = Math.cos(radx);
    const sinx = Math.sin(radx);
    const mx = gl.getUniformLocation(program, 'mx');
    const mxArr = new Float32Array([
        1, 0, 0, 0, 0, cosx, -sinx, 0, 0, sinx, cosx, 0, 0, 0, 0, 1
    ])
    gl.uniformMatrix4fv(mx, false, mxArr);

    const rady = angley * Math.PI / 180;
    const cosy = Math.cos(rady);
    const siny = Math.sin(rady);
    const my = gl.getUniformLocation(program, 'my');
    const myArr = new Float32Array([
        cosy, 0, -siny, 0, 0, 1, 0, 0, siny, 0, cosy, 0, 0, 0, 0, 1
    ])
    gl.uniformMatrix4fv(my, false, myArr);
    angley += yaxis;
    anglex += xaxis;
}
复制代码

2、通过矩阵来实现立方体的旋转

所以这里我们需要创建矩阵,创建矩阵有两种投影方式,正交投影和透射投影。这里采用的是正射投影。这里跟常规方法也就顶点着色器,inittranslate中的代码略有不同。 在下面的矩阵运算中用到了一个matrix的矩阵相关的库。库的链接地址为

  • 顶点着色器中的代码。这里就直接将矩阵相乘后的矩阵传递到顶点着色器中。
<script id="vertexShader" type="x-shader/x-vertex">
    //浮点数设置为中等精度
    precision mediump float;
    attribute vec3 apos;
    attribute vec4 acolor;
    varying vec4 vcolor;
    //uniform mat4 mx;
    //uniform mat4 my;
    uniform mat4 proj;
    void main() {
        //两个旋转矩阵、顶点齐次坐标连乘
        //gl_Position = mx*my*vec4(apos, 1);
        gl_Position = proj*vec4(apos, 1);
        vcolor=acolor;
    }
</script>
复制代码
  • init函数中的不同
let isrotate = false;
let xaxis = 0, yaxis = 0;
let projectionMatrix;
function init() {
    ...
    //创建正交投影矩阵
    const aspect = canvas.width / canvas.height;
    projectionMatrix = matrix.ortho(-aspect * 1, aspect * 1, -1, 1, 200, -200);
    ...
}
复制代码
  • rotate函数,通过矩阵运算来实现立方体的旋转。
let angley = 30, anglex = 30;
//单位矩阵
let mvp = matrix.identity();
function rotate(gl, program) {
    //先绕 Y 轴旋转矩阵。
    matrix.rotationY(angley * Math.PI / 180, mvp);
    //再绕 X 轴旋转
    matrix.multiply(
        mvp,
        matrix.rotationX(anglex * Math.PI / 180),
        mvp
    );
    //矩阵相乘
    matrix.multiply(projectionMatrix, mvp, mvp);
    const proj = gl.getUniformLocation(program, 'proj');
    gl.uniformMatrix4fv(proj, false, mvp);
    angley += yaxis;
    anglex += xaxis;
}
复制代码

效果图如下:

鼠标控制立方体的旋转.gif

文章分类
前端
文章标签