Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

WebGL(拾肆) 最简单的鼠标操作

  鼠标事件只能精确到CANVAS,如果要对绘制出来的东西也用上鼠标事件就需要自己计算了。乍看之下这个计算很复杂吧?但是如果有好好推导过投射矩阵就不会这么认为了。既然可以把三维的东西投射到二维上,我们当然也可以把二维的坐标投射到三维上了。
  鼠标在CANVAS上只是一个二维的坐标,要把这个坐标还原成原始视椎体上的三维坐标,可以把它补上齐次项,再使用投射矩阵的逆矩阵来对鼠标坐标做变换。
{ r*tan(a)000 }
0tan(a)00
000(n-f)/(2*f*n)
00-1(n+f)/(2*f*n)

  其实,使用逆矩阵做这个运算都大材小用了,因为鼠标坐标不需要计算z坐标。既然只要计算x和y,直接计算会更简单。而且触碰的计算是在CPU上完成的,不是在着色器中。也就是说,它是在JavaScript中的,而JavaScript没有着色器中那么方便的矩阵计算,特意构造成矩阵反而更麻烦。我的例子中就是直接计算的,下面是关键代码
//把所有要绘制的物体对象化方便保存物体的属性
var objs=[]; //存放对象的数组
for(i=-1;i<=1;i++)for(j=-1;j<=1;j++){ //循环创建对象
  objs.push({
    rot:0,x:i*3,y:j*3,z:-18, //循环变量作为物体的坐标值
    draw:function(){ //定义绘制函数
      var that=this;
      this.hitTest(function(){ //调用碰撞并传入回调函数
        that.rot+=0.1; //如果触碰检查成功,则让物体旋转
      });
      //下面是基本的绘制,这里就不说了
      s=Math.sin(this.rot),c=Math.cos(this.rot);
      webgl.uniformMatrix4fv(tra,false,[
        c,0,s,0, 0,1,0,0, -s,0,c,0, this.x,this.y,this.z,1
      ]);
      webgl.drawArrays(webgl.TRIANGLES,0,count);
    },hitTest:function(f){
      var x,y,i,j,r=1; //r是球的半径
      //这个x和y的计算基本上等于逆矩阵的计算了
      //这里的MX和MY是处理过的鼠标坐标
      x=MX/4*Math.abs(this.z),y=MY/4*Math.abs(this.z);
      //我使用了x和y与物体的坐标差来判断触碰的
      //如果坐标差小于r就判断为碰撞并调用回调函数
      //你也可以使用距离判断,不过要多一个取模运算
      if(x+r>this.x&&x-r<this.x&&y+r>this.y&&y-r<this.y)f();
    }
  });
};
  这个代码的说明基本都在注释里了。如果有推导过投射矩阵就会知道,在投射矩阵中,x和y坐标的计算其实就是乘上cot(a)再除以z,逆运算就只要把这个过程反过来就可以了(a是视角的一半)。之后是触碰的计算,3D中的触碰计算很复杂,我这里用了最简单的坐标差触碰计算,也可以是用距离触碰计算。其实复杂物体的触碰计算也是用这些做基本的触碰计算去逼近的。比如一个触碰计算优秀的人物模型就是使用很多个距离触碰和坐标差触碰组合而成的。
  代码中还有一个MX和MY没说,它们当然不可能是直接的鼠标坐标。直接的鼠标坐标连坐标系都不同的,当然无法使用。下面是MX和MY的获取和计算 //记录鼠标位置
var MX,MY,CW=canvas.width,CH=canvas.height;
canvas.onmousemove=function(e){
  MX=e.layerX*2/CW-1,MY=-e.layerY*2/CH+1;
};
  这个代码很简单吧,就是一个鼠标事件而已。鼠标坐标是二维屏幕坐标系,左上角是原点,y方向向下。由于这个坐标我们需要用作投射的逆变换,所以必须规范化设备坐标才行。也就是说,CANVAS里面的坐标系必须变换成中间为原点,x方向向右,y方向向上才行。所以就需要做这些操作,里面的基本数学计算我就不解释了。这个代码中我还使用了不符合W3C标准的layer,不过支持WebGL的火狐和Chrome都支持它,如果你是W3C的忠实拥护者可以换个获取方式。

  其他代码都是基础的了,我就不再说了。最后是完整例子
  WebGL最简单的鼠标操作
网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^