BufferGeometry not working

I’d like to draw thousands of cubes a time, InstancedMesh just allows to set the position (not the size of the cube), so I decided to use BufferGeometry and set the vertices and indices myself, but it’s not working.
It gives the error Uncaught TypeError: t.onUploadCallback is not a function.

My code is the following:

const geometry = new BufferGeometry();

// vertices per cuboid * 3 / 2
const coordinates = new Float32Array(12 * coords.length);
// polygons per cuboid * 3 / 2
const indices = new Int16Array(18 * coords.length);

for (let i = 0; i < coords.length / 2; i++) {
	const startCoordinate = new Vector3(...coords[i * 2]);
	const endCoordinate = new Vector3(...coords[i * 2 + 1]);

	// vertex 0
	coordinates[i * 24] = startCoordinate.x;
	coordinates[i * 24 + 1] = startCoordinate.y;
	coordinates[i * 24 + 2] = startCoordinate.z;
	// vextex 1
	coordinates[i * 24 + 3] = endCoordinate.x;
	coordinates[i * 24 + 4] = startCoordinate.y;
	coordinates[i * 24 + 5] = startCoordinate.z;
	// vextex 2
	coordinates[i * 24 + 6] = startCoordinate.x;
	coordinates[i * 24 + 7] = endCoordinate.y;
	coordinates[i * 24 + 8] = startCoordinate.z;
	// vextex 3
	coordinates[i * 24 + 9] = endCoordinate.x;
	coordinates[i * 24 + 10] = endCoordinate.y;
	coordinates[i * 24 + 11] = startCoordinate.z;
	// vextex 4
	coordinates[i * 24 + 12] = startCoordinate.x;
	coordinates[i * 24 + 13] = startCoordinate.y;
	coordinates[i * 24 + 14] = endCoordinate.z;
	// vextex 5
	coordinates[i * 24 + 15] = endCoordinate.x;
	coordinates[i * 24 + 16] = startCoordinate.y;
	coordinates[i * 24 + 17] = endCoordinate.z;
	// vextex 6
	coordinates[i * 24 + 18] = startCoordinate.x;
	coordinates[i * 24 + 19] = endCoordinate.y;
	coordinates[i * 24 + 20] = endCoordinate.z;
	// vextex 7
	coordinates[i * 24 + 21] = endCoordinate.x;
	coordinates[i * 24 + 22] = endCoordinate.y;
	coordinates[i * 24 + 23] = endCoordinate.z;

	// polygon 0
	indices[i * 36] = i * 8;
	indices[i * 36 + 1] = i * 8 + 1;
	indices[i * 36 + 2] = i * 8 + 2;
	// polygon 1
	indices[i * 36 + 3] = i * 8 + 1;
	indices[i * 36 + 4] = i * 8 + 2;
	indices[i * 36 + 5] = i * 8 + 3;
	// polygon 2
	indices[i * 36 + 6] = i * 8 + 4;
	indices[i * 36 + 7] = i * 8 + 5;
	indices[i * 36 + 8] = i * 8 + 6;
	// polygon 3
	indices[i * 36 + 9] = i * 8 + 5;
	indices[i * 36 + 10] = i * 8 + 6;
	indices[i * 36 + 11] = i * 8 + 7;
	// polygon 4
	indices[i * 36 + 12] = i * 8 + 4;
	indices[i * 36 + 13] = i * 8;
	indices[i * 36 + 14] = i * 8 + 2;
	// polygon 5
	indices[i * 36 + 15] = i * 8;
	indices[i * 36 + 16] = i * 8 + 6;
	indices[i * 36 + 17] = i * 8 + 2;
	// polygon 6
	indices[i * 36 + 18] = i * 8 + 5;
	indices[i * 36 + 19] = i * 8 + 1;
	indices[i * 36 + 20] = i * 8 + 7;
	// polygon 7
	indices[i * 36 + 21] = i * 8 + 1;
	indices[i * 36 + 22] = i * 8 + 7;
	indices[i * 36 + 23] = i * 8 + 3;
	// polygon 8
	indices[i * 36 + 24] = i * 8 + 4;
	indices[i * 36 + 25] = i * 8 + 5;
	indices[i * 36 + 26] = i * 8;
	// polygon 9
	indices[i * 36 + 27] = i * 8 + 5;
	indices[i * 36 + 28] = i * 8;
	indices[i * 36 + 29] = i * 8 + 1;
	// polygon 10
	indices[i * 36 + 30] = i * 8 + 6;
	indices[i * 36 + 31] = i * 8 + 7;
	indices[i * 36 + 32] = i * 8 + 2;
	// polygon 11
	indices[i * 36 + 33] = i * 8 + 7;
	indices[i * 36 + 34] = i * 8 + 2;
	indices[i * 36 + 35] = i * 8 + 3;
}

geometry.setAttribute(
	'position',
	new BufferAttribute(coordinates, 3)
);

geometry.setIndex(indices);

return new Mesh(
	geometry,
	new MeshLambertMaterial({
		color: new Color(1, 1, 1).getHex()
	})
);

coords is an array of the corners of the cube (e.g: [(x1min, y1min, z1min), (x1max, y1max, z1max), (x2min, y2min, z2min), (x2max, y2max, z2max)]).

I’m using r124.

What am I doing wrong?

Do you mind demonstrating with a live example the runtime error? Use this as a starter template: https://jsfiddle.net/vy29n6aj/

@Mugen87 this is the live example: https://jsfiddle.net/gwqcj29f/2/

Use a box 1 x 1 x 1 and scale each instance of it individually.

Example: Edit fiddle - JSFiddle - Code Playground
Picture:

@prisoner849 really thanks, but I’d love to know what is wrong with my polygon by polygon BufferGeometry (also, I guess that’d be faster). Anyway, if I didn’t discover how to do it (and anyone which read this post too) I’ll use your approach.

indices has to be Array, so instantiate it like this: const indices = [];
As internally. three.js has that check in .setIndex() method. So, when you pass Int16Array, Array.isArray() returns false and a buffer attribute for .index won’t be created.

Fixed example: https://jsfiddle.net/prisoner849/yocuesz6/

2 Likes

Thanks @prisoner849 this solved my problem, now I just need to fix the weird behavior, I guess that was my mistake when creating the indices.

The strange behavior is shown in the following live example: https://jsfiddle.net/jmc2edzL/

Yes, my mistake in creating the indices, working great now!

1 Like