码迷,mamicode.com
首页 > Web开发 > 详细

webgl圈中物体

时间:2016-08-04 01:34:28      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

这篇的标题非常不符合我的气质!

但是 如果带上那种 “不可能 姐姐 妹妹 君 套套 不要”等关键字标题的话 其他小伙伴就很难通过搜索引擎到这个地方来了!

所以还是使用这种简短大众的标题得了。。

 

注意标题中有个“圏” 字 我们讨论的并不是“选”

下面的圈中物体解决方案 其实已经把如何选中一个物体的问题一并搞定了

圈中物体 首先要有一条封闭曲线吧 那条曲线是由n个线段拼接起来的 我们要找到相交的那两条线段和那两条线段之间的所有线段 如图

 技术分享

相交的线段就是这两了 封闭曲线的起始和结束线段就是它们 不过还得截取它们的头或尾 绿色线段起始坐标替换为交点坐标  蓝色线段结束坐标替换为交点坐标

那么如何解决线段相交呢?

有好几种解决方案 我这里提供一种是利用直线参数式来解的 如下

p01=p0+v0*t

p11=p1+v1*s 

p0x+v0x*t=p1x+v1x*s

p0y+v0y*t=p1y+v1y*s

可以使用消元法来解 s 和 t 也可以使用 canvas曲线面片1 那种矩阵方法来解

如果 s和t同时大于0并且小于1  说明相交了 把s和t带进去可以计算出交点了

相交代码

Miku.lineCross = function(l1,l2){
      var t1,t2;
      var [v1,v2] = [
        new Miku.Vec(l1.x2-l1.x1 , l1.y2-l1.y1)
        ,new Miku.Vec(l2.x2-l2.x1 , l2.y2-l2.y1)
      ]
      const ar = [
        [v1.x,-v2.x]
        ,[v1.y,-v2.y]
      ];
      const res = Miku.Det2( ar , [l2.x1-l1.x1 , l2.y1-l1.y1]  );

      if(!res) return {cross:0};

      t1 = res[0],t2 = res[1];
      const o = {cross:t1>0&&t1<1&&t2>0&&t2<1,pos:0};
      if(o.cross){
        return o.pos = {
          x : l1.x1 + v1.x*t1
          ,y:l1.y1 + v1.y*t1
          ,xx:l2.x1 + v2.x*t2
          ,yy:l2.y1 + v2.y*t2
        }
        ,o;
      }
      return o;
    }

 

接下来要解决物体是不是被圈了

物体就是个任意多边形 所以你可以想到与多边形的边来做相交处理是吧。。然而并不能满足所有情况

因为 如果曲线包含了整个物体 但是它没有与任何边相交也算被圈中 又或者曲线全包含在物体内呢?

所以要换种方法了 我这里提供一种叫环绕数的解决方案 如下

技术分享

想象在上图那个封闭曲线内有一点P Pn是线段的端点 P的环绕数就可通过这个式子给出 如果结果是+=1  那就在内部

其实还可以用点乘给出结果 不过据我观察仅适用于凸边形。。

还有一种情况就是曲线全部在物体内部 那么Pn就是物体的顶点 反过来处理一边。。

环绕数代码(具体的可看后面给的源码)

for(let i = 0,dot;dot = ar[i++];){
  let n = 0;
  for(let j =0,l;l = this.cross_ar[j++];){
    let v1 = (new Miku.Vec(l.x1-dot.x , l.y1-dot.y)).normal();
    let v2 = (new Miku.Vec(l.x2-dot.x , l.y2-dot.y)).normal();
    n += asin(v1.cross(v2))*v;
  }
if(f(abs(n))) return 1;
}

这两关键问题就解决了

不过还要注意 这里用的是webgl接口 所以鼠标坐标还要规范下 代码

Miku(c).on(‘touchmove‘,e=>{
    var [x,y] = [(e.mouse_x-c.cx)/c.cx , -(e.mouse_y-c.cy)/c.cy];
    Xline.setRoute({x,y});
  });

cx cy是中心位置  xy值-1到1

 

给个 demo  

技术分享

其实 我们可以用上面的方法选中三维物体的

不过 如果要选中它们 首先要对鼠标坐标做投影矩阵的逆变换 把鼠标坐标投到三维上

然后给三维的物体来个包围圆或者是矩形 之后就可以用上面的方法来处理选中了 。。当然了 这不精确 不过也满足很多情况了

还有些其他方法 比如有基于像素的选中  以后相关demo会用上的  以后再说~

webgl圈中物体

标签:

原文地址:http://www.cnblogs.com/daidaidai/p/5734875.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!