加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Cesium学习笔记-WebGL篇02-选中对象

(2018-11-15 18:36:26)
标签:

cesium

webgl选中物体

分类: Cesium

基本上所有三维应用都需要用户能够交互地操纵三维物体,要这样做首先得允许用户选中物体。我们今天就来学习下在三维场景中如何实现选中物体。

Webgl最终呈现出来的只有一张纹理图显示在canvas容器内,我们如何利用这张纹理图片来分别是否选中呢?这里需要我们进行特殊处理,在《WebGL编程指南》教程中这样判断:

http://s2/mw690/006pZnPwzy7pdDU21RT61&690

相信所有webgl三维引擎都是这个核心思想吧。下面我们基于教程的示例,绘制三个点,点击判断是否选中点。

主要流程:

    //注册点击事件

    canvas.onmousedown = function (ev) {

        var x = ev.clientX, y = ev.clientY;

        var rect = ev.target.getBoundingClientRect();

        if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom) {

            var x_in_canvas = x - rect.left, y_in_canvas = rect.bottom - y;

            Draw(gl, n, vertices, colorsPicked);

            var pixels = getFixels(gl, x_in_canvas, y_in_canvas);

            var pickedObj = check([p1, p2, p3], pixels);

            if (pickedObj) alert('The cube was selected! ' + pickedObj.id);

            Draw(gl, n, vertices, colors);

        }

}

监听鼠标事件,在鼠标事件中做成一下逻辑:

1判断点击再canvas区域

2使用pickcolor重新绘制

3获取点击处当前像素值

4判断是否选中物体

5使用正常颜色重绘

判断点击再canvas区域

var x = ev.clientX, y = ev.clientY;

        var rect = ev.target.getBoundingClientRect();

        if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom)

使用pickcolor重新绘制

我们在定义顶点对象时,添加点击颜色这一属性:

function PickedPoint(options) {

    this.id = parseInt(Math.random() * 1000);

    this.position = defaultValue(options.position, [Math.random(), Math.random()]);

    this.pickColor = defaultValue(options.pickColor, [parseInt(Math.random() * 255.0), parseInt(Math.random() * 255.0), parseInt(Math.random() * 255.0)]);

    this.color = defaultValue(options.color, [parseInt(Math.random() * 255.0), parseInt(Math.random() * 255.0), parseInt(Math.random() * 255.0)]);

}

当鼠标处于点击状态时,用此颜色重绘,这里每个颜色有rgba四个分量,每个分量取值0-255,因此我们可以用rgba区分256*256*256*256个对象,这足够使用了。

获取点击处当前像素值

function getFixels(gl, x, y) {

    //

    var pixels = new Uint8Array(4);

    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

    return pixels;

}

gl.readPixels解释:

http://s9/mw690/006pZnPwzy7pdDVASs8f8&690

示例中我们返回1*1大小,即一个像素的rgba值。

判断是否选中物体

function check(ps, pixels) {

    for (var i = 0; i < ps.length; i++) {

        var r = ps[i].pickColor[0];

        var g = ps[i].pickColor[1];

        var b = ps[i].pickColor[2];

        if (r == pixels[0] && g == pixels[1] && b == pixels[2]) {

            return ps[i];

        }

    }

    return null;

}

将像素值与所有点对象匹配,如果rgb(这里我们没有使用a值)相同则说明选中改对象。

使用正常颜色重绘

Draw(gl, n, vertices, colors);

使用正常颜色重绘。

下面试效果:

http://s10/mw690/006pZnPwzy7pdDWNVPP69&690

示例源码:github源码

我的学习公众号也开通,感兴趣的小伙伴们可以加关注:giserYZ2SS

http://s11/small/006pZnPwzy7pdE0O7MK1a&690

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有