【问题标题】:Interactable Grid in ThreeJs三个 Js 中的交互式网格
【发布时间】:2018-07-16 21:11:26
【问题描述】:

我需要绘制一个矩形(不是二次方)“支撑”网格:用户可以悬停该网格的一个图块并将特定对象放置在那里。例如。我将鼠标悬停在 (x:0 y:15) 上并单击,我在 (x:0 y:15) 处得到一个对象。

这个 Grid 使用 PlaneGeometry 完成并绘制为线框(在 r58 中)。

new THREE.PlaneGeometry(x,y,16, 9);
var mat = new THREE.MeshBasicMaterial({
    color: 0x004488,
    wireframe: true
});
mat.color.r = r;
mat.color.g = g;
mat.color.b = b;

在我将代码库更新为 r94 后,我现在得到的是三角形而不是四边形,用于平面的不同图块。

我尝试了以下方法:

画线:看了GridHelper的源码后,我创建了一个矩形的版本。它看起来很不错,但瓷砖的命中检测已关闭。命中检测是使用 Raycaster 实现的。我认为问题是,只有当鼠标实际上在一条线上时,这条线才会被检测到。使用 PlaneGeometry 鼠标可以在瓦片内并且正确地检测到几何图形。

使用纹理绘制 PlaneGeometry 我尝试的下一个想法是使用带有自定义纹理的 PlaneGeometry,如下所示:

let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.height = 32;
canvas.width = 32;
context.beginPath();
context.rect(0, 0, 32, 32);
context.lineWidth = 2;
context.strokeStyle = color.getStyle();
context.stroke();

// canvas contents will be used for a texture
let texture = new THREE.Texture(canvas);

texture.needsUpdate = true;

let material = new THREE.MeshBasicMaterial();
// let material = new THREE.LineBasicMaterial();
material.map = texture;
material.flatShading = true;
material.fog = false;
material.lights = false;
material.side = THREE.DoubleSide;
material.transparent = true;

return material;

现在命中检测就像 r54 一样具有魅力,但现在如果视角平坦,它看起来很丑:

我的想法已经不多了,所以我希望能得到一些提示或其他东西,我可以如何绘制漂亮的网格,这是一种几何图形,因此可以使用当前的命中检测系统。

TL;DR; 我需要一个网格,它的行为类似于 PlaneGeometry(命中检测),但只绘制正方形而不是三角形。

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    你可以有一个网格,由线条构成。为此,您可以创建 THREE.PlaneBufferGeometry() 并更改其 .index 属性。然后将此几何图形与THREE.LineSegments() 一起使用。

    Reference

    以及更改索引的源代码:

      Object.assign(THREE.PlaneBufferGeometry.prototype, {
        toGrid: function() {
          let segmentsX = this.parameters.widthSegments || 1;
          let segmentsY = this.parameters.heightSegments || 1;
          let indices = [];
          for (let i = 0; i < segmentsY + 1; i++) {
            let index11 = 0;
            let index12 = 0;
            for (let j = 0; j < segmentsX; j++) {
              index11 = (segmentsX + 1) * i + j;
              index12 = index11 + 1;
              let index21 = index11;
              let index22 = index11 + (segmentsX + 1);
              indices.push(index11, index12);
              if (index22 < ((segmentsX + 1) * (segmentsY + 1) - 1)) {
                indices.push(index21, index22);
              }
            }
            if ((index12 + segmentsX + 1) <= ((segmentsX + 1) * (segmentsY + 1) - 1)) {
              indices.push(index12, index12 + segmentsX + 1);
            }
          }
          this.setIndex(indices);
          return this;
        }
      });
    

    使用:

    var planeGeom = new THREE.PlaneBufferGeometry(10, 5, 10, 5).toGrid();
    var gridPlane = new THREE.LineSegments(planeGeom, new THREE.LineBasicMaterial({color: "yellow"}));
    

    【讨论】:

    • 这个索引的“重写”究竟是做什么的?删除三角形或...?顺便说一句,非常酷的图片
    • @morpheus05 它允许您使用所谓的"indexed lines" 技术。因此,没有面孔,只有线条。有了这个,应该将使用 raycaster 的方法更改为使用线条。或者,你可以有一个普通的平面(用于光线投射器)和一个网格。在参考链接中,查看 jsfiddle 及其源代码。
    猜你喜欢
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2020-02-22
    相关资源
    最近更新 更多