Javascript 3JS中的可交互网格
我需要画一个矩形(不是二次的)“支撑”网格:用户可以悬停在这个网格的一块瓷砖上,然后在那里放置一个特定的对象。例如,我将鼠标悬停在(x:0y:15)上,然后单击,我在(x:0y:15)处得到一个对象 该网格使用平面几何体绘制,并绘制为线框(在r58中) 在我将代码库更新为r94之后,我现在得到的是三角形,而不是平面不同分片的四边形 我尝试了以下方法: 绘制线条:查看GridHelper的源代码后,我创建了一个矩形版本。它看起来很不错,但瓷砖的命中检测已关闭。命中检测是通过光线投射器实现的。我认为问题是,只有当鼠标确实在一条线上时,才会检测到这些线。使用PlaneGeometry,鼠标可以位于瓷砖内部,并且可以正确检测几何体 使用纹理绘制PlaneGeometry我尝试的下一个想法是使用带有自定义纹理的PlaneGeometry,如下所示:Javascript 3JS中的可交互网格,javascript,three.js,Javascript,Three.js,我需要画一个矩形(不是二次的)“支撑”网格:用户可以悬停在这个网格的一块瓷砖上,然后在那里放置一个特定的对象。例如,我将鼠标悬停在(x:0y:15)上,然后单击,我在(x:0y:15)处得到一个对象 该网格使用平面几何体绘制,并绘制为线框(在r58中) 在我将代码库更新为r94之后,我现在得到的是三角形,而不是平面不同分片的四边形 我尝试了以下方法: 绘制线条:查看GridHelper的源代码后,我创建了一个矩形版本。它看起来很不错,但瓷砖的命中检测已关闭。命中检测是通过光线投射器实现的。我认
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;博士我需要一个网格,它的行为类似于平面几何体(命中检测),但只绘制正方形而不是三角形 您可以使用线构建网格。为此,您可以创建
THREE.PlaneBufferGeometry()
并更改其.index
属性。然后将此几何图形与THREE.LineSegments()
一起使用
以及更改索引的源代码:
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;
}
});
这种指数的“重写”到底是做什么的?删除三角形还是。。。?顺便说一句,很酷picture@morpheus05它允许您使用所谓的技术。因此,没有面,只有线。有了这一点,使用raycaster的方法应该改变为使用线条。或者,你可以有一个普通的平面(对于raycaster)和一个网格。在参考链接中,请查看JSFIDLE及其源代码。
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"}));