Web 技术研究所

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

WebGL 来画个环面吧~

  知识要是学了不用就容易忘掉,今天就来写个WebGL的环面绘制来练练手。之前有做过球体的绘制,不过球体那玩意儿太简单了,这回的环面就稍微复杂了点,因为要自己计算法向量。当然你也可以完全使用公式,不过我不喜欢那样,这种东西自己思考比较有趣。
  环面就是面包圈的形状,可惜我没有面包圈的贴图素材,要不然我一定把它做成面包圈。从函数上分析的话它是由两个圆函数嵌套出来的。一个是整个面包圈的圆,这里就姑且称它为大圆吧。然后是截面的圆,就称它为小圆了。这两个圆函数嵌套起来就成了环面。
  如果是在3DMax之类的软件中,我们会这样做:先在垂直于y轴的平面上绘制一个小圆,然后以y轴为中心做车削。这个思路很容易绘制,因为在垂直于y轴的平面上绘制圆我们可以选择在xy平面或yz平面上绘制,这样小圆就很容易绘制了。对于大圆的绘制,我们甚至可以直接用旋转矩阵对小圆做y轴的旋转计算,不过那样的方式计算量太大了,JavaScritp不适合做矩阵运算。既然对物体的旋转不方便,我们就把物体分成点来计算。在小圆上的每一点分别绕y轴选择一圈,这样就可以得到环面了。
  环面的顶点坐标是画出来了,但是还需要计算法向量。观察环面可以发现,法向量其实就是小圆圆心到小圆圆上顶点的方向,既然是两个坐标的方向,那我们就把他们作为向量来计算。目标位置向量减去源位置向量就等于源到目标的方向向量了嘛。这里的源是小圆的圆心位置,所以我们还需要计算小圆的圆心位置。这个计算就更简单了,它直接就是大圆本身。因为小圆本来就是以大圆圆上的所有点为圆心画出来的。
  知道了上面这些我们就可以开始写代码了,下面是计算的代码
//m和n是大圆和小圆的顶点数量
//r1和r2是大圆和小圆的半径
var obj=(function(m,n,r1,r2){
  var i,j,o={
    position:[],normal:[]
  },f=function(i,j){
    var a,b,x,y,z,x0,z0;
    //坐标系转换
    a=(i/m)*2*Math.PI,b=(j/n)*2*Math.PI;
    //计算小圆圆上坐标
    r=Math.cos(b)*r2+r1,y=Math.sin(b)*r2;
    //对小圆上每一点绕y轴旋转的坐标
    x=Math.cos(a)*r,z=Math.sin(a)*r;
    //计算大圆圆上坐标(小圆圆心坐标)
    x0=Math.cos(a)*r1,z0=Math.sin(a)*r1;
    //顶点位置
    o.position.push(x,y,z);
    //法向量
    o.normal.push(x-x0,y,z-z0);
  };
  //遍历两个圆
  for(i=0;i<m;i++)for(j=0;j<n;j++)
    f(i,j),f(i+1,j),f(i,j+1),f(i+1,j+1),f(i+1,j),f(i,j+1);
  //保存总顶点量,绘制时要用到
  o.count=m*n*6;
  return o;
})(52,32,2,0.8);

  核心的部分上面已经说了,其它部分都是和以前的球体绘制类似,我就不再说了。最后是完整的实例。

  WebGL来画个环面吧
网名:
3.84.186.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^