WebGL编程指南-28 利用层次模型实现机械臂模拟动画

1.demo效果

请添加图片描述

2.实现要点

绘制两个机械臂,通过↑ ↓ ← →分别控制上臂与下臂的rotation转角,当下臂旋转时上臂也会跟着旋转,上臂旋转时下臂则不会
<子节点模型变换> = <父节点的模型变换> x <自身模型变换>

3.demo代码

//单模型关节
const VSHADER_SOURCE = `
//顶点位置信息
attribute vec4 a_Position;
//顶点法向量信息
attribute vec4 a_Normal;
//Mvp矩阵
uniform mat4 u_MvpMatrix;
//模型矩阵
uniform mat4 u_ModelMatrix;
//逆转置矩阵
uniform mat4 u_ReverseMatrix;
//计算过的法线
varying vec3 v_Normal;
//顶点颜色
varying vec4 v_Color;

void main() {
    gl_Position = u_MvpMatrix*a_Position;
    v_Normal = normalize(vec3(u_ReverseMatrix * a_Normal));
    v_Color = vec4(1.0,0.4,0.0,1.0);
}
`;

const FSHADER_SOURCE = `
precision mediump float;

varying vec3 v_Normal;
varying vec4 v_Color;

//平行光光源方向
uniform vec3 u_LightDirection;
//平行光颜色
uniform vec3 u_LightColor;
//环境光颜色
uniform vec3 u_AmbientLight;
void main() {
    //漫反射
    float cosL = max(dot(u_LightDirection,v_Normal),0.0);
    //反射光颜色
    vec3 lightColor = u_LightColor*v_Color.rgb*cosL;
    vec3 ambientLight = u_AmbientLight*v_Color.rgb;
    gl_FragColor = vec4(lightColor+ambientLight,v_Color.a);
}
`;
const vertexData = {
  position : new Float32Array([
    1.5, 10.0, 1.5, -1.5, 10.0, 1.5, -1.5,  0.0, 1.5,  1.5,  0.0, 1.5, // v0-v1-v2-v3 front
    1.5, 10.0, 1.5,  1.5,  0.0, 1.5,  1.5,  0.0,-1.5,  1.5, 10.0,-1.5, // v0-v3-v4-v5 right
    1.5, 10.0, 1.5,  1.5, 10.0,-1.5, -1.5, 10.0,-1.5, -1.5, 10.0, 1.5, // v0-v5-v6-v1 up
    -1.5, 10.0, 1.5, -1.5, 10.0,-1.5, -1.5,  0.0,-1.5, -1.5,  0.0, 1.5, // v1-v6-v7-v2 left
    -1.5,  0.0,-1.5,  1.5,  0.0,-1.5,  1.5,  0.0, 1.5, -1.5,  0.0, 1.5, // v7-v4-v3-v2 down
    1.5,  0.0,-1.5, -1.5,  0.0,-1.5, -1.5, 10.0,-1.5,  1.5, 10.0,-1.5  // v4-v7-v6-v5 back
]),
normal : 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, // v0-v1-v2-v3 front
    1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0, // v0-v3-v4-v5 right
    0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0, // v0-v5-v6-v1 up
    -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
    0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0, // v7-v4-v3-v2 down
    0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0  // v4-v7-v6-v5 back
]),
color : new Float32Array([]),
indices : new Uint8Array([
    0, 1, 2,   0, 2, 3,    // front
    4, 5, 6,   4, 6, 7,    // right
    8, 9,10,   8,10,11,    // up
    12,13,14,  12,14,15,    // left
    16,17,18,  16,18,19,    // down
    20,21,22,  20,22,23     // back
])
 }

 const mvpMat = {
  model : new Matrix4().setIdentity(),
  view : new Matrix4().setLookAt(0.0, 0.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0),
  pres : new Matrix4().setPerspective(50.0, 1, 1.0, 100),
  pv : function () {
      return new Matrix4().setIdentity().multiply(this.pres)
                                  .multiply(this.view);
  },
  mvp : function () {
      return new Matrix4().setIdentity().multiply(this.pres)
                                          .multiply(this.view)
                                          .multiply(this.model);
  }
 }

 const light = {
  lightColor : new Vector3([1.0, 1.0, 1.0]),
  lightDir : new Vector3([0.5, 3.0, 4.0]),
  AmbientLight : new Vector3([0.2, 0.2, 0.2])
 }
const initArrayBuffer = (gl, buffer, name, num, type) => {
  const buf = gl.createBuffer();
  //绑定target
  gl.bindBuffer(gl.ARRAY_BUFFER, buf);
  //赋值
  gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
  const location = gl.getAttribLocation(gl.program, name);
  //传值
  gl.vertexAttribPointer(location, num, type, false, 0, 0);
  //启用
  gl.enableVertexAttribArray(location);
};
const initElementBuffer = (gl,data)=>{
  const buf = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
  return true;
}
const initParLight= (gl, light) =>{
  const u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
  const u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
  const u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');

  gl.uniform3fv(u_LightColor, light.lightColor.elements);
  gl.uniform3fv(u_LightDirection, new Vector3(light.lightDir.elements).normalize().elements);
  gl.uniform3fv(u_AmbientLight, light.AmbientLight.elements);

  return true;
}
//设置法线的逆转置矩阵
const setReverseMat = (gl,modelMat)=>{
  const u_ReverseMatrix = gl.getUniformLocation(gl.program, 'u_ReverseMatrix');
  gl.uniformMatrix4fv(u_ReverseMatrix, false, new Matrix4().setInverseOf(modelMat).transpose().elements);
  return true;
}
// 画图
function draw (gl, n) {
  gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}
//设置模型视图矩阵
const setMVPMatrix = (gl,mvpMat) =>{
  const u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMat.mvp().elements);

  //model触发逆转置矩阵变化
  setReverseMat(gl, mvpMat.model);

  return true;
}
// 画层次模型
const drawLayer=(gl, mvpMat, layer, n)=>{
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  //arm1
  mvpMat.model.setTranslate(0.0, -12.0, 0.0).rotate(layer.armAngle, 0.0, 1.0, 0.0);
  setMVPMatrix(gl, mvpMat);
  draw(gl, n);
  //arm2
  mvpMat.model.translate(0.0, layer.armLength, 0.0).rotate(layer.jointAngle, 0.0, 0.0, 1.0);
  mvpMat.model.scale(1.3, 1.0, 1.3);
  setMVPMatrix(gl, mvpMat);
  draw(gl, n);
}
const bindKeydown=(gl, mvpMat, layer, n)=>{
  document.onkeydown = function(evt) {
    switch ( evt.keyCode ) {
        case 38 : //up
            if ( layer.jointAngle < 135.0 ) {
                layer.jointAngle += layer.angleStep;
            }
            break;
        case 40 : //down
            if ( layer.jointAngle > -135.0 ) {
                layer.jointAngle -= layer.angleStep;
            }
            break;
        case 37 : //left
            layer.armAngle = (layer.armAngle - layer.angleStep) % 360;
            break;
        case 39 : //right
            layer.armAngle = (layer.armAngle + layer.angleStep) % 360;
            break;
        default : return;
    }
    drawLayer(gl, mvpMat, layer, n);
}
}


const main = () => {
  const canvas = document.getElementById('webgl');
  const gl = canvas.getContext('webgl');
  debugger
  if ( !initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE) ) {
      console.error('Failed to init shaders!');
      return ;
  }

  //1=>初始化缓冲区 顶点
  initArrayBuffer(gl, vertexData.position, 'a_Position', 3, gl.FLOAT);
  // initArrayBuffer(gl, vertexData.color, 'a_Color', 3, gl.FLOAT);
  //初始化法线缓冲区
  initArrayBuffer(gl, vertexData.normal, 'a_Normal', 3, gl.FLOAT);
  initElementBuffer(gl, vertexData.indices);
  // 2=>设置模型视图范围矩阵
  setMVPMatrix(gl, mvpMat);
  // 3=>设置光照
  initParLight(gl, light);
  //4=>画图
  gl.enable(gl.DEPTH_TEST);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  //绘制顶点数
  const n = vertexData.indices.length;

  const layer = {
      armAngle : 0.0,
      jointAngle : 0.0,
      armLength : 10.0,
      angleStep : 3.0
  }

  //1=>bindEvent
  bindKeydown(gl, mvpMat, layer, n);
  //2=>画层次模型
  drawLayer(gl, mvpMat, layer, n);
};
main();

4.复杂的机械手臂

在上面的基础上,我们添加了更多关节,大体逻辑是一致的,只不过整体更加复杂了

5.demo效果

在这里插入图片描述

6.demo代码

//Chapter09
//temp 03

//jointModel - 手臂多关节模型
// 使用不同的position指定绘制部件
// 1.=> 直接绘制 //画一个部件 写入一次ARRAY_BUFFER
// 2.=> 先写入ARRAY_BUFFER //画部件的时候切换buf 即可 (推荐-内存最优)

var VSHADER = `
    attribute vec4 a_Position;
    // attribute vec4 a_Color;
    attribute vec4 a_Normal;
    uniform mat4 u_MvpMatrix;
    uniform mat4 u_ModelMatrix;
    uniform mat4 u_ReverseMatrix;
    // varying vec4 v_Position;
    varying vec4 v_Color;
    varying vec3 v_Normal;
    void main () {
        gl_Position = u_MvpMatrix * a_Position;
        
        //光照计算
        //法向量
        v_Normal = normalize( vec3(u_ReverseMatrix * a_Normal) );
        //变化坐标
        // v_Position = u_ModelMatrix * a_Position;

        v_Color = vec4(1.0, 0.4, 0.0, 1.0);
    }
`;

var FSHADER = `
    precision mediump float;
    uniform vec3 u_LightColor;
    uniform vec3 u_LightDirection;
    uniform vec3 u_AmbientLight;
    // varying vec4 v_Position;
    varying vec4 v_Color;
    varying vec3 v_Normal;
    void main () {
        //cos
        float cosLight = max( dot(u_LightDirection, v_Normal), 0.0 );
        //光颜色
        vec3 lightColor = u_LightColor * v_Color.rgb * cosLight;
        //环境光
        vec3 ambientColor = u_AmbientLight * v_Color.rgb;

        gl_FragColor = vec4( lightColor + ambientColor, v_Color.a);
    }
`;

var vertexData = {
    vertices_base : new Float32Array([ // Base(10x2x10)
        5.0, 2.0, 5.0, -5.0, 2.0, 5.0, -5.0, 0.0, 5.0,  5.0, 0.0, 5.0, // v0-v1-v2-v3 front
        5.0, 2.0, 5.0,  5.0, 0.0, 5.0,  5.0, 0.0,-5.0,  5.0, 2.0,-5.0, // v0-v3-v4-v5 right
        5.0, 2.0, 5.0,  5.0, 2.0,-5.0, -5.0, 2.0,-5.0, -5.0, 2.0, 5.0, // v0-v5-v6-v1 up
        -5.0, 2.0, 5.0, -5.0, 2.0,-5.0, -5.0, 0.0,-5.0, -5.0, 0.0, 5.0, // v1-v6-v7-v2 left
        -5.0, 0.0,-5.0,  5.0, 0.0,-5.0,  5.0, 0.0, 5.0, -5.0, 0.0, 5.0, // v7-v4-v3-v2 down
        5.0, 0.0,-5.0, -5.0, 0.0,-5.0, -5.0, 2.0,-5.0,  5.0, 2.0,-5.0  // v4-v7-v6-v5 back
    ]),

    vertices_arm1 : new Float32Array([  // Arm1(3x10x3)
        1.5, 10.0, 1.5, -1.5, 10.0, 1.5, -1.5,  0.0, 1.5,  1.5,  0.0, 1.5, // v0-v1-v2-v3 front
        1.5, 10.0, 1.5,  1.5,  0.0, 1.5,  1.5,  0.0,-1.5,  1.5, 10.0,-1.5, // v0-v3-v4-v5 right
        1.5, 10.0, 1.5,  1.5, 10.0,-1.5, -1.5, 10.0,-1.5, -1.5, 10.0, 1.5, // v0-v5-v6-v1 up
        -1.5, 10.0, 1.5, -1.5, 10.0,-1.5, -1.5,  0.0,-1.5, -1.5,  0.0, 1.5, // v1-v6-v7-v2 left
        -1.5,  0.0,-1.5,  1.5,  0.0,-1.5,  1.5,  0.0, 1.5, -1.5,  0.0, 1.5, // v7-v4-v3-v2 down
        1.5,  0.0,-1.5, -1.5,  0.0,-1.5, -1.5, 10.0,-1.5,  1.5, 10.0,-1.5  // v4-v7-v6-v5 back
    ]),

    vertices_arm2 : new Float32Array([  // Arm2(4x10x4)
        2.0, 10.0, 2.0, -2.0, 10.0, 2.0, -2.0,  0.0, 2.0,  2.0,  0.0, 2.0, // v0-v1-v2-v3 front
        2.0, 10.0, 2.0,  2.0,  0.0, 2.0,  2.0,  0.0,-2.0,  2.0, 10.0,-2.0, // v0-v3-v4-v5 right
        2.0, 10.0, 2.0,  2.0, 10.0,-2.0, -2.0, 10.0,-2.0, -2.0, 10.0, 2.0, // v0-v5-v6-v1 up
        -2.0, 10.0, 2.0, -2.0, 10.0,-2.0, -2.0,  0.0,-2.0, -2.0,  0.0, 2.0, // v1-v6-v7-v2 left
        -2.0,  0.0,-2.0,  2.0,  0.0,-2.0,  2.0,  0.0, 2.0, -2.0,  0.0, 2.0, // v7-v4-v3-v2 down
        2.0,  0.0,-2.0, -2.0,  0.0,-2.0, -2.0, 10.0,-2.0,  2.0, 10.0,-2.0  // v4-v7-v6-v5 back
    ]),

    vertices_palm : new Float32Array([  // Palm(2x2x6)
        1.0, 2.0, 3.0, -1.0, 2.0, 3.0, -1.0, 0.0, 3.0,  1.0, 0.0, 3.0, // v0-v1-v2-v3 front
        1.0, 2.0, 3.0,  1.0, 0.0, 3.0,  1.0, 0.0,-3.0,  1.0, 2.0,-3.0, // v0-v3-v4-v5 right
        1.0, 2.0, 3.0,  1.0, 2.0,-3.0, -1.0, 2.0,-3.0, -1.0, 2.0, 3.0, // v0-v5-v6-v1 up
        -1.0, 2.0, 3.0, -1.0, 2.0,-3.0, -1.0, 0.0,-3.0, -1.0, 0.0, 3.0, // v1-v6-v7-v2 left
        -1.0, 0.0,-3.0,  1.0, 0.0,-3.0,  1.0, 0.0, 3.0, -1.0, 0.0, 3.0, // v7-v4-v3-v2 down
        1.0, 0.0,-3.0, -1.0, 0.0,-3.0, -1.0, 2.0,-3.0,  1.0, 2.0,-3.0  // v4-v7-v6-v5 back
    ]),

    vertices_finger : new Float32Array([  // Fingers(1x2x1)
        0.5, 2.0, 0.5, -0.5, 2.0, 0.5, -0.5, 0.0, 0.5,  0.5, 0.0, 0.5, // v0-v1-v2-v3 front
        0.5, 2.0, 0.5,  0.5, 0.0, 0.5,  0.5, 0.0,-0.5,  0.5, 2.0,-0.5, // v0-v3-v4-v5 right
        0.5, 2.0, 0.5,  0.5, 2.0,-0.5, -0.5, 2.0,-0.5, -0.5, 2.0, 0.5, // v0-v5-v6-v1 up
        -0.5, 2.0, 0.5, -0.5, 2.0,-0.5, -0.5, 0.0,-0.5, -0.5, 0.0, 0.5, // v1-v6-v7-v2 left
        -0.5, 0.0,-0.5,  0.5, 0.0,-0.5,  0.5, 0.0, 0.5, -0.5, 0.0, 0.5, // v7-v4-v3-v2 down
        0.5, 0.0,-0.5, -0.5, 0.0,-0.5, -0.5, 2.0,-0.5,  0.5, 2.0,-0.5  // v4-v7-v6-v5 back
    ]),
    normal : 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, // v0-v1-v2-v3 front
        1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0, // v0-v3-v4-v5 right
        0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0, // v0-v5-v6-v1 up
        -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
        0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0, // v7-v4-v3-v2 down
        0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0  // v4-v7-v6-v5 back
    ]),
    color : new Float32Array([]),
    indices : new Uint8Array([
        0, 1, 2,   0, 2, 3,    // front
        4, 5, 6,   4, 6, 7,    // right
        8, 9,10,   8,10,11,    // up
        12,13,14,  12,14,15,    // left
        16,17,18,  16,18,19,    // down
        20,21,22,  20,22,23     // back
    ])
};

var mvpMat = {
    model : new Matrix4().setIdentity(),
    view : new Matrix4().setLookAt(20.0, 10.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0),
    pres : new Matrix4().setPerspective(50.0, 1, 1.0, 100),
    pv : function () {
        return new Matrix4().setIdentity().multiply(this.pres)
                                    .multiply(this.view);
    },
    mvp : function () {
        return new Matrix4().setIdentity().multiply(this.pres)
                                            .multiply(this.view)
                                            .multiply(this.model);
    }
};

var light = {
    lightColor : new Vector3([1.0, 1.0, 1.0]),
    lightDir : new Vector3([0.5, 3.0, 4.0]),
    AmbientLight : new Vector3([0.2, 0.2, 0.2])
}

var segments_buf = null;

function loadWEBGL () {
    var canvas = document.getElementById('webgl');
    var gl = canvas.getContext('webgl');

    if ( !initShaders(gl, VSHADER, FSHADER) ) {
        console.error('Failed to init shaders!');
        return ;
    }

    //1=>初始化缓冲区
    initArrayBuffer(gl, vertexData.normal, 'a_Normal', 3, gl.FLOAT);
    initElementBuffer(gl, vertexData.indices);
    // 2=>设置模型视图范围矩阵
    setMVPMatrix(gl, mvpMat);
    // 3=>设置光照
    initParLight(gl, light);
    //4=>画图
    gl.enable(gl.DEPTH_TEST);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    var n = vertexData.indices.length;

    var layer = {
        arm1_jointAngle : 110.0,
        arm2_jointAngle : 45.0,
        palm_jointAngle : 0.0,
        finger1_jointAngle : 0.0,
        finger2_jointAngle : 0.0,
        angleStep : 3.0
    }

    //1=>bindEvent
    bindKeydown(gl, mvpMat, layer, n);
    //2=>画层次模型
    // drawLayer(gl, mvpMat, layer, n);
    segments_buf = initBufs(gl);
    drawLayer(gl, mvpMat, layer, n);
}

// 初始化缓冲区array_buffer数据
function initArrayBuffer (gl, data, name, num, type) {
    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    var loc = gl.getAttribLocation(gl.program, name);
    gl.vertexAttribPointer(loc, num, type, false, 0, 0);
    gl.enableVertexAttribArray(loc);
    return true;
}
// 初始化缓冲区element_array_buffer数据
function initElementBuffer (gl, data) {
    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
    return true;
}

// 将data写入到buf中
// 返回一个buf => 后续切换ARRAY_BUFFER
function getBuffer (gl, data) {
    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    return buf;
}

// 获取对应attribute变量的设置函数
// 设置函数通过options来切换数据并开启写入着色器
function setBufferToArray ( gl, name ) {
    var loc = gl.getAttribLocation(gl.program, name);

    return (buf) => {
        gl.bindBuffer(gl.ARRAY_BUFFER, buf);
        gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(loc);
        return true;
    }
}

function initBufs (gl) {
    var segments_buf = {
        baseBuf : getBuffer(gl, vertexData.vertices_base),
        arm1Buf : getBuffer(gl, vertexData.vertices_arm1),
        arm2Buf : getBuffer(gl, vertexData.vertices_arm2),
        palmBuf : getBuffer(gl, vertexData.vertices_palm),
        fingerBuf : getBuffer(gl, vertexData.vertices_finger),
        switchBuf : setBufferToArray(gl, 'a_Position')
    };
    return segments_buf;
}

// 设置模型视图范围矩阵
function setMVPMatrix (gl, mvpMat) {
    var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
    gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMat.mvp().elements);

    //model触发逆转置矩阵变化
    setReverseMat(gl, mvpMat.model);

    return true;
}

// 初始化平行光源和环境光源
function initParLight (gl, light) {
    var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
    var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
    var u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');

    gl.uniform3fv(u_LightColor, light.lightColor.elements);
    gl.uniform3fv(u_LightDirection, new Vector3(light.lightDir.elements).normalize().elements);
    gl.uniform3fv(u_AmbientLight, light.AmbientLight.elements);

    return true;
}

// 设置变化矩阵 => 引起mvp发生变化
function setReverseMat (gl, modelMat) {
    var u_ReverseMatrix = gl.getUniformLocation(gl.program, 'u_ReverseMatrix');
    gl.uniformMatrix4fv(u_ReverseMatrix, false, new Matrix4().setInverseOf(modelMat).transpose().elements);
    return true;
}

// 设置键盘监听
// 修改layer值 => 重绘layer
function bindKeydown (gl, mvpMat, layer, n) {
    document.onkeydown = function(evt) {
        switch ( evt.keyCode ) {
            case 38 : //up
                if ( layer.arm2_jointAngle < 135.0 ) {
                    layer.arm2_jointAngle += layer.angleStep;
                }
                break;
            case 40 : //down
                if ( layer.arm2_jointAngle > -135.0 ) {
                    layer.arm2_jointAngle -= layer.angleStep;
                }
                break;
            case 37 : //left
                layer.arm1_jointAngle = (layer.arm1_jointAngle - layer.angleStep) % 360;
                break;
            case 39 : //right
                layer.arm1_jointAngle = (layer.arm1_jointAngle + layer.angleStep) % 360;
                break;
            case 65 : //a
                layer.palm_jointAngle = (layer.palm_jointAngle - layer.angleStep) % 360;
                break;
            case 68 : //d
                layer.palm_jointAngle = (layer.palm_jointAngle + layer.angleStep) % 360;
                break;
            case 87 : //w
                if ( layer.finger1_jointAngle < 60.0 ) {
                    layer.finger1_jointAngle += layer.angleStep;
                    layer.finger2_jointAngle = -layer.finger1_jointAngle;
                }
                break;
            case 83 : //s
                if ( layer.finger1_jointAngle > -60.0 ) {
                    layer.finger1_jointAngle -= layer.angleStep;
                    layer.finger2_jointAngle = -layer.finger1_jointAngle;
                }
                break;
            default : return;
        }
        drawLayer(gl, mvpMat, layer, n);
    }
}

// 画图
function draw (gl, n) {
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}

function drawSegment (gl, n, mvpMat, data) {
    // initArrayBuffer(gl, data, 'a_Position', 3, gl.FLOAT);
    setMVPMatrix(gl, mvpMat);
    draw(gl, n);
}

// 画层次模型
function drawLayer (gl, mvpMat, layer, n) {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    //base
    var baseHeight = 2.0;
    mvpMat.model.setTranslate(0.0, -12.0, 0.0);
    //切换部件buf
    segments_buf.switchBuf(segments_buf.baseBuf);
    //
    drawSegment(gl, n, mvpMat, vertexData.vertices_base);
    //arm1
    var arm1Length = 10.0;
    mvpMat.model.translate(0.0, baseHeight, 0.0)
                .rotate(layer.arm1_jointAngle, 0.0, 1.0, 0.0);
    segments_buf.switchBuf(segments_buf.arm1Buf);    
    drawSegment(gl, n, mvpMat, vertexData.vertices_arm1);
    //arm2
    var arm2Length = 10.0;
    mvpMat.model.translate(0.0, arm1Length, 0.0)
                .rotate(layer.arm2_jointAngle, 0.0, 0.0, 1.0);
    segments_buf.switchBuf(segments_buf.arm2Buf);
    drawSegment(gl, n, mvpMat, vertexData.vertices_arm2);
    //palm
    var palmLength = 2.0;
    mvpMat.model.translate(0.0, arm2Length, 0.0)
                .rotate(layer.palm_jointAngle, 0.0, 1.0, 0.0);
    segments_buf.switchBuf(segments_buf.palmBuf);
    drawSegment(gl, n, mvpMat, vertexData.vertices_palm);
    //finger 
    mvpMat.model.translate(0.0, palmLength, 0.0);
    //finger-1
    pushMatrix(mvpMat.model);
    mvpMat.model.translate(0.0, 0.0, 2.0)
                .rotate(layer.finger1_jointAngle, 1.0, 0.0, 0.0);
    segments_buf.switchBuf(segments_buf.fingerBuf);
    drawSegment(gl, n, mvpMat, vertexData.vertices_finger);
    mvpMat.model.set(popMatrix());
    //finger-2
    mvpMat.model.translate(0.0, 0.0, -2.0)
                .rotate(layer.finger2_jointAngle, 1.0, 0.0, 0.0);
    drawSegment(gl, n, mvpMat, vertexData.vertices_finger);
}

ready(loadWEBGL);

GOBAL_MATRIXS = [];
function pushMatrix(mat) {
    GOBAL_MATRIXS.push((new Matrix4).set(mat));
}
function popMatrix() {
    return GOBAL_MATRIXS.pop();
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值