3D grid of lines

Hello! I was asked by someone on SO to post this as a demo here. Here’s a simple way to make a 3D grid of lines from a grid of points, using the index attribute of BufferGeometry.

The interesting bit is:

let xSize = 3;
let ySize = 4;
let zSize = 5;
let n = xSize * ySize * zSize;

let geometry = new THREE.BufferGeometry();

function mapTo3D(i) {
	let z = Math.floor(i / (xSize * ySize));
	i -= z * xSize * ySize;
	let y = Math.floor(i / xSize);
	let x = i % xSize;
	return { x: x, y: y, z: z };
}

function mapFrom3D(x, y, z) {
	return x + y * xSize + z * xSize * ySize;
}

let positions = [];
for (let i = 0; i < n; i++) {
	let p = mapTo3D(i);
	positions.push((p.x - xSize / 2) / xSize);
	positions.push((p.y - ySize / 2) / ySize);
	positions.push((p.z - zSize / 2) / zSize);
}
let positionAttribute = new THREE.Float32BufferAttribute(positions, 3);
geometry.addAttribute("position", positionAttribute);

let indexPairs = [];
for (let i = 0; i < n; i++) {
	let p = mapTo3D(i);
	if (p.x + 1 < xSize) {
		indexPairs.push(i);
		indexPairs.push(mapFrom3D(p.x + 1, p.y, p.z));
	}
	if (p.y + 1 < ySize) {
		indexPairs.push(i);
		indexPairs.push(mapFrom3D(p.x, p.y + 1, p.z));
	}
	if (p.z + 1 < zSize) {
		indexPairs.push(i);
		indexPairs.push(mapFrom3D(p.x, p.y, p.z + 1));
	}
}
geometry.setIndex(indexPairs);
let lines = new THREE.LineSegments(geometry, new THREE.LineBasicMaterial());
scene.add(lines);

A dynamic 2D grid would be very similar (simpler).

One example of this being useful is this thing I made.

6 Likes

Hi!
Thanks for sharing :wink:

Just OOI, how would you turn this from a perspective to an orthographic view?

Just use OrthographicCamera instead of PerspectiveCamera. You’ll also want to turn off sizeAttenuation for PointsMaterial.

2 Likes

Thanks for the speedy reply. I need to play with the OthographicCamera positions to get something to actually show up and rotate with the mouse, but I can try that :slight_smile:

FYI eventually I’d like to adapt this for drawing mathematical magic cubes.

(BTW there’s a typo in the PEN: sizeAttentuation: false)