2

我使用 xtk 在 webgl 画布中可视化医疗数据。目前我正在玩这节课:

第 10 课

这个库非常好,但没有很好的文档记录。我想摆脱那个 gui 并添加一些鼠标事件。如果我从 gui 加载网格,如何向网格添加鼠标事件?我其实不知道从哪里开始。开始使用这个库有点令人困惑......

我试过

mesh.click(function(){
    alert("yes");
  })

或者

mesh.mousedown(function(){
    alert("yes");
}
4

3 回答 3

4

WebGL 中呈现的对象不是 DOM 的一部分,因此不会像 DOM 元素那样生成事件。这意味着对于此类事件,您必须自己实现鼠标交互代码。

传统上,在 WebGL/OpenGL 中,这个过程被称为“挑选”,在线上有几个不错的资源。(例如:http ://webgldemos.thoughtsincomputation.com/engine_tests/picking )核心流程是这样的,不过:

  • 对于场景中的每个可拾取对象,为其分配一种颜色。把它放在某个查找表中
  • 将整个场景重新渲染为纹理,使用分配的颜色渲染每个可拾取对象
  • 渲染场景后,确定鼠标坐标并回读该 X/Y 处的纹理颜色。
  • 从查找表中获取与该颜色关联的对象。这是您的鼠标光标指向的对象!

如您所见,虽然从概念上讲这不是一个困难的方法,但它也涉及几个中级 WebGL 主题,例如渲染到纹理,因此通常不建议初学者使用。我不确定 xtk 中是否有任何功能可以帮助解决这个问题(老实说,在你发帖之前我从未听说过这个库),但我想这是你必须自己实现的东西。

于 2012-05-30T17:11:35.763 回答
3

不支持 DOM 事件,但您可以使用 xtk 来实现。看看这个 JSFiddle

http://jsfiddle.net/haehn/r7Ugf/

// create and initialize a 3D renderer
var r = new X.renderer3D();
r.init();

// create a cube and a sphere
cube = new X.cube();
sphere = new X.sphere();
sphere.center = [-20, 0, 0];

r.interactor.onMouseMove = function() {

    // grab the current mouse position
    var _pos = r.interactor.mousePosition;

    // pick the current object
    var _id = r.pick(_pos[0], _pos[1]);

    if (_id != 0) {

        // grab the object and turn it red
        r.get(_id).color = [1, 0, 0];

    } else {

        // no object under the mouse
        cube.color = [1, 1, 1];
        sphere.color = [1, 1, 1];

    }

    r.render();

}

r.interactor.onMouseDown = function(left, middle, right) {

    // only observe right mouse clicks        
    if (!right) return;

    // grab the current mouse position
    var _pos = r.interactor.mousePosition;

    // pick the current object
    var _id = r.pick(_pos[0], _pos[1]);

    if (_id == sphere.id) {

        // turn the sphere green
        sphere.color = [0, 1, 0];
        r.render();

    }

}

r.add(cube); // add the cube to the renderer
r.add(sphere); // and the sphere as well
r.render(); // ..and render it

容易,不是吗?

于 2012-05-30T18:06:17.920 回答
1

XTK 实现了 Toji 解释的拾取方式(即使用 frameBuffer,其中每个对象都以不同的 RGBA“颜色”呈现)。当您拥有少于 255^4 个对象时,它会起作用,所以几乎总是如此。还有其他方法,例如不投影,但我认为它们会更长。

因此,使用 X.renderer.pick 和 X.renderer.get 您可以在鼠标下找到对象并更改其属性。但是,目前您只能更改可视化属性(请参阅每个类中的setGettersetSetter),但不能移动 X.object(因为 X.object._transform 属性是私有的,并且还没有 getter/setter)。

处理这件事很有趣:为 X.object 的变换添加一对 getter/setter 将允许,例如,用户将医疗材料(由网格或其他东西建模)放在场景中并放置以测量距离或查看如果它适合手术或类似的东西。海恩不应该是个好主意吗?这是框架中的一个小改动。

于 2012-06-01T14:49:04.327 回答