Currently, I am in the process of developing a WebGL game using Three.js. In order to enhance performance, I have made the decision to transition from using THREE.Geometry
to utilizing THREE.BufferGeometry
. However, after making this change, I encountered an issue where the mesh is not rendering as expected. Below, I have included the relevant portions of my code for reference. Interestingly, when reverting back to a regular geometry setup, everything works perfectly.
The game I'm working on is voxel-based, where each face of every cube has been pre-created as a standard THREE.Geometry
. The function positionVertices
is responsible for taking the vertices and faces from each face geometry, positioning them accordingly to correspond with the voxel, and then generating the buffer data required for the THREE.BufferGeometry
. Although there are no error messages or warnings displayed, the final mesh fails to display. It seems probable that the issue stems more from my limited knowledge in 3D graphics programming rather than a fault within Three.js itself. At this point, my assumption is that the problem might be related to incorrect indexes. Removing the indexes reveals the object, but half of the triangles have their normals facing in the opposite direction.
Chunk.prototype.positionVertices = function( position, vertices, faces, vertexBuffer, indexBuffer, normalBuffer, colorBuffer ) {
var vertexOffset = vertexBuffer.length / 3;
for( var i = 0; i < faces.length; ++i ) {
indexBuffer.push( faces[i].a + vertexOffset );
indexBuffer.push( faces[i].b + vertexOffset );
indexBuffer.push( faces[i].c + vertexOffset );
normalBuffer.push( faces[i].vertexNormals[0].x );
normalBuffer.push( faces[i].vertexNormals[0].y );
normalBuffer.push( faces[i].vertexNormals[0].z );
normalBuffer.push( faces[i].vertexNormals[1].x );
normalBuffer.push( faces[i].vertexNormals[1].y );
normalBuffer.push( faces[i].vertexNormals[1].z );
normalBuffer.push( faces[i].vertexNormals[2].x );
normalBuffer.push( faces[i].vertexNormals[2].y );
normalBuffer.push( faces[i].vertexNormals[2].z );
}
var color = new THREE.Color();
color.setRGB( 0, 0, 1 );
for( var i = 0; i < vertices.length; ++i ) {
vertexBuffer.push( vertices[i].x + position.x );
vertexBuffer.push( vertices[i].y + position.y );
vertexBuffer.push( vertices[i].z + position.z );
colorBuffer.push( color.r );
colorBuffer.push( color.g );
colorBuffer.push( color.b );
}
};
// This will need to change when more than one type of block exists.
Chunk.prototype.buildMesh = function() {
var cube = new THREE.Mesh();
var vertexBuffer = []; // [0] = v.x, [1] = v.y, etc
var faceBuffer = [];
var normalBuffer = [];
var colorBuffer = [];
for( var k = 0; k < this.size; ++k )
for( var j = 0; j < this.size; ++j )
for( var i = 0; i < this.size; ++i ) {
// Iterates over all of the voxels in this chunk and calls
// positionVertices( position, vertices, faces, vertexBuffer, indexBuffer, normalBuffer, colorBuffer ) for each face in the chunk
}
var bGeo = new THREE.BufferGeometry();
bGeo.attributes = {
index: {
itemSize: 1,
array: new Uint16Array( faceBuffer ),
numItems: faceBuffer.length
},
position: {
itemSize: 3,
array: new Float32Array( vertexBuffer ),
numItems: vertexBuffer.length
},
normal: {
itemSize: 3,
array: new Float32Array( normalBuffer ),
numItems: normalBuffer.length
},
color: {
itemSize: 3,
array: new Float32Array( colorBuffer ),
numItems: colorBuffer.length
}
}
var mesh = new THREE.Mesh( bGeo, VOXEL_MATERIALS["ROCK"]);
return mesh;
}