From bc05e732873f6f4a60999fb067788bd49bf54fb6 Mon Sep 17 00:00:00 2001 From: xeolabs Date: Wed, 6 Mar 2019 14:45:14 +0100 Subject: [PATCH] Fixed missing/malformed objects and picking bug --- .../GLTFLoaderPlugin/GLTFPerformanceLoader.js | 53 ++++++++----------- .../lib/batching/batchingPickRenderer.js | 6 +-- .../lib/batching/batchingPickShaderSource.js | 2 +- .../lib/instancing/instancingDrawRenderer.js | 17 +++--- .../lib/instancing/instancingEdgesRenderer.js | 4 ++ .../lib/instancing/instancingFillRenderer.js | 3 ++ .../lib/instancing/instancingPickRenderer.js | 25 +++++---- .../instancing/instancingPickShaderSource.js | 10 +++- src/viewer/scene/webgl/Attribute.js | 2 +- 9 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/plugins/GLTFLoaderPlugin/GLTFPerformanceLoader.js b/src/plugins/GLTFLoaderPlugin/GLTFPerformanceLoader.js index 4ee87628be..1561a713de 100644 --- a/src/plugins/GLTFLoaderPlugin/GLTFPerformanceLoader.js +++ b/src/plugins/GLTFLoaderPlugin/GLTFPerformanceLoader.js @@ -406,7 +406,7 @@ var parseGLTF = (function () { if (glTFNode.mesh !== undefined) { - var meshInfo = json.meshes[glTFNode.mesh]; + const meshInfo = json.meshes[glTFNode.mesh]; if (meshInfo) { @@ -414,16 +414,16 @@ var parseGLTF = (function () { if (numPrimitives > 0) { - var meshIds = []; + const meshIds = []; for (var i = 0; i < numPrimitives; i++) { const meshCfg = { id: performanceModel.id + "." + ctx.numObjects++, matrix: matrix }; - var primitiveInfo = meshInfo.primitives[i]; + const primitiveInfo = meshInfo.primitives[i]; - var materialIndex = primitiveInfo.material; + const materialIndex = primitiveInfo.material; var materialInfo; if (materialIndex !== null && materialIndex !== undefined) { materialInfo = json.materials[materialIndex]; @@ -452,20 +452,20 @@ var parseGLTF = (function () { // Instancing //------------------------------------------------------------------ - const geometryId = performanceModel.id + "." + glTFNode.mesh; + const geometryId = performanceModel.id + "." + glTFNode.mesh + "." + i; - if (!meshInfo.geometryId) { - meshInfo.geometryId = geometryId; - var geometryCfg = { + if (!primitiveInfo.geometryId) { // Ensures we only load each primitive mesh once + primitiveInfo.geometryId = geometryId; + const geometryCfg = { id: geometryId }; - loadPrimitiveGeometry(ctx, meshInfo, i, geometryCfg); + loadPrimitiveGeometry(ctx, primitiveInfo, geometryCfg); performanceModel.createGeometry(geometryCfg); } meshCfg.geometryId = geometryId; - const mesh = performanceModel.createMesh(meshCfg); + performanceModel.createMesh(meshCfg); meshIds.push(meshCfg.id); } else { @@ -474,9 +474,9 @@ var parseGLTF = (function () { // Batching //------------------------------------------------------------------ - loadPrimitiveGeometry(ctx, meshInfo, i, meshCfg); + loadPrimitiveGeometry(ctx, primitiveInfo, meshCfg); - const mesh = performanceModel.createMesh(meshCfg); + performanceModel.createMesh(meshCfg); meshIds.push(meshCfg.id); } } @@ -486,9 +486,9 @@ var parseGLTF = (function () { meshIds: meshIds })); } else { - // PerformanceModel.createEntity({ - // meshIds: meshIds - // }); + performanceModel.createEntity({ + meshIds: meshIds + }); } } } @@ -510,15 +510,7 @@ var parseGLTF = (function () { } } - function loadPrimitiveGeometry(ctx, meshInfo, primitiveIdx, geometryCfg) { - var primitivesInfo = meshInfo.primitives; - if (!primitivesInfo) { - return; - } - var primitiveInfo = primitivesInfo[primitiveIdx]; - if (!primitiveInfo) { - return; - } + function loadPrimitiveGeometry(ctx, primitiveInfo, geometryCfg) { var attributes = primitiveInfo.attributes; if (!attributes) { return; @@ -533,7 +525,7 @@ var parseGLTF = (function () { if (positionsIndex !== null && positionsIndex !== undefined) { const accessorInfo = ctx.json.accessors[positionsIndex]; geometryCfg.positions = loadAccessorTypedArray(ctx, accessorInfo); - // scalePositionsArray(geometryCfg.positions); + // scalePositionsArray(geometryCfg.positions); } var normalsIndex = attributes.NORMAL; if (normalsIndex !== null && normalsIndex !== undefined) { @@ -559,10 +551,10 @@ var parseGLTF = (function () { } function scalePositionsArray(positions) { - for (var i =0, len = positions.length; i < len; i+=3) { - positions[i+0] *= 1000; - positions[i+1] *= 1000; - positions[i+2] *= 1000; + for (var i = 0, len = positions.length; i < len; i += 3) { + positions[i + 0] *= 1000; + positions[i + 1] *= 1000; + positions[i + 2] *= 1000; } } @@ -570,6 +562,7 @@ var parseGLTF = (function () { function error(ctx, msg) { ctx.plugin.error(msg); } -})(); +}) +(); export {GLTFPerformanceLoader} \ No newline at end of file diff --git a/src/viewer/scene/PerformanceModel/lib/batching/batchingPickRenderer.js b/src/viewer/scene/PerformanceModel/lib/batching/batchingPickRenderer.js index daae5c3ad5..94c0266663 100644 --- a/src/viewer/scene/PerformanceModel/lib/batching/batchingPickRenderer.js +++ b/src/viewer/scene/PerformanceModel/lib/batching/batchingPickRenderer.js @@ -73,10 +73,10 @@ BatchingPickRenderer.prototype.drawLayer = function (frameCtx, layer) { this._bindProgram(frameCtx, layer); } gl.uniformMatrix4fv(this._uModelMatrix, gl.FALSE, model.worldMatrix); - this._aPosition.bindArrayBuffer(state.positionsBuf, gl.UNSIGNED_SHORT, false); // TODO: Don't need these params, these are now derived from the buffer. + this._aPosition.bindArrayBuffer(state.positionsBuf); // TODO: Don't need these params, these are now derived from the buffer. frameCtx.bindArray++; if (this._aFlags) { - this._aFlags.bindArrayBuffer(state.flagsBuf, gl.UNSIGNED_BYTE, true); + this._aFlags.bindArrayBuffer(state.flagsBuf); frameCtx.bindArray++; } if (this._aFlags2) { @@ -84,7 +84,7 @@ BatchingPickRenderer.prototype.drawLayer = function (frameCtx, layer) { frameCtx.bindArray++; } if (this._aPickColor) { - this._aPickColor.bindArrayBuffer(state.pickColorsBuf, gl.UNSIGNED_BYTE, true); + this._aPickColor.bindArrayBuffer(state.pickColorsBuf); frameCtx.bindArray++; } state.indicesBuf.bind(); diff --git a/src/viewer/scene/PerformanceModel/lib/batching/batchingPickShaderSource.js b/src/viewer/scene/PerformanceModel/lib/batching/batchingPickShaderSource.js index eb16ebc479..3ddbd528a4 100644 --- a/src/viewer/scene/PerformanceModel/lib/batching/batchingPickShaderSource.js +++ b/src/viewer/scene/PerformanceModel/lib/batching/batchingPickShaderSource.js @@ -39,7 +39,7 @@ function buildVertex(layer) { src.push(" if (!visible || !pickable) {"); src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex src.push(" } else {"); - src.push(" vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); "); + src.push(" vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); "); // Batched positions are baked in World-space src.push(" vec4 viewPosition = viewMatrix * worldPosition; "); src.push(" vPickColor = vec4(float(pickColor.r) / 255.0, float(pickColor.g) / 255.0, float(pickColor.b) / 255.0, float(pickColor.a) / 255.0);"); if (clipping) { diff --git a/src/viewer/scene/PerformanceModel/lib/instancing/instancingDrawRenderer.js b/src/viewer/scene/PerformanceModel/lib/instancing/instancingDrawRenderer.js index 5f994d3008..05f1e1b38d 100644 --- a/src/viewer/scene/PerformanceModel/lib/instancing/instancingDrawRenderer.js +++ b/src/viewer/scene/PerformanceModel/lib/instancing/instancingDrawRenderer.js @@ -106,19 +106,19 @@ InstancingDrawRenderer.prototype.drawLayer = function (frameCtx, layer, renderPa this._aPosition.bindArrayBuffer(state.positionsBuf); frameCtx.bindArray++; - this._aNormal.bindArrayBuffer(state.normalsBuf, gl.BYTE, true); + this._aNormal.bindArrayBuffer(state.normalsBuf); frameCtx.bindArray++; - this._aColor.bindArrayBuffer(state.colorsBuf, gl.UNSIGNED_BYTE, false); + this._aColor.bindArrayBuffer(state.colorsBuf); instanceExt.vertexAttribDivisorANGLE(this._aColor.location, 1); frameCtx.bindArray++; - this._aFlags.bindArrayBuffer(state.flagsBuf, gl.UNSIGNED_BYTE, true); + this._aFlags.bindArrayBuffer(state.flagsBuf); instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 1); frameCtx.bindArray++; if (this._aFlags2) { - this._aFlags2.bindArrayBuffer(state.flags2Buf, gl.UNSIGNED_BYTE, true); + this._aFlags2.bindArrayBuffer(state.flags2Buf); instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 1); frameCtx.bindArray++; } @@ -142,16 +142,17 @@ InstancingDrawRenderer.prototype.drawLayer = function (frameCtx, layer, renderPa instanceExt.drawElementsInstancedANGLE(state.primitive, state.indicesBuf.numItems, state.indicesBuf.itemType, 0, state.numInstances); - instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol0.location, 0); // TODO: Is this needed + instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol0.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol1.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol2.location, 0); - - instanceExt.vertexAttribDivisorANGLE(this._aModelNormalMatrixCol0.location, 0); // TODO: Is this needed + instanceExt.vertexAttribDivisorANGLE(this._aModelNormalMatrixCol0.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelNormalMatrixCol1.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelNormalMatrixCol2.location, 0); - instanceExt.vertexAttribDivisorANGLE(this._aColor.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 0); + if (this._aFlags2) { // Won't be in shader when not clipping + instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 0); + } frameCtx.drawElements++; }; diff --git a/src/viewer/scene/PerformanceModel/lib/instancing/instancingEdgesRenderer.js b/src/viewer/scene/PerformanceModel/lib/instancing/instancingEdgesRenderer.js index d911a95582..6260bd552e 100644 --- a/src/viewer/scene/PerformanceModel/lib/instancing/instancingEdgesRenderer.js +++ b/src/viewer/scene/PerformanceModel/lib/instancing/instancingEdgesRenderer.js @@ -144,6 +144,10 @@ InstancingEdgesRenderer.prototype.drawLayer = function (frameCtx, layer, renderP instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 0); } + if (this._aFlags2) { + instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 0); + } + frameCtx.drawElements++; }; diff --git a/src/viewer/scene/PerformanceModel/lib/instancing/instancingFillRenderer.js b/src/viewer/scene/PerformanceModel/lib/instancing/instancingFillRenderer.js index 0af21705af..292941e3be 100644 --- a/src/viewer/scene/PerformanceModel/lib/instancing/instancingFillRenderer.js +++ b/src/viewer/scene/PerformanceModel/lib/instancing/instancingFillRenderer.js @@ -139,6 +139,9 @@ InstancingFillRenderer.prototype.drawLayer = function (frameCtx, layer, renderPa instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol2.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 0); + if (this._aFlags2) { + instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 0); + } frameCtx.drawElements++; }; diff --git a/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickRenderer.js b/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickRenderer.js index d687bc4e27..f977423f8c 100644 --- a/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickRenderer.js +++ b/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickRenderer.js @@ -79,28 +79,30 @@ InstancingPickRenderer.prototype.drawLayer = function (frameCtx, layer) { this._bindProgram(frameCtx, layer); } - this._aModelMatrixCol0.bindArrayBuffer(state.modelMatrixCol0Buf, gl.FLOAT, false); - this._aModelMatrixCol1.bindArrayBuffer(state.modelMatrixCol1Buf, gl.FLOAT, false); - this._aModelMatrixCol2.bindArrayBuffer(state.modelMatrixCol2Buf, gl.FLOAT, false); + gl.uniformMatrix4fv(this._uPositionsDecodeMatrix, false, layer._state.positionsDecodeMatrix); + + this._aModelMatrixCol0.bindArrayBuffer(state.modelMatrixCol0Buf); + this._aModelMatrixCol1.bindArrayBuffer(state.modelMatrixCol1Buf); + this._aModelMatrixCol2.bindArrayBuffer(state.modelMatrixCol2Buf); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol0.location, 1); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol1.location, 1); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol2.location, 1); - frameCtx.bindArray+=3; + frameCtx.bindArray += 3; - this._aPickColor.bindArrayBuffer(state.pickColorsBuf, gl.UNSIGNED_BYTE, false); + this._aPickColor.bindArrayBuffer(state.pickColorsBuf); instanceExt.vertexAttribDivisorANGLE(this._aPickColor.location, 1); frameCtx.bindArray++; - this._aPosition.bindArrayBuffer(state.positionsBuf, gl.UNSIGNED_SHORT, false); + this._aPosition.bindArrayBuffer(state.positionsBuf); frameCtx.bindArray++; - this._aFlags.bindArrayBuffer(state.flagsBuf, gl.UNSIGNED_BYTE, true); + this._aFlags.bindArrayBuffer(state.flagsBuf); instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 1); frameCtx.bindArray++; if (this._aFlags2) { - this._aFlags2.bindArrayBuffer(state.flags2Buf, gl.UNSIGNED_BYTE, true); + this._aFlags2.bindArrayBuffer(state.flags2Buf); instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 1); frameCtx.bindArray++; } @@ -112,11 +114,14 @@ InstancingPickRenderer.prototype.drawLayer = function (frameCtx, layer) { // Cleanup - instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol0.location, 0); // TODO: Is this needed + instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol0.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol1.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aModelMatrixCol2.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aPickColor.location, 0); instanceExt.vertexAttribDivisorANGLE(this._aFlags.location, 0); + if (this._aFlags2) { // Won't be in shader when not clipping + instanceExt.vertexAttribDivisorANGLE(this._aFlags2.location, 0); + } frameCtx.drawElements++; }; @@ -124,7 +129,6 @@ InstancingPickRenderer.prototype.drawLayer = function (frameCtx, layer) { InstancingPickRenderer.prototype._allocate = function (layer) { var scene = layer.model.scene; const gl = scene.canvas.gl; - const lightsState = scene._lightsState; const sectionPlanesState = scene._sectionPlanesState; this._program = new Program(gl, this._shaderSource); @@ -174,7 +178,6 @@ InstancingPickRenderer.prototype._bindProgram = function (frameCtx, layer) { const cameraState = camera._state; gl.uniformMatrix4fv(this._uViewMatrix, false, cameraState.matrix); gl.uniformMatrix4fv(this._uProjMatrix, false, camera._project._state.matrix); - gl.uniformMatrix4fv(this._uPositionsDecodeMatrix, false, layer._state.positionsDecodeMatrix); if (sectionPlanesState.sectionPlanes.length > 0) { const clips = scene._sectionPlanesState.sectionPlanes; let sectionPlaneUniforms; diff --git a/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickShaderSource.js b/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickShaderSource.js index abce02c33f..f7819ceba0 100644 --- a/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickShaderSource.js +++ b/src/viewer/scene/PerformanceModel/lib/instancing/instancingPickShaderSource.js @@ -37,13 +37,19 @@ function buildVertex(layer) { } src.push("varying vec4 vPickColor;"); src.push("void main(void) {"); - src.push("bool visible = (float(flags.x) > 0.0);"); - src.push(`if (!visible) {`); + src.push("bool visible = (float(flags.x) > 0.0);"); + src.push("bool pickable = (float(flags2.z) > 0.0);"); + src.push(`if (!visible || !pickable) {`); src.push(" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);"); // Cull vertex src.push("} else {"); + + src.push(" vec4 worldPosition = positionsDecodeMatrix * vec4(position, 1.0); "); + src.push(" worldPosition = vec4(dot(worldPosition, modelMatrixCol0), dot(worldPosition, modelMatrixCol1), dot(worldPosition, modelMatrixCol2), 1.0);"); + src.push(" vec4 viewPosition = viewMatrix * worldPosition; "); + src.push(" vPickColor = vec4(float(pickColor.r) / 255.0, float(pickColor.g) / 255.0, float(pickColor.b) / 255.0, float(pickColor.a) / 255.0);"); if (clipping) { src.push(" vWorldPosition = worldPosition;"); diff --git a/src/viewer/scene/webgl/Attribute.js b/src/viewer/scene/webgl/Attribute.js index d131c8aa4f..ff534a7ba4 100644 --- a/src/viewer/scene/webgl/Attribute.js +++ b/src/viewer/scene/webgl/Attribute.js @@ -10,7 +10,7 @@ class Attribute { this.location = location; } - bindArrayBuffer(arrayBuf, type, normalized = false, stride = 0, offset = 0) { + bindArrayBuffer(arrayBuf) { if (!arrayBuf) { return; }