Browse Source

fix for missing glTF2 normal, tangent and vertex color attributes on glTF 2 mesh primitives; validation tests added for gltf 1 and gltf mesh prim attribs

Kacey Coley 7 years ago
parent
commit
f8d6fd45a6

+ 40 - 6
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -903,13 +903,47 @@
             MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
 
             // Attribs
-            if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE)) {
-                if (mesh) {
-                    if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                        mesh.createNormals(true);
-                        Tools.Warn("PBRMaterial: Normals have been created for the mesh: " + mesh.name);
-                    }
+            if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE) && mesh) {
+                let bufferMesh = null;
+                if (mesh instanceof InstancedMesh) {
+                    bufferMesh = (mesh as InstancedMesh).sourceMesh;
+                }
+                else if (mesh instanceof Mesh) {
+                    bufferMesh = mesh as Mesh;
                 }
+
+                if (bufferMesh) { 
+                    if (bufferMesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                        // If the first normal's components is the zero vector in one of the submeshes, we have invalid normals
+                        let normalVertexBuffer = bufferMesh.getVertexBuffer(VertexBuffer.NormalKind);
+                        let normals = normalVertexBuffer!.getData();
+                        let vertexBufferOffset = normalVertexBuffer!.getOffset();
+                        let strideSize = normalVertexBuffer!.getStrideSize();
+                        let offset = vertexBufferOffset + subMesh.indexStart * strideSize;
+                         
+                        if (normals![offset] === 0 && normals![offset + 1] === 0 && normals![offset + 2] === 0) {
+                            defines.NORMAL = false;
+                        }
+                        if (bufferMesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                            // If the first tangent's components is the zero vector in one of the submeshes, we have invalid tangents
+                            let tangentVertexBuffer = bufferMesh.getVertexBuffer(VertexBuffer.TangentKind);
+                            let tangents = tangentVertexBuffer!.getData();
+                            let vertexBufferOffset = tangentVertexBuffer!.getOffset();
+                            let strideSize = tangentVertexBuffer!.getStrideSize();
+                            let offset = vertexBufferOffset + subMesh.indexStart * strideSize;
+
+                            if (tangents![offset] === 0 && tangents![offset + 1] === 0 && tangents![offset + 2] === 0) {
+                                defines.TANGENT = false;
+                            }
+                        }
+                    }
+                    else {
+                        if (!scene.getEngine().getCaps().standardDerivatives) {
+                            bufferMesh.createNormals(true);
+                            Tools.Warn("PBRMaterial: Normals have been created for the mesh: " + bufferMesh.name);
+                        }
+                    }
+                }   
             }
 
             // Get correct effect

+ 9 - 5
src/Mesh/babylon.mesh.vertexData.ts

@@ -323,7 +323,7 @@
             this.uvs4 = this._mergeElement(this.uvs4, other.uvs4, count * 2);
             this.uvs5 = this._mergeElement(this.uvs5, other.uvs5, count * 2);
             this.uvs6 = this._mergeElement(this.uvs6, other.uvs6, count * 2);
-            this.colors = this._mergeElement(this.colors, other.colors, count * 4);
+            this.colors = this._mergeElement(this.colors, other.colors, count * 4, 1);
             this.matricesIndices = this._mergeElement(this.matricesIndices, other.matricesIndices, count * 4);
             this.matricesWeights = this._mergeElement(this.matricesWeights, other.matricesWeights, count * 4);
             this.matricesIndicesExtra = this._mergeElement(this.matricesIndicesExtra, other.matricesIndicesExtra, count * 4);
@@ -331,21 +331,25 @@
             return this;
         }
 
-        private _mergeElement(source: Nullable<FloatArray>, other: Nullable<FloatArray>, length = 0): Nullable<FloatArray> {
+        private _mergeElement(source: Nullable<FloatArray>, other: Nullable<FloatArray>, length = 0, defaultValue = 0): Nullable<FloatArray> {
             if (!other && !source) {
                 return null;
             }
 
             if (!other) {
-                return this._mergeElement(source, new Float32Array((<FloatArray>source).length), length);
+                var padding = new Float32Array((<FloatArray>source).length);
+                padding.fill(defaultValue);
+                return this._mergeElement(source, padding, length);
             }
 
             if (!source) {
                 if (length === 0 || length === other.length) {
                     return other;
                 }
-
-                return this._mergeElement(new Float32Array(length - other.length), other, length);
+                
+                var padding = new Float32Array(length - other.length);
+                padding.fill(defaultValue);
+                return this._mergeElement(padding, other, length);
             }
 
             var len = other.length + source.length;

BIN
tests/validation/ReferenceImages/gltf1CesiumMan.png


BIN
tests/validation/ReferenceImages/gltfMeshPrimAttribTest.png


+ 14 - 0
tests/validation/config.json

@@ -230,6 +230,20 @@
       "referenceImage": "gltfTextureSampler.png"
     },
     {
+      "title": "GLTF 1.0 Skin Animation Test",
+      "renderCount": 20,
+      "scriptToRun": "/Demos/GLTF1CesiumMan/index.js",
+      "functionToCall": "createScene",
+      "referenceImage": "gltf1CesiumMan.png"
+    },
+    {
+      "title": "GLTF Mesh Primitive Attribute Test",
+      "renderCount": 20,
+      "scriptToRun": "/Demos/GLTFMeshPrimitiveAttributeTest/index.js",
+      "functionToCall": "createScene",
+      "referenceImage": "gltfMeshPrimAttribTest.png"
+    },
+    {
       "title": "PBR glossy",
       "renderCount": 20,
       "replace": "engine.setHardwareScalingLevel, //engine.setHardwareScalingLevel",