I have a mesh that is generated using the marching cubes algorithm that is drawn using gl.drawArrays(), however the whole mesh isn't rendered, only part of it. I checked if the count I was specifiying in my gl.drawArrays() method was equal to the number of triangles, it was, and I checked if the mesh data was valid, and it was. So I am out of ideas on what to do. My meshes are split into 16x16 chunks. Here is what the issue looks like:
For a 1x1 mesh, it didn't even render, even though the 1x1 mesh data looks correct. If it helps, the vertex data where every 3 entries is an x, y, z position looked like this:
[1, 0.5, 0, 0, 0.5, 0, 1, 0.5, 1, 1, 0.5, 1, 0, 0.5, 0, 0, 0.5, 1]
Have you guys ever had meshes being partially rendered, if so, any ideas on how to solve it? If it helps, here is the chunk class:
function Chunk(chunkX, chunkY, cameraMatrix) {
this.chunkX = chunkX;
this.chunkY = chunkY;
this.cameraMatrix = cameraMatrix;
this.positionData = [];
this.textureIdData = [];
this.uvData = [];
this.normalData = [];
const chunkSizePlusOne = chunkSize + 1;
const full = -1;
const empty = 1;
const totallyInside = 255;
const totallyOutside = 0;
const edgeIntersectionsSize = 16;
const surface = 0;
const chunkXPosition = chunkSize * chunkX;
const chunkYPosition = chunkSize * chunkY;
this.build = function () {
const normalsOfTrianglesAdjacentToVertex = {};
const vertexNormals = {};
const perlinValues = [];
for (let y = 0; y < chunkSizePlusOne; y++) {
for (let x = 0; x < chunkSizePlusOne; x++) {
const trueX = x + chunkXPosition;
const trueY = y + chunkYPosition;
perlinValues[y * chunkSizePlusOne + x] = perlin(trueX, trueY);
};
};
for (let y = 0; y < chunkSize; y++) {
for (let x = 0; x < chunkSize; x++) {
const trueX = x + chunkXPosition;
const trueY = y + chunkYPosition;
for (let z = 0; z < worldHeight; z++) {
const cubePositions = [
[trueX, trueY, z],
[trueX + 1, trueY, z],
[trueX + 1, trueY + 1, z],
[trueX, trueY + 1, z],
[trueX, trueY, z + 1],
[trueX + 1, trueY, z + 1],
[trueX + 1, trueY + 1, z + 1],
[trueX, trueY + 1, z + 1]
];
const cubeScalarField = [];
let lookupIndexOrrer = 1;
let lookupIndex = 0;
for (let cubePosition of cubePositions) {
const [cubeX, cubeY, cubeZ] = cubePosition;
const perlinValuesIndex = chunkSizePlusOne * (cubeY - chunkYPosition) + (cubeX - chunkXPosition);
const height = worldHeight * perlinValues[perlinValuesIndex];
if (cubeZ <= height) {
cubeScalarField.push(full);
lookupIndex |= lookupIndexOrrer;
} else {
cubeScalarField.push(empty);
};
lookupIndexOrrer <<= 1;
};
if (lookupIndex != totallyInside && lookupIndex != totallyOutside) {
const edgeIntersections = triangulationTable[lookupIndex];
for (let i = 0; i < edgeIntersectionsSize; i += 3) {
const edgeIntersectionAtI = edgeIntersections[i];
if (edgeIntersectionAtI !== -1) {
const triangleEdgeIntersections = [
edgeIntersectionAtI,
edgeIntersections[i + 1],
edgeIntersections[i + 2]
];
const xArray = [];
const yArray = [];
const zArray = [];
for (let edgeIntersection of triangleEdgeIntersections) {
const [vertex1, vertex2] = verticesByEdge[edgeIntersection];
const [x1, y1, z1] = cubePositions[vertex1];
const [x2, y2, z2] = cubePositions[vertex2];
const vertex1Value = cubeScalarField[vertex1];
const vertex2Value = cubeScalarField[vertex2];
const vertex2Bias = (surface - vertex1Value) / (vertex2Value - vertex1Value);
const vertex1Bias = 1 - vertex2Bias;
const interpolatedX = x1 * vertex1Bias + x2 * vertex2Bias;
const interpolatedY = y1 * vertex1Bias + y2 * vertex2Bias;
const interpolatedZ = z1 * vertex1Bias + z2 * vertex2Bias;
xArray.push(interpolatedX);
yArray.push(interpolatedY);
zArray.push(interpolatedZ);
// push in order of actual webgl coordinates
this.positionData.push(interpolatedX);
this.positionData.push(interpolatedZ);
this.positionData.push(interpolatedY);
};
this.textureIdData.push(textureId(zArray));
const uvData2D = uv(xArray, yArray);
// parameters in order of webgl coordinates
const normalOfTriangle = triangleNormal(xArray, zArray, yArray);
for (let i = 0; i < numberOfTriangleVertices; i++) {
for (let j = 0; j < 2; j++) {
this.uvData.push(uvData2D[i][j]);
};
// in order of webgl coordinates
const vertexCoordinate = [xArray[i], zArray[i], yArray[i]];
if (normalsOfTrianglesAdjacentToVertex[vertexCoordinate]) {
normalsOfTrianglesAdjacentToVertex[vertexCoordinate].push(normalOfTriangle);
} else {
normalsOfTrianglesAdjacentToVertex[vertexCoordinate] = [normalOfTriangle];
};
};
};
};
};
};
};
};
for (let vertex of Object.keys(normalsOfTrianglesAdjacentToVertex)) {
vertexNormals[vertex] = meanOfVector3Ds(normalsOfTrianglesAdjacentToVertex[vertex]);
};
const positionData = this.positionData;
const positionDataLength = positionData.length;
for (let i = 0; i < positionDataLength; i += 3) {
const vertex = [positionData[i], positionData[i + 1], positionData[i + 2]];
this.normalData.push(...vertexNormals[vertex]);
};
};
this.render = function () {
gl.useProgram(program);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.positionData), gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
const textureIdBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureIdBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.textureIdData), gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(textureIdLocation);
gl.vertexAttribPointer(textureIdLocation, 1, gl.FLOAT, false, 0, 0);
const uvBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.uvData), gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(uvLocation);
gl.vertexAttribPointer(uvLocation, 2, gl.FLOAT, false, 0, 0);
const normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.normalData), gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(normalLocation);
gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0);
gl.uniformMatrix4fv(matrixLocation, false, this.cameraMatrix);
gl.drawArrays(gl.TRIANGLES, 0, this.textureIdData.length);
};
};
[1, 0.5, 0, 0, 0.5, 0, 1, 0.5, 1, 1, 0.5, 1, 0, 0.5, 0, 0, 0.5, 1]
\$\endgroup\$