I want to draw cylinders edges so instead of using a InstancedMesh
I want to use a InstancedBufferGeometry
as its attributes can be reused for the edges.
But I’m having a problem: the cylinders aren’t drawn.
The cylinders matrix is an equivalent to new Matrix4().setPosition(...).lookAt(...).scale(1, 1, cylinderHeight)
.
My code is the following:
const cylindersCenters = new Float32Array(coords.length / 2 * 16);
const up = new Vector3(0, 1, 0);
for (let i = 0; i < coords.length / 2; i++) {
const startCoordinate = new Vector3(...coords[i * 2]);
const endCoordinate = new Vector3(...coords[i * 2 + 1]);
const cylinderHeight = startCoordinate.distanceTo(endCoordinate);
const z = new Vector3().subVectors(endCoordinate, startCoordinate);
const x = new Vector3().crossVectors(up, z);
const y = new Vector3().crossVectors(z, x);
cylindersCenters[i * 8] = x.x;
cylindersCenters[i * 8 + 1] = x.y;
cylindersCenters[i * 8 + 2] = x.z;
cylindersCenters[i * 8 + 4] = y.x;
cylindersCenters[i * 8 + 5] = y.y;
cylindersCenters[i * 8 + 6] = y.z;
cylindersCenters[i * 8 + 8] = z.x * cylinderHeight;
cylindersCenters[i * 8 + 9] = z.y * cylinderHeight;
cylindersCenters[i * 8 + 10] = z.z * cylinderHeight;
cylindersCenters[i * 8 + 12] = startCoordinate.x;
cylindersCenters[i * 8 + 13] = startCoordinate.y;
cylindersCenters[i * 8 + 14] = startCoordinate.z;
cylindersCenters[i * 8 + 15] = 1;
}
const cylinderGeometry = new InstancedBufferGeometry().copy(new CylinderGeometry());
cylinderGeometry.instanceCount = coords.length / 2;
cylinderGeometry.setAttribute(
'instanceMatrix',
new InstancedBufferAttribute(cylindersCenters, 4)
);
const cylinders = new Mesh(
cylinderGeometry,
new MeshLambertMaterial({
onBeforeCompile: (shader) => {
shader.vertexShader = `
attribute mat4 instanceMatrix;
void main() {
vec4 mvPosition = modelViewMatrix * instanceMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
`;
shader.fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
}
})
);
What I’m doing wrong?