Reputation: 4872
I need to draw a rectangular (not quadratic) "support" grid: Users can hover an tile of this grid and place a specific object there. E.g. I hover over (x:0 y:15) and I click, I get an object at (x:0 y:15).
This Grid was done with a PlaneGeometry and drawn as a wireframe (in 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;
After I updated the code base to r94 I get now triangles instead of quads for the different tiles of the plane.
I tried the following:
Drawing lines: After looking at the source code of GridHelper, I created a rectangular version. It looks very nice but the hit detection of a tile is off. Hit detection is implemented with a Raycaster. I think the problem is, thaht lines only get detected if the mouse is actually over a line. With the PlaneGeometry the mouse could be inside a tile and the geometry was detected correctly.
Drawing a PlaneGeometry with a Texture The next think I tried was using a PlaneGeometry with a custom Texture, like this:
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;
Now hit detection works like a charm, as it did with r54, but now it looks very ugly if the viewing angle is flat:
I'm running out of ideas, so I would appreciate a hint or something how I can draw nice looking grid, which is one geometry so the current hit detection system can be used.
TL;DR; I need a grid, which behaves like a PlaneGeometry (hit detection) but only drawing squares instead of triangles.
Upvotes: 3
Views: 3055
Reputation: 17596
You can have a grid, built from lines. For that, you can create THREE.PlaneBufferGeometry()
and change its .index
propery. Then use this geometry with THREE.LineSegments()
.
And the source code for changing the indices:
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;
}
});
Using:
var planeGeom = new THREE.PlaneBufferGeometry(10, 5, 10, 5).toGrid();
var gridPlane = new THREE.LineSegments(planeGeom, new THREE.LineBasicMaterial({color: "yellow"}));
Upvotes: 3