diff options
26 files changed, 2413 insertions, 1890 deletions
diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine.bin b/examples/qt3d/exampleresources/assets/gltf/wine/wine.bin Binary files differindex 7c8093c5a..c43dfb43a 100755..100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine.bin +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine.bin diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine.json b/examples/qt3d/exampleresources/assets/gltf/wine/wine.gltf index bdff245d5..39e139779 100755..100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine.json +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine.gltf @@ -1,9 +1,140 @@ { "accessors": { - "attribute_120": { - "bufferView": "bufferView_408", - "byteOffset": 38592, + "accessor_10": { + "bufferView": "bufferView_428", + "byteOffset": 9272, + "byteStride": 0, + "componentType": 5123, + "count": 2, + "type": "SCALAR" + }, + "accessor_101": { + "bufferView": "bufferView_429", + "byteOffset": 20400, "byteStride": 12, + "componentType": 5126, + "count": 720, + "max": [ + 16.8, + 19.5, + 0.75 + ], + "min": [ + 1.4, + -0, + 0 + ], + "type": "VEC3" + }, + "accessor_103": { + "bufferView": "bufferView_429", + "byteOffset": 29040, + "byteStride": 12, + "componentType": 5126, + "count": 720, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + "accessor_12": { + "bufferView": "bufferView_429", + "byteOffset": 47344, + "byteStride": 12, + "componentType": 5126, + "count": 2, + "max": [ + 24.7369, + 1.5, + 3.5 + ], + "min": [ + 24.7369, + 1, + 3.5 + ], + "type": "VEC3" + }, + "accessor_124": { + "bufferView": "bufferView_428", + "byteOffset": 8120, + "byteStride": 0, + "componentType": 5123, + "count": 48, + "type": "SCALAR" + }, + "accessor_126": { + "bufferView": "bufferView_429", + "byteOffset": 37680, + "byteStride": 12, + "componentType": 5126, + "count": 30, + "max": [ + 0.5, + 21, + 46.6166 + ], + "min": [ + -0.5, + 0, + 2.5 + ], + "type": "VEC3" + }, + "accessor_128": { + "bufferView": "bufferView_429", + "byteOffset": 38040, + "byteStride": 12, + "componentType": 5126, + "count": 30, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + "accessor_130": { + "bufferView": "bufferView_429", + "byteOffset": 38400, + "byteStride": 8, + "componentType": 5126, + "count": 30, + "max": [ + 0.291667, + 1 + ], + "min": [ + -0.291667, + 0.352547 + ], + "type": "VEC2" + }, + "accessor_151": { + "bufferView": "bufferView_428", + "byteOffset": 8216, + "byteStride": 0, + "componentType": 5123, + "count": 360, + "type": "SCALAR" + }, + "accessor_153": { + "bufferView": "bufferView_429", + "byteOffset": 38640, + "byteStride": 12, + "componentType": 5126, "count": 176, "max": [ 54, @@ -15,12 +146,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_122": { - "bufferView": "bufferView_408", - "byteOffset": 40704, + "accessor_155": { + "bufferView": "bufferView_429", + "byteOffset": 40752, "byteStride": 12, + "componentType": 5126, "count": 176, "max": [ 1, @@ -32,12 +164,13 @@ -1, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_124": { - "bufferView": "bufferView_408", - "byteOffset": 42816, + "accessor_157": { + "bufferView": "bufferView_429", + "byteOffset": 42864, "byteStride": 8, + "componentType": 5126, "count": 176, "max": [ 8.17898, @@ -47,12 +180,21 @@ 2.31603, -0.06428 ], - "type": 35664 + "type": "VEC2" + }, + "accessor_178": { + "bufferView": "bufferView_428", + "byteOffset": 8936, + "byteStride": 0, + "componentType": 5123, + "count": 168, + "type": "SCALAR" }, - "attribute_147": { - "bufferView": "bufferView_408", - "byteOffset": 44224, + "accessor_180": { + "bufferView": "bufferView_429", + "byteOffset": 44272, "byteStride": 12, + "componentType": 5126, "count": 96, "max": [ 2, @@ -64,12 +206,13 @@ 0, 5.5 ], - "type": 35665 + "type": "VEC3" }, - "attribute_149": { - "bufferView": "bufferView_408", - "byteOffset": 45376, + "accessor_182": { + "bufferView": "bufferView_429", + "byteOffset": 45424, "byteStride": 12, + "componentType": 5126, "count": 96, "max": [ 1, @@ -81,12 +224,13 @@ -1, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_151": { - "bufferView": "bufferView_408", - "byteOffset": 46528, + "accessor_184": { + "bufferView": "bufferView_429", + "byteOffset": 46576, "byteStride": 8, + "componentType": 5126, "count": 96, "max": [ 4.15963, @@ -96,12 +240,21 @@ -1.14777, -0.08885 ], - "type": 35664 + "type": "VEC2" + }, + "accessor_205": { + "bufferView": "bufferView_428", + "byteOffset": 9276, + "byteStride": 0, + "componentType": 5123, + "count": 4740, + "type": "SCALAR" }, - "attribute_174": { - "bufferView": "bufferView_408", - "byteOffset": 47296, + "accessor_207": { + "bufferView": "bufferView_429", + "byteOffset": 47368, "byteStride": 12, + "componentType": 5126, "count": 1968, "max": [ 117.98, @@ -113,12 +266,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_176": { - "bufferView": "bufferView_408", - "byteOffset": 70912, + "accessor_209": { + "bufferView": "bufferView_429", + "byteOffset": 70984, "byteStride": 12, + "componentType": 5126, "count": 1968, "max": [ 0.995313, @@ -130,12 +284,13 @@ -0.995313, -0.962469 ], - "type": 35665 + "type": "VEC3" }, - "attribute_178": { - "bufferView": "bufferView_408", - "byteOffset": 94528, + "accessor_211": { + "bufferView": "bufferView_429", + "byteOffset": 94600, "byteStride": 8, + "componentType": 5126, "count": 1968, "max": [ 0.855532, @@ -145,12 +300,55 @@ -0.555297, 0.021103 ], - "type": 35664 + "type": "VEC2" }, - "attribute_221": { - "bufferView": "bufferView_408", - "byteOffset": 110272, + "accessor_22": { + "bufferView": "bufferView_428", + "byteOffset": 0, + "byteStride": 0, + "componentType": 5123, + "count": 2, + "type": "SCALAR" + }, + "accessor_24": { + "bufferView": "bufferView_429", + "byteOffset": 0, "byteStride": 12, + "componentType": 5126, + "count": 2, + "max": [ + 19.7369, + 1.5, + 3.5 + ], + "min": [ + 19.7369, + 1, + 3.5 + ], + "type": "VEC3" + }, + "accessor_249": { + "bufferView": "bufferView_428", + "byteOffset": 18756, + "byteStride": 0, + "componentType": 5123, + "count": 66, + "type": "SCALAR" + }, + "accessor_252": { + "bufferView": "bufferView_428", + "byteOffset": 18888, + "byteStride": 0, + "componentType": 5123, + "count": 66, + "type": "SCALAR" + }, + "accessor_254": { + "bufferView": "bufferView_429", + "byteOffset": 110344, + "byteStride": 12, + "componentType": 5126, "count": 48, "max": [ 82.9854, @@ -162,12 +360,13 @@ 34.9944, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_223": { - "bufferView": "bufferView_408", - "byteOffset": 110848, + "accessor_256": { + "bufferView": "bufferView_429", + "byteOffset": 110920, "byteStride": 12, + "componentType": 5126, "count": 48, "max": [ -0, @@ -179,12 +378,13 @@ 0, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_225": { - "bufferView": "bufferView_408", - "byteOffset": 111424, + "accessor_258": { + "bufferView": "bufferView_429", + "byteOffset": 111496, "byteStride": 8, + "componentType": 5126, "count": 48, "max": [ 0.642232, @@ -194,12 +394,21 @@ 0.349715, 0.987863 ], - "type": 35664 + "type": "VEC2" + }, + "accessor_279": { + "bufferView": "bufferView_428", + "byteOffset": 19020, + "byteStride": 0, + "componentType": 5123, + "count": 360, + "type": "SCALAR" }, - "attribute_248": { - "bufferView": "bufferView_408", - "byteOffset": 111808, + "accessor_281": { + "bufferView": "bufferView_429", + "byteOffset": 111880, "byteStride": 12, + "componentType": 5126, "count": 176, "max": [ 54, @@ -211,12 +420,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_250": { - "bufferView": "bufferView_408", - "byteOffset": 113920, + "accessor_283": { + "bufferView": "bufferView_429", + "byteOffset": 113992, "byteStride": 12, + "componentType": 5126, "count": 176, "max": [ 1, @@ -228,12 +438,13 @@ -1, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_252": { - "bufferView": "bufferView_408", - "byteOffset": 116032, + "accessor_285": { + "bufferView": "bufferView_429", + "byteOffset": 116104, "byteStride": 8, + "componentType": 5126, "count": 176, "max": [ 8.17898, @@ -243,29 +454,21 @@ 2.31603, -0.06428 ], - "type": 35664 + "type": "VEC2" }, - "attribute_26": { - "bufferView": "bufferView_408", - "byteOffset": 0, - "byteStride": 12, - "count": 96, - "max": [ - 2, - 21, - 38 - ], - "min": [ - 0, - 0, - 5.5 - ], - "type": 35665 + "accessor_301": { + "bufferView": "bufferView_428", + "byteOffset": 19740, + "byteStride": 0, + "componentType": 5123, + "count": 600, + "type": "SCALAR" }, - "attribute_270": { - "bufferView": "bufferView_408", - "byteOffset": 117440, + "accessor_303": { + "bufferView": "bufferView_429", + "byteOffset": 117512, "byteStride": 12, + "componentType": 5126, "count": 224, "max": [ 5, @@ -277,12 +480,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_272": { - "bufferView": "bufferView_408", - "byteOffset": 120128, + "accessor_305": { + "bufferView": "bufferView_429", + "byteOffset": 120200, "byteStride": 12, + "componentType": 5126, "count": 224, "max": [ 1, @@ -294,29 +498,21 @@ -0.97185, -0.97185 ], - "type": 35665 + "type": "VEC3" }, - "attribute_28": { - "bufferView": "bufferView_408", - "byteOffset": 1152, - "byteStride": 12, - "count": 96, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": 35665 + "accessor_326": { + "bufferView": "bufferView_428", + "byteOffset": 20940, + "byteStride": 0, + "componentType": 5123, + "count": 6918, + "type": "SCALAR" }, - "attribute_295": { - "bufferView": "bufferView_408", - "byteOffset": 122816, + "accessor_328": { + "bufferView": "bufferView_429", + "byteOffset": 122888, "byteStride": 12, + "componentType": 5126, "count": 2933, "max": [ 25.9025, @@ -328,12 +524,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_297": { - "bufferView": "bufferView_408", - "byteOffset": 158012, + "accessor_330": { + "bufferView": "bufferView_429", + "byteOffset": 158084, "byteStride": 12, + "componentType": 5126, "count": 2933, "max": [ 0.999806, @@ -345,12 +542,13 @@ -0.999806, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_299": { - "bufferView": "bufferView_408", - "byteOffset": 193208, + "accessor_332": { + "bufferView": "bufferView_429", + "byteOffset": 193280, "byteStride": 8, + "componentType": 5126, "count": 2933, "max": [ 0.888318, @@ -360,27 +558,29 @@ -0.595152, 0.013247 ], - "type": 35664 - }, - "attribute_30": { - "bufferView": "bufferView_408", - "byteOffset": 2304, - "byteStride": 8, - "count": 96, - "max": [ - 4.15963, - 1.11374 - ], - "min": [ - -1.14777, - -0.08885 - ], - "type": 35664 + "type": "VEC2" + }, + "accessor_34": { + "bufferView": "bufferView_428", + "byteOffset": 4, + "byteStride": 0, + "componentType": 5123, + "count": 2, + "type": "SCALAR" + }, + "accessor_348": { + "bufferView": "bufferView_428", + "byteOffset": 34776, + "byteStride": 0, + "componentType": 5123, + "count": 216, + "type": "SCALAR" }, - "attribute_317": { - "bufferView": "bufferView_408", - "byteOffset": 216672, + "accessor_350": { + "bufferView": "bufferView_429", + "byteOffset": 216744, "byteStride": 12, + "componentType": 5126, "count": 120, "max": [ 0, @@ -392,12 +592,13 @@ -0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_319": { - "bufferView": "bufferView_408", - "byteOffset": 218112, + "accessor_352": { + "bufferView": "bufferView_429", + "byteOffset": 218184, "byteStride": 12, + "componentType": 5126, "count": 120, "max": [ 1, @@ -409,12 +610,39 @@ -1, -1 ], - "type": 35665 + "type": "VEC3" + }, + "accessor_36": { + "bufferView": "bufferView_429", + "byteOffset": 24, + "byteStride": 12, + "componentType": 5126, + "count": 2, + "max": [ + 119, + -0, + 34.625 + ], + "min": [ + 118, + -0, + 34.625 + ], + "type": "VEC3" + }, + "accessor_373": { + "bufferView": "bufferView_428", + "byteOffset": 35208, + "byteStride": 0, + "componentType": 5123, + "count": 4740, + "type": "SCALAR" }, - "attribute_342": { - "bufferView": "bufferView_408", - "byteOffset": 219552, + "accessor_375": { + "bufferView": "bufferView_429", + "byteOffset": 219624, "byteStride": 12, + "componentType": 5126, "count": 1968, "max": [ 117.98, @@ -426,12 +654,13 @@ 0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_344": { - "bufferView": "bufferView_408", - "byteOffset": 243168, + "accessor_377": { + "bufferView": "bufferView_429", + "byteOffset": 243240, "byteStride": 12, + "componentType": 5126, "count": 1968, "max": [ 0.995313, @@ -443,12 +672,13 @@ -0.995313, -0.962469 ], - "type": 35665 + "type": "VEC3" }, - "attribute_346": { - "bufferView": "bufferView_408", - "byteOffset": 266784, + "accessor_379": { + "bufferView": "bufferView_429", + "byteOffset": 266856, "byteStride": 8, + "componentType": 5126, "count": 1968, "max": [ 0.855532, @@ -458,12 +688,29 @@ -0.555297, 0.021103 ], - "type": 35664 + "type": "VEC2" }, - "attribute_389": { - "bufferView": "bufferView_408", - "byteOffset": 282528, + "accessor_417": { + "bufferView": "bufferView_428", + "byteOffset": 44688, + "byteStride": 0, + "componentType": 5123, + "count": 66, + "type": "SCALAR" + }, + "accessor_420": { + "bufferView": "bufferView_428", + "byteOffset": 44820, + "byteStride": 0, + "componentType": 5123, + "count": 66, + "type": "SCALAR" + }, + "accessor_422": { + "bufferView": "bufferView_429", + "byteOffset": 282600, "byteStride": 12, + "componentType": 5126, "count": 48, "max": [ 82.9854, @@ -475,12 +722,13 @@ 34.9944, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_391": { - "bufferView": "bufferView_408", - "byteOffset": 283104, + "accessor_424": { + "bufferView": "bufferView_429", + "byteOffset": 283176, "byteStride": 12, + "componentType": 5126, "count": 48, "max": [ -0, @@ -492,12 +740,13 @@ 0, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_393": { - "bufferView": "bufferView_408", - "byteOffset": 283680, + "accessor_426": { + "bufferView": "bufferView_429", + "byteOffset": 283752, "byteStride": 8, + "componentType": 5126, "count": 48, "max": [ 0.642232, @@ -507,30 +756,40 @@ 0.349715, 0.987863 ], - "type": 35664 + "type": "VEC2" + }, + "accessor_57": { + "bufferView": "bufferView_428", + "byteOffset": 8, + "byteStride": 0, + "componentType": 5123, + "count": 168, + "type": "SCALAR" }, - "attribute_48": { - "bufferView": "bufferView_408", - "byteOffset": 3072, + "accessor_59": { + "bufferView": "bufferView_429", + "byteOffset": 48, "byteStride": 12, - "count": 720, + "componentType": 5126, + "count": 96, "max": [ - 16.8, - 19.5, - 0.75 + 2, + 21, + 38 ], "min": [ - 1.4, - -0, - 0 + 0, + 0, + 5.5 ], - "type": 35665 + "type": "VEC3" }, - "attribute_50": { - "bufferView": "bufferView_408", - "byteOffset": 11712, + "accessor_61": { + "bufferView": "bufferView_429", + "byteOffset": 1200, "byteStride": 12, - "count": 720, + "componentType": 5126, + "count": 96, "max": [ 1, 1, @@ -541,12 +800,37 @@ -1, -1 ], - "type": 35665 + "type": "VEC3" }, - "attribute_68": { - "bufferView": "bufferView_408", - "byteOffset": 20352, + "accessor_63": { + "bufferView": "bufferView_429", + "byteOffset": 2352, + "byteStride": 8, + "componentType": 5126, + "count": 96, + "max": [ + 4.15963, + 1.11374 + ], + "min": [ + -1.14777, + -0.08885 + ], + "type": "VEC2" + }, + "accessor_79": { + "bufferView": "bufferView_428", + "byteOffset": 344, + "byteStride": 0, + "componentType": 5123, + "count": 1944, + "type": "SCALAR" + }, + "accessor_81": { + "bufferView": "bufferView_429", + "byteOffset": 3120, "byteStride": 12, + "componentType": 5126, "count": 720, "max": [ 16.8, @@ -558,12 +842,13 @@ -0, 0 ], - "type": 35665 + "type": "VEC3" }, - "attribute_70": { - "bufferView": "bufferView_408", - "byteOffset": 28992, + "accessor_83": { + "bufferView": "bufferView_429", + "byteOffset": 11760, "byteStride": 12, + "componentType": 5126, "count": 720, "max": [ 1, @@ -575,182 +860,43 @@ -1, -1 ], - "type": 35665 - }, - "attribute_93": { - "bufferView": "bufferView_408", - "byteOffset": 37632, - "byteStride": 12, - "count": 30, - "max": [ - 0.5, - 21, - 46.6166 - ], - "min": [ - -0.5, - 0, - 2.5 - ], - "type": 35665 - }, - "attribute_95": { - "bufferView": "bufferView_408", - "byteOffset": 37992, - "byteStride": 12, - "count": 30, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": 35665 - }, - "attribute_97": { - "bufferView": "bufferView_408", - "byteOffset": 38352, - "byteStride": 8, - "count": 30, - "max": [ - 0.291667, - 1 - ], - "min": [ - -0.291667, - 0.352547 - ], - "type": 35664 - }, - "indices_118": { - "bufferView": "bufferView_409", - "byteOffset": 8208, - "count": 360, - "type": 5123 - }, - "indices_145": { - "bufferView": "bufferView_409", - "byteOffset": 8928, - "count": 168, - "type": 5123 - }, - "indices_172": { - "bufferView": "bufferView_409", - "byteOffset": 9264, - "count": 4740, - "type": 5123 - }, - "indices_216": { - "bufferView": "bufferView_409", - "byteOffset": 18744, - "count": 66, - "type": 5123 - }, - "indices_219": { - "bufferView": "bufferView_409", - "byteOffset": 18876, - "count": 66, - "type": 5123 - }, - "indices_24": { - "bufferView": "bufferView_409", - "byteOffset": 0, - "count": 168, - "type": 5123 - }, - "indices_246": { - "bufferView": "bufferView_409", - "byteOffset": 19008, - "count": 360, - "type": 5123 + "type": "VEC3" }, - "indices_268": { - "bufferView": "bufferView_409", - "byteOffset": 19728, - "count": 600, - "type": 5123 - }, - "indices_293": { - "bufferView": "bufferView_409", - "byteOffset": 20928, - "count": 6918, - "type": 5123 - }, - "indices_315": { - "bufferView": "bufferView_409", - "byteOffset": 34764, - "count": 216, - "type": 5123 - }, - "indices_340": { - "bufferView": "bufferView_409", - "byteOffset": 35196, - "count": 4740, - "type": 5123 - }, - "indices_384": { - "bufferView": "bufferView_409", - "byteOffset": 44676, - "count": 66, - "type": 5123 - }, - "indices_387": { - "bufferView": "bufferView_409", - "byteOffset": 44808, - "count": 66, - "type": 5123 - }, - "indices_46": { - "bufferView": "bufferView_409", - "byteOffset": 336, + "accessor_99": { + "bufferView": "bufferView_428", + "byteOffset": 4232, + "byteStride": 0, + "componentType": 5123, "count": 1944, - "type": 5123 - }, - "indices_66": { - "bufferView": "bufferView_409", - "byteOffset": 4224, - "count": 1944, - "type": 5123 - }, - "indices_91": { - "bufferView": "bufferView_409", - "byteOffset": 8112, - "count": 48, - "type": 5123 + "type": "SCALAR" } }, "animations": {}, "asset": { - "generator": "collada2gltf@75061f683116dc0ffdad48f33c226e933132e98c" + "generator": "collada2gltf@f356b99aef8868f74877c7ca545f2cd206b9d3b7", + "premultipliedAlpha": true, + "profile": "WebGL 1.0.2", + "version": 0.8 }, "bufferViews": { - "bufferView_408": { + "bufferView_428": { "buffer": "wine", - "byteLength": 284064, + "byteLength": 44952, "byteOffset": 0, - "target": 34962 - }, - "bufferView_409": { - "buffer": "wine", - "byteLength": 44940, - "byteOffset": 284064, "target": 34963 }, - "bufferView_410": { + "bufferView_429": { "buffer": "wine", - "byteLength": 0, - "byteOffset": 329004 + "byteLength": 284136, + "byteOffset": 44952, + "target": 34962 } }, "buffers": { "wine": { - "byteLength": 329004, - "path": "wine.bin", - "type": "arraybuffer" + "byteLength": 329088, + "type": "arraybuffer", + "uri": "wine.bin" } }, "cameras": { @@ -764,14 +910,14 @@ } }, "images": { - "image_0": { - "path": "artezin_bottle.jpg" + "ID140": { + "uri": "artezin_bottle.jpg" }, - "image_1": { - "path": "Wood_Cherry_Original_.jpg" + "ID7": { + "uri": "Wood_Cherry_Original_.jpg" }, - "image_2": { - "path": "_2004_old_vine_zinfandel_btl_xlg.jpg" + "ID78": { + "uri": "_2004_old_vine_zinfandel_btl_xlg.jpg" } }, "materials": { @@ -785,7 +931,7 @@ 0.2, 1 ], - "diffuse": "texture_image_0" + "diffuse": "texture_ID140" } }, "name": "artezin_bottle" @@ -811,6 +957,20 @@ }, "name": "material_5" }, + "ID217": { + "instanceTechnique": { + "technique": "technique3", + "values": {} + }, + "name": "edge_color683818255" + }, + "ID227": { + "instanceTechnique": { + "technique": "technique3", + "values": {} + }, + "name": "edge_color353535255" + }, "ID6": { "instanceTechnique": { "technique": "technique1", @@ -821,7 +981,7 @@ 0.2, 1 ], - "diffuse": "texture_image_1" + "diffuse": "texture_ID7" } }, "name": "Wood_Cherry_Original_" @@ -836,14 +996,14 @@ 0.2, 1 ], - "diffuse": "texture_image_2" + "diffuse": "texture_ID78" } }, "name": "_2004_old_vine_zinfandel_btl_xlg" }, "ID89": { "instanceTechnique": { - "technique": "technique3", + "technique": "technique4", "values": { "ambient": [ 0.2, @@ -863,16 +1023,42 @@ } }, "meshes": { + "geometry10": { + "name": "geometry10", + "primitives": [ + { + "attributes": { + "POSITION": "accessor_24" + }, + "indices": "accessor_22", + "material": "ID217", + "primitive": 1 + } + ] + }, + "geometry13": { + "name": "geometry13", + "primitives": [ + { + "attributes": { + "POSITION": "accessor_36" + }, + "indices": "accessor_34", + "material": "ID227", + "primitive": 1 + } + ] + }, "geometry16": { "name": "geometry16", "primitives": [ { "attributes": { - "NORMAL": "attribute_28", - "POSITION": "attribute_26", - "TEXCOORD_0": "attribute_30" + "NORMAL": "accessor_61", + "POSITION": "accessor_59", + "TEXCOORD_0": "accessor_63" }, - "indices": "indices_24", + "indices": "accessor_57", "material": "ID6", "primitive": 4 } @@ -883,10 +1069,10 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_50", - "POSITION": "attribute_48" + "NORMAL": "accessor_83", + "POSITION": "accessor_81" }, - "indices": "indices_46", + "indices": "accessor_79", "material": "ID21", "primitive": 4 } @@ -897,10 +1083,10 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_70", - "POSITION": "attribute_68" + "NORMAL": "accessor_103", + "POSITION": "accessor_101" }, - "indices": "indices_66", + "indices": "accessor_99", "material": "ID21", "primitive": 4 } @@ -911,11 +1097,11 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_95", - "POSITION": "attribute_93", - "TEXCOORD_0": "attribute_97" + "NORMAL": "accessor_128", + "POSITION": "accessor_126", + "TEXCOORD_0": "accessor_130" }, - "indices": "indices_91", + "indices": "accessor_124", "material": "ID6", "primitive": 4 } @@ -926,11 +1112,11 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_122", - "POSITION": "attribute_120", - "TEXCOORD_0": "attribute_124" + "NORMAL": "accessor_155", + "POSITION": "accessor_153", + "TEXCOORD_0": "accessor_157" }, - "indices": "indices_118", + "indices": "accessor_151", "material": "ID6", "primitive": 4 } @@ -941,26 +1127,39 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_149", - "POSITION": "attribute_147", - "TEXCOORD_0": "attribute_151" + "NORMAL": "accessor_182", + "POSITION": "accessor_180", + "TEXCOORD_0": "accessor_184" }, - "indices": "indices_145", + "indices": "accessor_178", "material": "ID6", "primitive": 4 } ] }, + "geometry5": { + "name": "geometry5", + "primitives": [ + { + "attributes": { + "POSITION": "accessor_12" + }, + "indices": "accessor_10", + "material": "ID217", + "primitive": 1 + } + ] + }, "geometry51": { "name": "geometry51", "primitives": [ { "attributes": { - "NORMAL": "attribute_176", - "POSITION": "attribute_174", - "TEXCOORD_0": "attribute_178" + "NORMAL": "accessor_209", + "POSITION": "accessor_207", + "TEXCOORD_0": "accessor_211" }, - "indices": "indices_172", + "indices": "accessor_205", "material": "ID77", "primitive": 4 } @@ -971,21 +1170,21 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_223", - "POSITION": "attribute_221", - "TEXCOORD_0": "attribute_225" + "NORMAL": "accessor_256", + "POSITION": "accessor_254", + "TEXCOORD_0": "accessor_258" }, - "indices": "indices_216", + "indices": "accessor_249", "material": "ID89", "primitive": 4 }, { "attributes": { - "NORMAL": "attribute_223", - "POSITION": "attribute_221", - "TEXCOORD_0": "attribute_225" + "NORMAL": "accessor_256", + "POSITION": "accessor_254", + "TEXCOORD_0": "accessor_258" }, - "indices": "indices_219", + "indices": "accessor_252", "material": "ID77", "primitive": 4 } @@ -996,11 +1195,11 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_250", - "POSITION": "attribute_248", - "TEXCOORD_0": "attribute_252" + "NORMAL": "accessor_283", + "POSITION": "accessor_281", + "TEXCOORD_0": "accessor_285" }, - "indices": "indices_246", + "indices": "accessor_279", "material": "ID6", "primitive": 4 } @@ -1011,10 +1210,10 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_272", - "POSITION": "attribute_270" + "NORMAL": "accessor_305", + "POSITION": "accessor_303" }, - "indices": "indices_268", + "indices": "accessor_301", "material": "ID21", "primitive": 4 } @@ -1025,11 +1224,11 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_297", - "POSITION": "attribute_295", - "TEXCOORD_0": "attribute_299" + "NORMAL": "accessor_330", + "POSITION": "accessor_328", + "TEXCOORD_0": "accessor_332" }, - "indices": "indices_293", + "indices": "accessor_326", "material": "ID139", "primitive": 4 } @@ -1040,10 +1239,10 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_319", - "POSITION": "attribute_317" + "NORMAL": "accessor_352", + "POSITION": "accessor_350" }, - "indices": "indices_315", + "indices": "accessor_348", "material": "ID21", "primitive": 4 } @@ -1054,11 +1253,11 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_344", - "POSITION": "attribute_342", - "TEXCOORD_0": "attribute_346" + "NORMAL": "accessor_377", + "POSITION": "accessor_375", + "TEXCOORD_0": "accessor_379" }, - "indices": "indices_340", + "indices": "accessor_373", "material": "ID77", "primitive": 4 } @@ -1069,21 +1268,21 @@ "primitives": [ { "attributes": { - "NORMAL": "attribute_391", - "POSITION": "attribute_389", - "TEXCOORD_0": "attribute_393" + "NORMAL": "accessor_424", + "POSITION": "accessor_422", + "TEXCOORD_0": "accessor_426" }, - "indices": "indices_384", + "indices": "accessor_417", "material": "ID89", "primitive": 4 }, { "attributes": { - "NORMAL": "attribute_391", - "POSITION": "attribute_389", - "TEXCOORD_0": "attribute_393" + "NORMAL": "accessor_424", + "POSITION": "accessor_422", + "TEXCOORD_0": "accessor_426" }, - "indices": "indices_387", + "indices": "accessor_420", "material": "ID77", "primitive": 4 } @@ -2993,6 +3192,9 @@ 0, 1 ], + "meshes": [ + "geometry5" + ], "name": "ID215" }, "ID221": { @@ -3015,6 +3217,9 @@ 0, 1 ], + "meshes": [ + "geometry10" + ], "name": "ID221" }, "ID225": { @@ -3037,6 +3242,9 @@ 0, 1 ], + "meshes": [ + "geometry13" + ], "name": "ID225" }, "ID28": { @@ -11577,9 +11785,33 @@ "geometry58" ], "name": "ID88" + }, + "node_424": { + "children": [ + "SketchUp", + "default_camera" + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Y_UP_Transform" } }, - "profile": "WebGL 1.0.2", "programs": { "program_0": { "attributes": [ @@ -11595,16 +11827,23 @@ "a_normal", "a_position" ], + "fragmentShader": "wine1FS", + "vertexShader": "wine1VS" + }, + "program_2": { + "attributes": [ + "a_position" + ], "fragmentShader": "wine2FS", "vertexShader": "wine2VS" }, - "program_2": { + "program_3": { "attributes": [ "a_normal", "a_position" ], - "fragmentShader": "wine4FS", - "vertexShader": "wine4VS" + "fragmentShader": "wine3FS", + "vertexShader": "wine3VS" } }, "samplers": { @@ -11619,29 +11858,42 @@ "scenes": { "defaultScene": { "nodes": [ - "SketchUp", - "default_camera" + "node_424" ] } }, "shaders": { "wine0FS": { - "path": "wine0FS.glsl" + "type": 35632, + "uri": "wine0FS.glsl" }, "wine0VS": { - "path": "wine0VS.glsl" + "type": 35633, + "uri": "wine0VS.glsl" + }, + "wine1FS": { + "type": 35632, + "uri": "wine1FS.glsl" + }, + "wine1VS": { + "type": 35633, + "uri": "wine1VS.glsl" }, "wine2FS": { - "path": "wine2FS.glsl" + "type": 35632, + "uri": "wine2FS.glsl" }, "wine2VS": { - "path": "wine2VS.glsl" + "type": 35633, + "uri": "wine2VS.glsl" }, - "wine4FS": { - "path": "wine4FS.glsl" + "wine3FS": { + "type": 35632, + "uri": "wine3FS.glsl" }, - "wine4VS": { - "path": "wine4VS.glsl" + "wine3VS": { + "type": 35633, + "uri": "wine3VS.glsl" } }, "skins": {}, @@ -11717,10 +11969,10 @@ } }, "states": { - "blendEnable": 0, - "cullFaceEnable": 1, - "depthMask": 1, - "depthTestEnable": 1 + "enable": [ + 2884, + 2929 + ] } } } @@ -11793,21 +12045,79 @@ } }, "states": { - "blendEnable": 1, - "blendEquation": 32774, - "blendFunc": { - "dfactor": 771, - "sfactor": 770 - }, - "cullFaceEnable": 1, - "depthMask": 0, - "depthTestEnable": 1 + "enable": [ + 2884, + 2929, + 3042 + ], + "functions": { + "blendEquationSeparate": [ + 32774, + 32774 + ], + "blendFuncSeparate": [ + 1, + 771, + 1, + 771 + ] + } } } } }, "technique3": { "parameters": { + "modelViewMatrix": { + "semantic": "MODELVIEW", + "type": 35676 + }, + "position": { + "semantic": "POSITION", + "type": 35665 + }, + "projectionMatrix": { + "semantic": "PROJECTION", + "type": 35676 + } + }, + "pass": "defaultPass", + "passes": { + "defaultPass": { + "details": { + "commonProfile": { + "extras": { + "doubleSided": false + }, + "lightingModel": "Constant", + "parameters": [ + "modelViewMatrix", + "projectionMatrix" + ] + }, + "type": "COLLADA-1.4.1/commonProfile" + }, + "instanceProgram": { + "attributes": { + "a_position": "position" + }, + "program": "program_2", + "uniforms": { + "u_modelViewMatrix": "modelViewMatrix", + "u_projectionMatrix": "projectionMatrix" + } + }, + "states": { + "enable": [ + 2884, + 2929 + ] + } + } + } + }, + "technique4": { + "parameters": { "ambient": { "type": 35666 }, @@ -11859,7 +12169,7 @@ "a_normal": "normal", "a_position": "position" }, - "program": "program_2", + "program": "program_3", "uniforms": { "u_ambient": "ambient", "u_diffuse": "diffuse", @@ -11869,36 +12179,39 @@ } }, "states": { - "blendEnable": 0, - "cullFaceEnable": 1, - "depthMask": 1, - "depthTestEnable": 1 + "enable": [ + 2884, + 2929 + ] } } } } }, "textures": { - "texture_image_0": { + "texture_ID140": { "format": 6408, "internalFormat": 6408, "sampler": "sampler_0", - "source": "image_0", - "target": 3553 + "source": "ID140", + "target": 3553, + "type": 5121 }, - "texture_image_1": { + "texture_ID7": { "format": 6408, "internalFormat": 6408, "sampler": "sampler_0", - "source": "image_1", - "target": 3553 + "source": "ID7", + "target": 3553, + "type": 5121 }, - "texture_image_2": { + "texture_ID78": { "format": 6408, "internalFormat": 6408, "sampler": "sampler_0", - "source": "image_2", - "target": 3553 + "source": "ID78", + "target": 3553, + "type": 5121 } } }
\ No newline at end of file diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine0FS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine0FS.glsl index b01fbb1a1..6e4b7e6d1 100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine0FS.glsl +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine0FS.glsl @@ -1,21 +1,17 @@ -#version 150 -//precision highp float; - -in vec3 v_normal; +precision highp float; +varying vec3 v_normal; uniform vec4 u_ambient; -in vec2 v_texcoord0; +varying vec2 v_texcoord0; uniform sampler2D u_diffuse; -out vec4 fragColor; - void main(void) { - vec3 normal = normalize(v_normal); - vec4 color = vec4(0., 0., 0., 0.); - vec4 diffuse = vec4(0., 0., 0., 1.); - vec4 ambient; - ambient = u_ambient; - diffuse = texture(u_diffuse, v_texcoord0); - diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); - color.xyz += diffuse.xyz; - color = vec4(color.rgb * diffuse.a, diffuse.a); - fragColor = color; +vec3 normal = normalize(v_normal); +vec4 color = vec4(0., 0., 0., 0.); +vec4 diffuse = vec4(0., 0., 0., 1.); +vec4 ambient; +ambient = u_ambient; +diffuse = texture2D(u_diffuse, v_texcoord0); +diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); +color.xyz += diffuse.xyz; +color = vec4(color.rgb * diffuse.a, diffuse.a); +gl_FragColor = color; } diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine0VS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine0VS.glsl index f03b74739..cacc9ed99 100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine0VS.glsl +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine0VS.glsl @@ -1,18 +1,15 @@ -#version 150 -//precision highp float; - -in vec3 a_position; -in vec3 a_normal; -out vec3 v_normal; +precision highp float; +attribute vec3 a_position; +attribute vec3 a_normal; +varying vec3 v_normal; uniform mat3 u_normalMatrix; uniform mat4 u_modelViewMatrix; uniform mat4 u_projectionMatrix; -in vec2 a_texcoord0; -out vec2 v_texcoord0; - +attribute vec2 a_texcoord0; +varying vec2 v_texcoord0; void main(void) { - vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); - v_normal = normalize(u_normalMatrix * a_normal); - v_texcoord0 = a_texcoord0; - gl_Position = u_projectionMatrix * pos; +vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); +v_normal = u_normalMatrix * a_normal; +v_texcoord0 = a_texcoord0; +gl_Position = u_projectionMatrix * pos; } diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine1FS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine1FS.glsl new file mode 100644 index 000000000..d490b4ee7 --- /dev/null +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine1FS.glsl @@ -0,0 +1,17 @@ +precision highp float; +varying vec3 v_normal; +uniform vec4 u_ambient; +uniform vec4 u_diffuse; +uniform float u_transparency; +void main(void) { +vec3 normal = normalize(v_normal); +vec4 color = vec4(0., 0., 0., 0.); +vec4 diffuse = vec4(0., 0., 0., 1.); +vec4 ambient; +ambient = u_ambient; +diffuse = u_diffuse; +diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); +color.xyz += diffuse.xyz; +color = vec4(color.rgb * diffuse.a, diffuse.a * u_transparency); +gl_FragColor = color; +} diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine1VS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine1VS.glsl new file mode 100644 index 000000000..9e3592280 --- /dev/null +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine1VS.glsl @@ -0,0 +1,12 @@ +precision highp float; +attribute vec3 a_position; +attribute vec3 a_normal; +varying vec3 v_normal; +uniform mat3 u_normalMatrix; +uniform mat4 u_modelViewMatrix; +uniform mat4 u_projectionMatrix; +void main(void) { +vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); +v_normal = u_normalMatrix * a_normal; +gl_Position = u_projectionMatrix * pos; +} diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine2FS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine2FS.glsl index 72192fee4..b41a6d5fc 100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine2FS.glsl +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine2FS.glsl @@ -1,21 +1,8 @@ -#version 150 -//precision highp float; - -in vec3 v_normal; -uniform vec4 u_ambient; -uniform vec4 u_diffuse; -uniform float u_transparency; -out vec4 fragColor; - +precision highp float; void main(void) { - vec3 normal = normalize(v_normal); - vec4 color = vec4(0., 0., 0., 0.); - vec4 diffuse = vec4(0., 0., 0., 1.); - vec4 ambient; - ambient = u_ambient; - diffuse = u_diffuse; - diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); - color.xyz += diffuse.xyz; - color = vec4(color.rgb * diffuse.a, diffuse.a * u_transparency); - fragColor = color; +vec4 color = vec4(0., 0., 0., 0.); +vec4 diffuse = vec4(0., 0., 0., 1.); +color.xyz += diffuse.xyz; +color = vec4(color.rgb * diffuse.a, diffuse.a); +gl_FragColor = color; } diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine2VS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine2VS.glsl index 1b5eabce9..17237bfea 100644 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine2VS.glsl +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine2VS.glsl @@ -1,15 +1,8 @@ -#version 150 -//precision highp float; - -in vec3 a_position; -in vec3 a_normal; -out vec3 v_normal; -uniform mat3 u_normalMatrix; +precision highp float; +attribute vec3 a_position; uniform mat4 u_modelViewMatrix; uniform mat4 u_projectionMatrix; - void main(void) { - vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); - v_normal = normalize(u_normalMatrix * a_normal); - gl_Position = u_projectionMatrix * pos; +vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); +gl_Position = u_projectionMatrix * pos; } diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine3FS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine3FS.glsl new file mode 100644 index 000000000..79082198c --- /dev/null +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine3FS.glsl @@ -0,0 +1,16 @@ +precision highp float; +varying vec3 v_normal; +uniform vec4 u_ambient; +uniform vec4 u_diffuse; +void main(void) { +vec3 normal = normalize(v_normal); +vec4 color = vec4(0., 0., 0., 0.); +vec4 diffuse = vec4(0., 0., 0., 1.); +vec4 ambient; +ambient = u_ambient; +diffuse = u_diffuse; +diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); +color.xyz += diffuse.xyz; +color = vec4(color.rgb * diffuse.a, diffuse.a); +gl_FragColor = color; +} diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine3VS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine3VS.glsl new file mode 100644 index 000000000..9e3592280 --- /dev/null +++ b/examples/qt3d/exampleresources/assets/gltf/wine/wine3VS.glsl @@ -0,0 +1,12 @@ +precision highp float; +attribute vec3 a_position; +attribute vec3 a_normal; +varying vec3 v_normal; +uniform mat3 u_normalMatrix; +uniform mat4 u_modelViewMatrix; +uniform mat4 u_projectionMatrix; +void main(void) { +vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); +v_normal = u_normalMatrix * a_normal; +gl_Position = u_projectionMatrix * pos; +} diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine4FS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine4FS.glsl deleted file mode 100644 index 99acdb37c..000000000 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine4FS.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 150 -//precision highp float; - -in vec3 v_normal; -uniform vec4 u_ambient; -uniform vec4 u_diffuse; -out vec4 fragColor; - -void main(void) { - vec3 normal = normalize(v_normal); - vec4 color = vec4(0., 0., 0., 0.); - vec4 diffuse = vec4(0., 0., 0., 1.); - vec4 ambient; - ambient = u_ambient; - diffuse = u_diffuse; - diffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.); - color.xyz += diffuse.xyz; - color = vec4(color.rgb * diffuse.a, diffuse.a); - fragColor = color; -} diff --git a/examples/qt3d/exampleresources/assets/gltf/wine/wine4VS.glsl b/examples/qt3d/exampleresources/assets/gltf/wine/wine4VS.glsl deleted file mode 100644 index 0e66d42c1..000000000 --- a/examples/qt3d/exampleresources/assets/gltf/wine/wine4VS.glsl +++ /dev/null @@ -1,17 +0,0 @@ -#version 150 -//precision highp float; - -in vec3 a_position; -in vec3 a_normal; -out vec3 v_normal; - -uniform mat3 u_normalMatrix; -uniform mat4 u_modelViewMatrix; -uniform mat4 u_projectionMatrix; - -void main(void) { - vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); - v_normal = normalize(u_normalMatrix * a_normal); - gl_Position = u_projectionMatrix * pos; -} - diff --git a/examples/qt3d/exampleresources/gltf.qrc b/examples/qt3d/exampleresources/gltf.qrc index ecc727504..869fb16dc 100644 --- a/examples/qt3d/exampleresources/gltf.qrc +++ b/examples/qt3d/exampleresources/gltf.qrc @@ -4,13 +4,15 @@ <file>assets/gltf/wine/artezin_bottle.jpg</file> <file>assets/gltf/wine/wine.bin</file> <file>assets/gltf/wine/wine.dae</file> - <file>assets/gltf/wine/wine.json</file> <file>assets/gltf/wine/wine0FS.glsl</file> <file>assets/gltf/wine/wine0VS.glsl</file> <file>assets/gltf/wine/wine2FS.glsl</file> <file>assets/gltf/wine/wine2VS.glsl</file> - <file>assets/gltf/wine/wine4FS.glsl</file> - <file>assets/gltf/wine/wine4VS.glsl</file> <file>assets/gltf/wine/Wood_Cherry_Original_.jpg</file> + <file>assets/gltf/wine/wine.gltf</file> + <file>assets/gltf/wine/wine1FS.glsl</file> + <file>assets/gltf/wine/wine1VS.glsl</file> + <file>assets/gltf/wine/wine3FS.glsl</file> + <file>assets/gltf/wine/wine3VS.glsl</file> </qresource> </RCC> diff --git a/examples/qt3d/gltf/Wine.qml b/examples/qt3d/gltf/Wine.qml new file mode 100644 index 000000000..4a61c6584 --- /dev/null +++ b/examples/qt3d/gltf/Wine.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D 2.0 +import Qt3D.Renderer 2.0 + +Entity { + id: root + + property alias x: wineTranslate.dx + property alias y: wineTranslate.dy + property alias z: wineTranslate.dz + property alias angleX: rotateX.angle + property alias angleY: rotateY.angle + property alias angleZ: rotateZ.angle + property alias scale: wineScale.scale + + components: [ + Transform { + Rotate { + id: rotateX + axis: Qt.vector3d(1, 0, 0) + } + Rotate { + id: rotateY + axis: Qt.vector3d(0, 1, 0) + } + Rotate { + id: rotateZ + axis: Qt.vector3d(0, 0, 1) + } + Translate { + id: wineTranslate + } + Scale { + id: wineScale + } + }, + SceneLoader + { + source: "qrc:/assets/gltf/wine/wine.gltf" + } + ] +} diff --git a/examples/qt3d/gltf/basic.frag b/examples/qt3d/gltf/basic.frag deleted file mode 100644 index 6f83f6b90..000000000 --- a/examples/qt3d/gltf/basic.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 - -in vec3 color; - -out vec4 fragColor; - -void main() -{ - // The color variable is interpolated to this fragment's position - // for us by OpenGL. - fragColor = vec4( color, 1.0 ); -} diff --git a/examples/qt3d/gltf/basic.vert b/examples/qt3d/gltf/basic.vert deleted file mode 100644 index 0e35affd5..000000000 --- a/examples/qt3d/gltf/basic.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 330 - -in vec3 vertexPosition; -in vec3 vertexColor; - -uniform mat4 u_projection; -uniform mat4 u_model; - -out vec3 color; - -void main() -{ - // Pass through the color to the fragment shader - color = vertexColor; - - // Calculate the vertex position - gl_Position = u_projection * u_model * vec4( vertexPosition, 1.0 ); -} diff --git a/examples/qt3d/gltf/gltf.pro b/examples/qt3d/gltf/gltf.pro index 5b75283ae..7f65358d5 100644 --- a/examples/qt3d/gltf/gltf.pro +++ b/examples/qt3d/gltf/gltf.pro @@ -10,9 +10,9 @@ SOURCES += \ main.cpp OTHER_FILES += \ - main.qml + main.qml \ + Wine.qml RESOURCES += \ gltf_example.qrc \ ../exampleresources/gltf.qrc \ - ../exampleresources/obj.qrc diff --git a/examples/qt3d/gltf/gltf_example.qrc b/examples/qt3d/gltf/gltf_example.qrc index c24519313..0da7ea21f 100644 --- a/examples/qt3d/gltf/gltf_example.qrc +++ b/examples/qt3d/gltf/gltf_example.qrc @@ -1,7 +1,6 @@ <RCC> <qresource prefix="/"> <file>main.qml</file> - <file>basic.frag</file> - <file>basic.vert</file> + <file>Wine.qml</file> </qresource> </RCC> diff --git a/examples/qt3d/gltf/main.qml b/examples/qt3d/gltf/main.qml index acce5d7ac..c58aaf5d4 100644 --- a/examples/qt3d/gltf/main.qml +++ b/examples/qt3d/gltf/main.qml @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -36,150 +37,43 @@ import Qt3D 2.0 import Qt3D.Renderer 2.0 -import QtQuick 2.1 as QQ2 Entity { - id: root - objectName: "root" - - Scene { - id: wineScene - source: ":/assets/gltf/wine/wine.json" - - Entity { - transforms: [ - Translate { - dx: 100 - dy: 0 - dz: -100 - } - - ] - - property Mesh myMesh: ballmesh - } - - Entity { - property Mesh myMesh: ballmesh - - transforms: [ - Translate { - dx: 0 - dy: 100 - } - - ] - - property Material mat: greenMaterial - } - - Entity { - property Shape myShape: sphere1 - - transforms: [ - Translate { - dx: 50 - dy: 50 - } - - ] - - property Material mat: greenMaterial - - Shape { - id: sphere1 - radius: 25 - rings: 32 - slices: 32 - } - } - - Entity { - property Shape myShape: torus1 - - transforms: [ - Translate { - dx: 50 - dy: 120 - } - - ] - - property Material mat: blueMaterial - - Shape { - id: torus1 - radius: 40 - minorRadius: 15 - type: Shape.ShapeTorus - } - } - - - Entity { - property Mesh myMesh: ballmesh - - transforms: [ - Rotate { - angle: 45 - axis: Qt.vector3d(0, 1, 0) - }, - - Translate { - dx: 40 - dy: 100 - } - ] - - property Material mat: blueMaterial - } + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 20.0, -120.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) } - Mesh { - id: ballmesh - source: ":/assets/obj/ball.obj" + Configuration { + controlledCamera: camera } - Material { - id: greenMaterial - - parameters: [ - /* - Tag { - name: "kd" - value: Qt.green - } - */ - - Tag { - name: "kd" - value: Qt.vector3d( 0.2, 1.0, 0.1 ) - - QQ2.Vector3dAnimation on value { - from: Qt.vector3d(0.0, 1.0, 0.1) - to: Qt.vector3d(1.0, 1.0, 0.1) - duration: 1000 - loops: QQ2.Animation.Infinite - } - }, - - Tag { - name: "diffuse" - value: brick - } - ] + FrameGraph { + id : external_forward_renderer + activeFrameGraph : ForwardRenderer { + camera: camera + clearColor: "black" + } } - Material { - id: blueMaterial + components: [external_forward_renderer] - parameters: [ - Tag { name: "kd"; value: Qt.vector3d(0.2, 0.2, 1.0) } - ] + Wine { + id: wineRack + scale: 1 + x: -60.0 + y: -20.0 + z: 0.0 + angleX: 180 } - Texture { - id: brick - source: "/Users/jmt/KDAB/Qt3D/qt3d-ng/assets/textures/brick1.jpg" - } } diff --git a/src/plugins/sceneparsers/gltf/gltf.pro b/src/plugins/sceneparsers/gltf/gltf.pro new file mode 100644 index 000000000..bf289372d --- /dev/null +++ b/src/plugins/sceneparsers/gltf/gltf.pro @@ -0,0 +1,12 @@ +TARGET = gltfsceneparser +QT += core-private 3dcore 3dcore-private 3drenderer 3drenderer-private + +PLUGIN_TYPE = sceneparsers +PLUGIN_CLASS_NAME = GLTFParser +load(qt_plugin) + +HEADERS += \ + gltfparser_p.h + +SOURCES += \ + gltfparser.cpp diff --git a/src/plugins/sceneparsers/gltf/gltfparser.cpp b/src/plugins/sceneparsers/gltf/gltfparser.cpp new file mode 100644 index 000000000..a4a0602c2 --- /dev/null +++ b/src/plugins/sceneparsers/gltf/gltfparser.cpp @@ -0,0 +1,1345 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gltfparser_p.h" + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QJsonArray> +#include <QtCore/QJsonObject> + +#include <QtGui/QVector2D> + +#include <Qt3DCore/QCameraLens> +#include <Qt3DCore/QEntity> +#include <Qt3DCore/QMatrixTransform> +#include <Qt3DCore/QTransform> + +#include <Qt3DCore/private/qurlhelper_p.h> + +#include <Qt3DRenderer/QAlphaCoverage> +#include <Qt3DRenderer/QBlendEquation> +#include <Qt3DRenderer/QBlendStateSeparate> +#include <Qt3DRenderer/QColorMask> +#include <Qt3DRenderer/QCullFace> +#include <Qt3DRenderer/QDepthMask> +#include <Qt3DRenderer/QDepthTest> +#include <Qt3DRenderer/QEffect> +#include <Qt3DRenderer/QFrontFace> +#include <Qt3DRenderer/QGeometry> +#include <Qt3DRenderer/QGeometryRenderer> +#include <Qt3DRenderer/QMaterial> +#include <Qt3DRenderer/QParameter> +#include <Qt3DRenderer/QParameterMapping> +#include <Qt3DRenderer/QPolygonOffset> +#include <Qt3DRenderer/QRenderState> +#include <Qt3DRenderer/QScissorTest> +#include <Qt3DRenderer/QShaderProgram> +#include <Qt3DRenderer/QTechnique> +#include <Qt3DRenderer/QTexture> + +QT_BEGIN_NAMESPACE + +namespace Qt3D { + +Q_LOGGING_CATEGORY(GLTFParserLog, "Qt3D.GLTFParser") + +namespace { + +const QString KEY_CAMERA = QStringLiteral("camera"); +const QString KEY_CAMERAS = QStringLiteral("cameras"); +const QString KEY_SCENES = QStringLiteral("scenes"); +const QString KEY_NODES = QStringLiteral("nodes"); +const QString KEY_MESHES = QStringLiteral("meshes"); +const QString KEY_CHILDREN = QStringLiteral("children"); +const QString KEY_MATRIX = QStringLiteral("matrix"); +const QString KEY_TYPE = QStringLiteral("type"); +const QString KEY_PERSPECTIVE =QStringLiteral("perspective"); +const QString KEY_NAME = QStringLiteral("name"); +const QString KEY_COUNT = QStringLiteral("count"); +const QString KEY_YFOV = QStringLiteral("yfov"); +const QString KEY_ZNEAR = QStringLiteral("znear"); +const QString KEY_ZFAR = QStringLiteral("zfar"); +const QString KEY_MATERIALS = QStringLiteral("materials"); +const QString KEY_TECHNIQUE = QStringLiteral("technique"); +const QString KEY_VALUES = QStringLiteral("values"); +const QString KEY_BUFFERS = QStringLiteral("buffers"); +const QString KEY_SHADERS = QStringLiteral("shaders"); +const QString KEY_PROGRAMS = QStringLiteral("programs"); +const QString KEY_PROGRAM = QStringLiteral("program"); +const QString KEY_TECHNIQUES = QStringLiteral("techniques"); +const QString KEY_ACCESSORS = QStringLiteral("accessors"); +const QString KEY_IMAGES = QStringLiteral("images"); +const QString KEY_TEXTURES = QStringLiteral("textures"); +const QString KEY_SCENE = QStringLiteral("scene"); +const QString KEY_BUFFER = QStringLiteral("buffer"); +const QString KEY_TARGET = QStringLiteral("target"); +const QString KEY_BYTE_OFFSET = QStringLiteral("byteOffset"); +const QString KEY_BYTE_LENGTH = QStringLiteral("byteLength"); +const QString KEY_BYTE_STRIDE = QStringLiteral("byteStride"); +const QString KEY_PRIMITIVES = QStringLiteral("primitives"); +const QString KEY_PRIMITIVE = QStringLiteral("primitive"); +const QString KEY_MATERIAL = QStringLiteral("material"); +const QString KEY_ATTRIBUTES = QStringLiteral("attributes"); +const QString KEY_INDICES = QStringLiteral("indices"); +const QString KEY_URI = QStringLiteral("uri"); +const QString KEY_FORMAT = QStringLiteral("format"); +const QString KEY_PASSES = QStringLiteral("passes"); +const QString KEY_SOURCE = QStringLiteral("source"); +const QString KEY_SAMPLER = QStringLiteral("sampler"); +const QString KEY_SAMPLERS = QStringLiteral("samplers"); +const QString KEY_SEMANTIC = QStringLiteral("semantic"); +const QString KEY_STATES = QStringLiteral("states"); +const QString KEY_UNIFORMS = QStringLiteral("uniforms"); +const QString KEY_PARAMETERS = QStringLiteral("parameters"); +const QString KEY_WRAP_S = QStringLiteral("wrapS"); +const QString KEY_MIN_FILTER = QStringLiteral("minFilter"); +const QString KEY_MAG_FILTER = QStringLiteral("magFilter"); + +const QString KEY_INSTANCE_TECHNIQUE = QStringLiteral("instanceTechnique"); +const QString KEY_INSTANCE_PROGRAM = QStringLiteral("instanceProgram"); +const QString KEY_BUFFER_VIEWS = QStringLiteral("bufferViews"); +const QString KEY_BUFFER_VIEW = QStringLiteral("bufferView"); +const QString KEY_VERTEX_SHADER = QStringLiteral("vertexShader"); +const QString KEY_FRAGMENT_SHADER = QStringLiteral("fragmentShader"); +const QString KEY_INTERNAL_FORMAT = QStringLiteral("internalFormat"); +const QString KEY_COMPONENT_TYPE = QStringLiteral("componentType"); +const QString KEY_ASPECT_RATIO = QStringLiteral("aspect_ratio"); +const QString KEY_VALUE = QStringLiteral("value"); +const QString KEY_ENABLE = QStringLiteral("enable"); +const QString KEY_FUNCTIONS = QStringLiteral("functions"); + +} // of anonymous namespace + +GLTFParser::GLTFParser() : AbstractSceneParser(), + m_parseDone(false) +{ +} + +GLTFParser::~GLTFParser() +{ + +} + +void GLTFParser::setBasePath(const QString& path) +{ + m_basePath = path; +} + +bool GLTFParser::setJSON(const QJsonDocument &json ) +{ + if ( !json.isObject() ) { + return false; + } + + m_json = json; + m_parseDone = false; + + cleanup(); + + return true; +} + +/*! + * Sets the \a path used by the parser to load the scene file. + * If the file is valid, parsing is automatically triggered. + */ +void GLTFParser::setSource(const QUrl &source) +{ + const QString path = QUrlHelper::urlToLocalFileOrQrc(source); + QFileInfo finfo(path); + if (!finfo.exists()) { + qCWarning(GLTFParserLog) << "missing file:" << path; + return; + } + QFile f(path); + f.open(QIODevice::ReadOnly); + + if (!setJSON(QJsonDocument::fromJson(f.readAll()))) { + qCWarning(GLTFParserLog) << "not a JSON document"; + return; + } + + setBasePath(finfo.dir().absolutePath()); +} + +/*! + * Returns true if the extension of \a path is supported by the + * GLTF parser. + */ +bool GLTFParser::isExtensionSupported(const QUrl &source) const +{ + const QString path = QUrlHelper::urlToLocalFileOrQrc(source); + return GLTFParser::isGLTFPath(path); +} + +QEntity* GLTFParser::node(const QString &id) +{ + QJsonObject nodes = m_json.object().value(KEY_NODES).toObject(); + if (!nodes.contains(id)) { + qCWarning(GLTFParserLog) << "unknown node" << id << "in GLTF file" << m_basePath; + return NULL; + } + + QJsonObject jsonObj = nodes.value(id).toObject(); + QEntity* result = Q_NULLPTR; + + // Qt3D has a limitation that a QEntity can only have 1 mesh and 1 material component + // So if the node has only 1 mesh, we only create 1 QEntity + // Otherwise if there are n meshes, there is 1 QEntity, with n children for each mesh/material combo + if (jsonObj.contains(KEY_MESHES)) { + QVector<QEntity *> entities; + + Q_FOREACH (QJsonValue mesh, jsonObj.value(KEY_MESHES).toArray()) { + if (!m_meshDict.contains(mesh.toString())) { + qCWarning(GLTFParserLog) << "node" << id << "references unknown mesh" << mesh.toString(); + continue; + } + + Q_FOREACH (QGeometryRenderer *geometryRenderer, m_meshDict.values(mesh.toString())) { + QEntity *entity = new QEntity; + entity->addComponent(geometryRenderer); + entity->addComponent(material(m_meshMaterialDict[geometryRenderer])); + entities.append(entity); + } + + } + + if (entities.count() == 1) { + result = entities.first(); + } else { + result = new QEntity; + Q_FOREACH (QEntity *entity, entities) { + entity->setParent(result); + } + } + } + + //If the entity contains no meshes, results will still be null here + if (result == Q_NULLPTR) + result = new QEntity; + + if ( jsonObj.contains(KEY_CHILDREN) ) { + Q_FOREACH (QJsonValue c, jsonObj.value(KEY_CHILDREN).toArray()) { + QEntity* child = node(c.toString()); + if (!child) + continue; + child->setParent(result); + } + } + + renameFromJson(jsonObj, result); + + if ( jsonObj.contains(KEY_MATRIX) ) { + QMatrix4x4 m(Qt::Uninitialized); + + QJsonArray matrixValues = jsonObj.value(KEY_MATRIX).toArray(); + for (int i=0; i<16; ++i) { + double v = matrixValues.at( i ).toDouble(); + m(i % 4, i >> 2) = v; + } + + // ADD MATRIX TRANSFORM COMPONENT TO ENTITY + QTransform *trans = new QTransform(); + trans->addTransform(new QMatrixTransform(m)); + result->addComponent(trans); + } + + if ( jsonObj.contains(KEY_CAMERA) ) { + QCameraLens* cam = camera( jsonObj.value(KEY_CAMERA).toString() ); + if (!cam) { + qCWarning(GLTFParserLog) << "failed to build camera:" << jsonObj.value(KEY_CAMERA) + << "on node" << id; + } else { + result->addComponent(cam); + } + } // of have camera attribute + + return result; +} + +QEntity* GLTFParser::scene(const QString &id) +{ + parse(); + + QJsonObject scenes = m_json.object().value(KEY_SCENES).toObject(); + if (!scenes.contains(id)) { + if (!id.isNull()) + qCWarning(GLTFParserLog) << "GLTF: no such scene" << id << "in file" << m_basePath; + return defaultScene(); + } + + QJsonObject sceneObj = scenes.value(id).toObject(); + QEntity* sceneEntity = new QEntity; + Q_FOREACH (QJsonValue nnv, sceneObj.value(KEY_NODES).toArray()) { + QString nodeName = nnv.toString(); + QEntity* child = node(nodeName); + if (!child) + continue; + child->setParent(sceneEntity); + } + + return sceneEntity; +} + +GLTFParser::BufferData::BufferData() + : length(0) + , data(Q_NULLPTR) +{ +} + +GLTFParser::BufferData::BufferData(QJsonObject json) +{ + path = json.value(KEY_URI).toString(); + length = json.value(KEY_BYTE_LENGTH).toInt(); + data = Q_NULLPTR; +} + +GLTFParser::ParameterData::ParameterData() : + type(0) +{ + +} + +GLTFParser::ParameterData::ParameterData(QJsonObject json) +{ + type = json.value(KEY_TYPE).toInt(); + semantic = json.value(KEY_SEMANTIC).toString(); +} + +GLTFParser::AccessorData::AccessorData() + : type(QAttribute::Float) + , dataSize(0) + , count(0) + , offset(0) + , stride(0) +{ + +} + +GLTFParser::AccessorData::AccessorData(const QJsonObject &json) +{ + bufferViewName = json.value(KEY_BUFFER_VIEW).toString(); + offset = 0; + stride = 0; + int componentType = json.value(KEY_COMPONENT_TYPE).toInt(); + type = accessorTypeFromJSON(componentType); + count = json.value(KEY_COUNT).toInt(); + dataSize = accessorDataSizeFromJson(json.value(KEY_TYPE).toString()); + + if ( json.contains(KEY_BYTE_OFFSET)) + offset = json.value(KEY_BYTE_OFFSET).toInt(); + if ( json.contains(KEY_BYTE_STRIDE)) + stride = json.value(KEY_BYTE_STRIDE).toInt(); +} + +bool GLTFParser::isGLTFPath(const QString& path) +{ + QFileInfo finfo(path); + if (!finfo.exists()) + return false; + + // might need to detect other things in the future, but would + // prefer to avoid doing a full parse. + QString suffix = finfo.suffix().toLower(); + return (suffix == QStringLiteral("json") || suffix == QStringLiteral("gltf")); +} + +void GLTFParser::renameFromJson(const QJsonObject &json, QObject * const object) +{ + if ( json.contains(KEY_NAME) ) + object->setObjectName( json.value(KEY_NAME).toString() ); +} + +QString GLTFParser::standardUniformNamefromSemantic(const QString &semantic) +{ + //Standard Uniforms + //if (semantic == QStringLiteral("LOCAL")); + if (semantic == QStringLiteral("MODEL")) + return QStringLiteral("modelMatrix"); + if (semantic == QStringLiteral("VIEW")) + return QStringLiteral("viewMatrix"); + if (semantic == QStringLiteral("PROJECTION")) + return QStringLiteral("projectionMatrix"); + if (semantic == QStringLiteral("MODELVIEW")) + return QStringLiteral("modelView"); + if (semantic == QStringLiteral("MODELVIEWPROJECTION")) + return QStringLiteral("modelViewProjection"); + if (semantic == QStringLiteral("MODELINVERSE")) + return QStringLiteral("inverseModelMatrix"); + if (semantic == QStringLiteral("VIEWINVERSE")) + return QStringLiteral("inverViewMatrix"); + if (semantic == QStringLiteral("PROJECTIONINVERSE")) + return QStringLiteral("inverseProjectionMatrix"); + if (semantic == QStringLiteral("MODELVIEWPROJECTIONINVERSE")) + return QStringLiteral("inverseModelViewProjection"); + if (semantic == QStringLiteral("MODELINVERSETRANSPOSE")) + return QStringLiteral("modelNormalMatrix"); + if (semantic == QStringLiteral("MODELVIEWINVERSETRANSPOSE")) + return QStringLiteral("modelViewNormal"); + if (semantic == QStringLiteral("VIEWPORT")) + return QStringLiteral("viewportMatrix"); + + return QString(); +} + +QString GLTFParser::standardAttributeNameFromSemantic(const QString &semantic) +{ + //Standard Attributes + if (semantic.startsWith(QStringLiteral("POSITION"))) + return QAttribute::defaultPositionAttributeName(); + if (semantic.startsWith(QStringLiteral("NORMAL"))) + return QAttribute::defaultNormalAttributeName(); + if (semantic.startsWith(QStringLiteral("TEXCOORD"))) + return QAttribute::defaultTextureCoordinateAttributeName(); + if (semantic.startsWith(QStringLiteral("COLOR"))) + return QAttribute::defaultColorAttributeName(); + if (semantic.startsWith(QStringLiteral("TANGENT"))) + return QAttribute::defaultTangentAttributeName(); + +// if (semantic.startsWith(QStringLiteral("JOINT"))); +// if (semantic.startsWith(QStringLiteral("JOINTMATRIX"))); +// if (semantic.startsWith(QStringLiteral("WEIGHT"))); + + return QString(); +} + +QEntity* GLTFParser::defaultScene() +{ + if (m_defaultScene.isEmpty()) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "no default scene"; + return NULL; + } + + return scene(m_defaultScene); +} + +QMaterial* GLTFParser::material(const QString &id) +{ + if (m_materialCache.contains(id)) + return m_materialCache.value(id); + + QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject(); + if (!mats.contains(id)) { + qCWarning(GLTFParserLog) << "unknown material" << id << "in GLTF file" << m_basePath; + return NULL; + } + + QJsonObject jsonObj = mats.value(id).toObject(); + + QJsonObject tech = jsonObj.value(KEY_INSTANCE_TECHNIQUE).toObject(); + QString tname = tech.value(KEY_TECHNIQUE).toString(); + if (!m_techniques.contains(tname)) { + qCWarning(GLTFParserLog) << "unknown technique" << tname + << "for material" << id << "in GLTF file" << m_basePath; + return NULL; + } + + QTechnique *technique = m_techniques.value(tname); + // glTF doesn't deal in effects, but we need a trivial one to wrap + // up our techniques + // However we need to create a unique effect for each material instead + // of caching because QMaterial does not keep up with effects + // its not the parent of. + QEffect* effect = new QEffect; + effect->setObjectName(tname); + effect->addTechnique(technique); + + QMaterial* mat = new QMaterial; + mat->setEffect(effect); + + renameFromJson(jsonObj, mat); + + QJsonObject values = tech.value(KEY_VALUES).toObject(); + Q_FOREACH (QString vName, values.keys()) { + QParameter *param = Q_NULLPTR; + Q_FOREACH (QParameter *parameter, technique->parameters()) { + if (parameter->name() == vName) { + param = parameter; + break; + } + } + if (param == Q_NULLPTR) { + qCWarning(GLTFParserLog) << "unknown parameter:" << vName << "in technique" << tname + << "processing material" << id; + continue; + } + + ParameterData paramData = m_parameterDataDict.value(param); + QVariant var = parameterValueFromJSON(paramData.type, values.value(vName)); + + mat->addParameter(new QParameter(param->name(), var)); + } // of material technique-instance values iteration + + m_materialCache[id] = mat; + return mat; +} + +QCameraLens* GLTFParser::camera(const QString &id) const +{ + QJsonObject cams = m_json.object().value(KEY_CAMERAS).toObject(); + if (!cams.contains(id)) { + qCWarning(GLTFParserLog) << "unknown camera" << id << "in GLTF file" << m_basePath; + return Q_NULLPTR; + } + + QJsonObject jsonObj = cams.value(id).toObject(); + QString camTy = jsonObj.value(KEY_TYPE).toString(); + + if (camTy == QStringLiteral("perspective")) { + if (!jsonObj.contains(KEY_PERSPECTIVE)) { + qCWarning(GLTFParserLog) << "camera:" << id << "missing 'perspective' object"; + return Q_NULLPTR; + } + + QJsonObject pObj = jsonObj.value(KEY_PERSPECTIVE).toObject(); + double aspectRatio = pObj.value(KEY_ASPECT_RATIO).toDouble(); + double yfov = pObj.value(KEY_YFOV).toDouble(); + double frustumNear = pObj.value(KEY_ZNEAR).toDouble(); + double frustumFar = pObj.value(KEY_ZFAR).toDouble(); + + QCameraLens* result = new QCameraLens; + result->setPerspectiveProjection(yfov, aspectRatio, frustumNear, frustumFar); + return result; + } else if (camTy == QStringLiteral("orthographic")) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "implement me"; + + return Q_NULLPTR; + } else { + qCWarning(GLTFParserLog) << "camera:" << id << "has unsupported type:" << camTy; + return Q_NULLPTR; + } +} + + +void GLTFParser::parse() +{ + if (m_parseDone) + return; + + QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject(); + Q_FOREACH (QString nm, buffers.keys()) { + processJSONBuffer( nm, buffers.value(nm).toObject() ); + } + + QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject(); + loadBufferData(); + Q_FOREACH (QString nm, views.keys()) { + processJSONBufferView( nm, views.value(nm).toObject() ); + } + unloadBufferData(); + + QJsonObject shaders = m_json.object().value(KEY_SHADERS).toObject(); + Q_FOREACH (QString nm, shaders.keys()) { + processJSONShader( nm, shaders.value(nm).toObject() ); + } + + QJsonObject programs = m_json.object().value(KEY_PROGRAMS).toObject(); + Q_FOREACH (QString nm, programs.keys()) { + processJSONProgram( nm, programs.value(nm).toObject() ); + } + + QJsonObject techniques = m_json.object().value(KEY_TECHNIQUES).toObject(); + Q_FOREACH (QString nm, techniques.keys()) { + processJSONTechnique( nm, techniques.value(nm).toObject() ); + } + + QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject(); + Q_FOREACH (QString nm, attrs.keys()) { + processJSONAccessor( nm, attrs.value(nm).toObject() ); + } + + QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject(); + Q_FOREACH (QString nm, meshes.keys()) { + processJSONMesh( nm, meshes.value(nm).toObject() ); + } + + QJsonObject images = m_json.object().value(KEY_IMAGES).toObject(); + Q_FOREACH (QString nm, images.keys()) { + processJSONImage( nm, images.value(nm).toObject() ); + } + + QJsonObject textures = m_json.object().value(KEY_TEXTURES).toObject(); + Q_FOREACH (QString nm, textures.keys()) { + processJSONTexture(nm, textures.value(nm).toObject() ); + } + + m_defaultScene = m_json.object().value(KEY_SCENE).toString(); + m_parseDone = true; +} + +void GLTFParser::cleanup() +{ + m_meshDict.clear(); + m_meshMaterialDict.clear(); + m_accessorDict.clear(); + //Check for Materials with no parent + Q_FOREACH (QMaterial *material, m_materialCache.values()) { + if (material->parent() == Q_NULLPTR) + delete material; + } + m_materialCache.clear(); + m_bufferDatas.clear(); + m_buffers.clear(); + m_shaderPaths.clear(); + //Check for ShaderPrograms with no parent + Q_FOREACH (QShaderProgram *program, m_programs.values()) { + if (program->parent() == Q_NULLPTR) + delete program; + } + m_programs.clear(); + //Check for Techniques with no parent + Q_FOREACH (QTechnique *technique, m_techniques.values()) { + if (technique->parent() == Q_NULLPTR) + delete technique; + } + m_techniques.clear(); + //Check for Textures with no parent + Q_FOREACH (QAbstractTextureProvider *texture, m_textures.values()) { + if (texture->parent() == Q_NULLPTR) + delete texture; + } + m_textures.clear(); + m_imagePaths.clear(); + m_defaultScene.clear(); + m_parameterDataDict.clear(); +} + +void GLTFParser::processJSONBuffer(const QString &id, const QJsonObject& json) +{ + // simply cache buffers for lookup by buffer-views + m_bufferDatas[id] = BufferData(json); +} + +void GLTFParser::processJSONBufferView(const QString &id, const QJsonObject& json) +{ + QString bufName = json.value(KEY_BUFFER).toString(); + if (!m_bufferDatas.contains(bufName)) { + qCWarning(GLTFParserLog) << "unknown buffer:" << bufName << "processing view:" << id; + return; + } + + int target = json.value(KEY_TARGET).toInt(); + QBuffer::BufferType ty(QBuffer::VertexBuffer); + + switch (target) { + case GL_ARRAY_BUFFER: ty = QBuffer::VertexBuffer; break; + case GL_ELEMENT_ARRAY_BUFFER: ty = QBuffer::IndexBuffer; break; + default: + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "buffer" << id << "unsupported target:" << target; + return; + } + + quint64 offset = 0; + if (json.contains(KEY_BYTE_OFFSET)) { + offset = json.value(KEY_BYTE_OFFSET).toInt(); + qCDebug(GLTFParserLog) << "bv:" << id << "has offset:" << offset; + } + + quint64 len = json.value(KEY_BYTE_LENGTH).toInt(); + + QByteArray bytes(m_bufferDatas[bufName].data->mid(offset, len)); + if (bytes.count() != (int) len) { + qCWarning(GLTFParserLog) << "failed to read sufficient bytes from:" << m_bufferDatas[bufName].path + << "for view" << id; + } + + QBuffer *b(new QBuffer(ty)); + b->setData(bytes); + m_buffers[id] = b; +} + +void GLTFParser::processJSONShader(const QString &id, const QJsonObject &jsonObject) +{ + // shaders are trivial for the moment, defer the real work + // to the program section + QString path = jsonObject.value(KEY_URI).toString(); + + QFileInfo info(m_basePath, path); + if (!info.exists()) { + qCWarning(GLTFParserLog) << "can't find shader" << id << "from path" << path; + return; + } + + m_shaderPaths[id] = info.absoluteFilePath(); +} + +void GLTFParser::processJSONProgram(const QString &id, const QJsonObject &jsonObject) +{ + QShaderProgram* prog = new QShaderProgram; + prog->setObjectName(id); + + QString fragName = jsonObject.value(KEY_FRAGMENT_SHADER).toString(), + vertName = jsonObject.value(KEY_VERTEX_SHADER).toString(); + if (!m_shaderPaths.contains(fragName) || !m_shaderPaths.contains(vertName)) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "program:" << id << "missing shader:" + << fragName << vertName; + return; + } + + prog->setFragmentShaderCode(Qt3D::QShaderProgram::loadSource(QUrl::fromLocalFile(m_shaderPaths[fragName]))); + prog->setVertexShaderCode(Qt3D::QShaderProgram::loadSource(QUrl::fromLocalFile(m_shaderPaths[vertName]))); + m_programs[id] = prog; +} + +void GLTFParser::processJSONTechnique(const QString &id, const QJsonObject &jsonObject ) +{ + QTechnique *t = new QTechnique; + t->setObjectName(id); + + QHash<QString, QParameter*> paramDict; + QJsonObject params = jsonObject.value(KEY_PARAMETERS).toObject(); + Q_FOREACH (QString pname, params.keys()) { + QJsonObject po = params.value(pname).toObject(); + + //QString semantic = po.value(KEY_SEMANTIC).toString(); + QParameter *p = new QParameter(t); + p->setName(pname); + m_parameterDataDict.insert(p, ParameterData(po)); + + //If the parameter has default value, set it + QJsonValue value = po.value(KEY_VALUE); + if (!value.isUndefined()) { + int dataType = po.value(KEY_TYPE).toInt(); + p->setValue(parameterValueFromJSON(dataType, value)); + } + + t->addParameter(p); + + paramDict[pname] = p; + } // of parameters iteration + + QJsonObject passes = jsonObject.value(KEY_PASSES).toObject(); + Q_FOREACH (QString pname, passes.keys()) { + QJsonObject po = passes.value(pname).toObject(); + QJsonObject ip = po.value(KEY_INSTANCE_PROGRAM).toObject(); + + QString programName = ip.value(KEY_PROGRAM).toString(); + if (!m_programs.contains(programName)) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "technique" << id << "pass" << pname + << ": missing program" << programName; + continue; + } + + QRenderPass* pass = new QRenderPass; + pass->setShaderProgram(m_programs[programName]); + + QJsonObject attrs = ip.value(KEY_ATTRIBUTES).toObject(); + Q_FOREACH ( QString shaderAttributeName, attrs.keys() ) { + QString pname = attrs.value(shaderAttributeName).toString(); + QParameter *parameter = paramDict.value(pname, Q_NULLPTR); + QString attributeName = pname; + if (parameter == Q_NULLPTR) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "attribute " << pname + << "defined in instanceProgram but not as parameter"; + continue; + } + //Check if the parameter has a standard attribute semantic + QString standardAttributeName = standardAttributeNameFromSemantic(m_parameterDataDict[parameter].semantic); + if (!standardAttributeName.isNull()) { + attributeName = standardAttributeName; + t->removeParameter(parameter); + m_parameterDataDict.remove(parameter); + delete parameter; + } + + pass->addBinding(new QParameterMapping(attributeName, shaderAttributeName, QParameterMapping::Attribute)); + } // of program-instance attributes + + QJsonObject uniforms = ip.value(KEY_UNIFORMS).toObject(); + Q_FOREACH (QString shaderUniformName, uniforms.keys()) { + QString pname = uniforms.value(shaderUniformName).toString(); + QParameter *parameter = paramDict.value(pname, Q_NULLPTR); + if (parameter == Q_NULLPTR) { + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "uniform " << pname + << "defined in instanceProgram but not as parameter"; + continue; + } + //Check if the parameter has a standard uniform semantic + QString standardUniformName = standardUniformNamefromSemantic(m_parameterDataDict[parameter].semantic); + if (standardUniformName.isNull()) { + pass->addBinding(new QParameterMapping(pname, shaderUniformName, QParameterMapping::Uniform)); + } else { + pass->addBinding(new QParameterMapping(standardUniformName, shaderUniformName, QParameterMapping::StandardUniform)); + t->removeParameter(parameter); + m_parameterDataDict.remove(parameter); + delete parameter; + } + } // of program-instance uniforms + + QJsonObject states = po.value(KEY_STATES).toObject(); + + //Process states to enable + QJsonArray enableStatesArray = states.value(KEY_ENABLE).toArray(); + QVector<int> enableStates; + Q_FOREACH (QJsonValue enableValue, enableStatesArray) { + enableStates.append(enableValue.toInt()); + } + + //Process the list of state functions + QJsonObject functions = states.value(KEY_FUNCTIONS).toObject(); + Q_FOREACH (QString functionName, functions.keys()) { + int enableStateType = 0; + QRenderState *renderState = buildState(functionName, functions.value(functionName), enableStateType); + if (renderState != Q_NULLPTR) { + //Remove the need to set a default state values for enableStateType + enableStates.removeOne(enableStateType); + pass->addRenderState(renderState); + } + } + + //Create render states with default values for any remaining enable states + Q_FOREACH (int enableState, enableStates) { + QRenderState *renderState = buildStateEnable(enableState); + if (renderState != Q_NULLPTR) + pass->addRenderState(renderState); + } + + + t->addPass(pass); + } // of passes iteration + + m_techniques[id] = t; +} + +void GLTFParser::processJSONAccessor( const QString &id, const QJsonObject& json ) +{ + m_accessorDict[id] = AccessorData(json); +} + +void GLTFParser::processJSONMesh(const QString &id, const QJsonObject &json) +{ + QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray(); + Q_FOREACH (QJsonValue primitiveValue, primitivesArray) { + QJsonObject primitiveObject = primitiveValue.toObject(); + int type = primitiveObject.value(KEY_PRIMITIVE).toInt(); + QString material = primitiveObject.value(KEY_MATERIAL).toString(); + + if ( material.isEmpty()) { + qCWarning(GLTFParserLog) << "malformed primitive on " << id << ", missing material value" + << material; + continue; + } + + QGeometryRenderer *geometryRenderer = new QGeometryRenderer; + QGeometry *meshGeometry = new QGeometry(geometryRenderer); + + //Set Primitive Type + geometryRenderer->setPrimitiveType(static_cast<QGeometryRenderer::PrimitiveType>(type)); + + //Save Material for mesh + m_meshMaterialDict[geometryRenderer] = material; + + QJsonObject attrs = primitiveObject.value(KEY_ATTRIBUTES).toObject(); + Q_FOREACH (QString attrName, attrs.keys()) { + QString k = attrs.value(attrName).toString(); + if (!m_accessorDict.contains(k)) { + qCWarning(GLTFParserLog) << "unknown attribute accessor:" << k << "on mesh" << id; + continue; + } + + QString attributeName = standardAttributeNameFromSemantic(attrName); + if (attributeName.isEmpty()) + attributeName = attrName; + + //Get buffer handle for accessor + QBuffer *buffer = m_buffers.value(m_accessorDict[k].bufferViewName, Q_NULLPTR); + if (buffer == Q_NULLPTR) { + qCWarning(GLTFParserLog) << "unknown buffer-view:" << m_accessorDict[k].bufferViewName << "processing accessor:" << id; + continue; + } + + QAttribute *attribute = new QAttribute(buffer, + attributeName, + m_accessorDict[k].type, + m_accessorDict[k].dataSize, + m_accessorDict[k].count, + m_accessorDict[k].offset, + m_accessorDict[k].stride); + attribute->setAttributeType(QAttribute::VertexAttribute); + meshGeometry->addAttribute(attribute); + } + + if ( primitiveObject.contains(KEY_INDICES)) { + QString k = primitiveObject.value(KEY_INDICES).toString(); + if (!m_accessorDict.contains(k)) { + qCWarning(GLTFParserLog) << "unknown index accessor:" << k << "on mesh" << id; + } else { + //Get buffer handle for accessor + QBuffer *buffer = m_buffers.value(m_accessorDict[k].bufferViewName, Q_NULLPTR); + if (buffer == Q_NULLPTR) { + qCWarning(GLTFParserLog) << "unknown buffer-view:" << m_accessorDict[k].bufferViewName << "processing accessor:" << id; + continue; + } + + QAttribute *attribute = new QAttribute(buffer, + m_accessorDict[k].type, + m_accessorDict[k].dataSize, + m_accessorDict[k].count, + m_accessorDict[k].offset, + m_accessorDict[k].stride); + attribute->setAttributeType(QAttribute::IndexAttribute); + meshGeometry->addAttribute(attribute); + } + } // of has indices + + geometryRenderer->setGeometry(meshGeometry); + + m_meshDict.insert( id, geometryRenderer); + } // of primitives iteration +} + +void GLTFParser::processJSONImage(const QString &id, const QJsonObject &jsonObject) +{ + QString path = jsonObject.value(KEY_URI).toString(); + QFileInfo info(m_basePath, path); + if (!info.exists()) { + qCWarning(GLTFParserLog) << "can't find image" << id << "from path" << path; + return; + } + + m_imagePaths[id] = info.absoluteFilePath(); +} + +void GLTFParser::processJSONTexture(const QString &id, const QJsonObject &jsonObject) +{ + int target = jsonObject.value(KEY_TARGET).toInt(GL_TEXTURE_2D); + //TODO: support other targets that GL_TEXTURE_2D (though the spec doesn't support anything else) + if (target != GL_TEXTURE_2D) { + qCWarning(GLTFParserLog) << "unsupported texture target: " << target; + return; + } + + QTexture2D* tex = new QTexture2D; + + // TODO: Choose suitable internal format - may vary on OpenGL context type + //int pixelFormat = jsonObj.value(KEY_FORMAT).toInt(GL_RGBA); + int internalFormat = jsonObject.value(KEY_INTERNAL_FORMAT).toInt(GL_RGBA); + + tex->setFormat(static_cast<QAbstractTextureProvider::TextureFormat>(internalFormat)); + + QString samplerId = jsonObject.value(KEY_SAMPLER).toString(); + QString source = jsonObject.value(KEY_SOURCE).toString(); + if (!m_imagePaths.contains(source)) { + qCWarning(GLTFParserLog) << "texture" << id << "references missing image" << source; + return; + } + + QTextureImage *texImage = new QTextureImage(tex); + texImage->setSource(QUrl::fromLocalFile(m_imagePaths[source])); + tex->addTextureImage(texImage); + + QJsonObject samplersDict(m_json.object().value(KEY_SAMPLERS).toObject()); + if (!samplersDict.contains(samplerId)) { + qCWarning(GLTFParserLog) << "texture" << id << "references unknown sampler" << samplerId; + return; + } + + QJsonObject sampler = samplersDict.value(samplerId).toObject(); + + tex->setWrapMode(QTextureWrapMode(static_cast<QTextureWrapMode::WrapMode>(sampler.value(KEY_WRAP_S).toInt()))); + tex->setMinificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MIN_FILTER).toInt())); + if (tex->minificationFilter() == QAbstractTextureProvider::NearestMipMapLinear || + tex->minificationFilter() == QAbstractTextureProvider::LinearMipMapNearest || + tex->minificationFilter() == QAbstractTextureProvider::NearestMipMapNearest || + tex->minificationFilter() == QAbstractTextureProvider::LinearMipMapLinear) { + + tex->setGenerateMipMaps(true); + } + tex->setMagnificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MAG_FILTER).toInt())); + + m_textures[id] = tex; +} + +void GLTFParser::loadBufferData() +{ + Q_FOREACH (QString bufferName, m_bufferDatas.keys()) { + if (m_bufferDatas[bufferName].data == Q_NULLPTR) { + QFile* bufferFile = resolveLocalData(m_bufferDatas[bufferName].path); + QByteArray *data = new QByteArray(bufferFile->readAll()); + m_bufferDatas[bufferName].data = data; + delete bufferFile; + } + } +} + +void GLTFParser::unloadBufferData() +{ + Q_FOREACH (QString bufferName, m_bufferDatas.keys()) { + QByteArray *data = m_bufferDatas[bufferName].data; + delete data; + } +} + +QFile *GLTFParser::resolveLocalData(QString path) const +{ + QDir d(m_basePath); + Q_ASSERT(d.exists()); + + QString absPath = d.absoluteFilePath(path); + QFile* f = new QFile(absPath); + f->open(QIODevice::ReadOnly); + return f; +} + +QVariant GLTFParser::parameterValueFromJSON(int type, const QJsonValue &value) const +{ + if (value.isBool()) { + if (type == GL_BOOL) + return QVariant(static_cast<GLboolean>(value.toBool())); + } else if (value.isString()) { + if (type == GL_SAMPLER_2D) { + //Textures are special because we need to do a lookup to return the + //QAbstractTextureProvider + QString textureId = value.toString(); + if (!m_textures.contains(textureId)) { + qCWarning(GLTFParserLog) << "unknown texture" << textureId; + return QVariant(); + } else { + return QVariant::fromValue(m_textures.value(textureId)); + } + } + } else if (value.isDouble()) { + switch (type) { + case GL_BYTE: + return QVariant(static_cast<GLbyte>(value.toInt())); + case GL_UNSIGNED_BYTE: + return QVariant(static_cast<GLubyte>(value.toInt())); + case GL_SHORT: + return QVariant(static_cast<GLshort>(value.toInt())); + case GL_UNSIGNED_SHORT: + return QVariant(static_cast<GLushort>(value.toInt())); + case GL_INT: + return QVariant(static_cast<GLint>(value.toInt())); + case GL_UNSIGNED_INT: + return QVariant(static_cast<GLuint>(value.toInt())); + case GL_FLOAT: + return QVariant(static_cast<GLfloat>(value.toDouble())); + } + } else if (value.isArray()) { + + QJsonArray valueArray = value.toArray(); + + QVector2D vector2D; + QVector3D vector3D; + QVector4D vector4D; + QVector<float> dataMat2(4, 0.0f); + QVector<float> dataMat3(9, 0.0f); + + switch (type) { + case GL_BYTE: + return QVariant(static_cast<GLbyte>(valueArray.first().toInt())); + case GL_UNSIGNED_BYTE: + return QVariant(static_cast<GLubyte>(valueArray.first().toInt())); + case GL_SHORT: + return QVariant(static_cast<GLshort>(valueArray.first().toInt())); + case GL_UNSIGNED_SHORT: + return QVariant(static_cast<GLushort>(valueArray.first().toInt())); + case GL_INT: + return QVariant(static_cast<GLint>(valueArray.first().toInt())); + case GL_UNSIGNED_INT: + return QVariant(static_cast<GLuint>(valueArray.first().toInt())); + case GL_FLOAT: + return QVariant(static_cast<GLfloat>(valueArray.first().toDouble())); + case GL_FLOAT_VEC2: + vector2D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble())); + vector2D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble())); + return QVariant(vector2D); + case GL_FLOAT_VEC3: + vector3D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble())); + vector3D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble())); + vector3D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble())); + return QVariant(vector3D); + case GL_FLOAT_VEC4: + vector4D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble())); + vector4D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble())); + vector4D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble())); + vector4D.setW(static_cast<GLfloat>(valueArray.at(3).toDouble())); + return QVariant(vector4D); + case GL_INT_VEC2: + vector2D.setX(static_cast<GLint>(valueArray.at(0).toInt())); + vector2D.setY(static_cast<GLint>(valueArray.at(1).toInt())); + return QVariant(vector2D); + case GL_INT_VEC3: + vector3D.setX(static_cast<GLint>(valueArray.at(0).toInt())); + vector3D.setY(static_cast<GLint>(valueArray.at(1).toInt())); + vector3D.setZ(static_cast<GLint>(valueArray.at(2).toInt())); + return QVariant(vector3D); + case GL_INT_VEC4: + vector4D.setX(static_cast<GLint>(valueArray.at(0).toInt())); + vector4D.setY(static_cast<GLint>(valueArray.at(1).toInt())); + vector4D.setZ(static_cast<GLint>(valueArray.at(2).toInt())); + vector4D.setW(static_cast<GLint>(valueArray.at(3).toInt())); + return QVariant(vector4D); + case GL_BOOL: + return QVariant(static_cast<GLboolean>(valueArray.first().toBool())); + case GL_BOOL_VEC2: + vector2D.setX(static_cast<GLboolean>(valueArray.at(0).toBool())); + vector2D.setY(static_cast<GLboolean>(valueArray.at(1).toBool())); + return QVariant(vector2D); + case GL_BOOL_VEC3: + vector3D.setX(static_cast<GLboolean>(valueArray.at(0).toBool())); + vector3D.setY(static_cast<GLboolean>(valueArray.at(1).toBool())); + vector3D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool())); + return QVariant(vector3D); + case GL_BOOL_VEC4: + vector4D.setX(static_cast<GLboolean>(valueArray.at(0).toBool())); + vector4D.setY(static_cast<GLboolean>(valueArray.at(1).toBool())); + vector4D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool())); + vector4D.setW(static_cast<GLboolean>(valueArray.at(3).toBool())); + return QVariant(vector4D); + case GL_FLOAT_MAT2: + //Matrix2x2 is in Row Major ordering (so we need to convert) + dataMat2[0] = static_cast<GLfloat>(valueArray.at(0).toDouble()); + dataMat2[1] = static_cast<GLfloat>(valueArray.at(2).toDouble()); + dataMat2[2] = static_cast<GLfloat>(valueArray.at(1).toDouble()); + dataMat2[3] = static_cast<GLfloat>(valueArray.at(3).toDouble()); + return QVariant::fromValue(QMatrix2x2(dataMat2.constData())); + case GL_FLOAT_MAT3: + //Matrix3x3 is in Row Major ordering (so we need to convert) + dataMat3[0] = static_cast<GLfloat>(valueArray.at(0).toDouble()); + dataMat3[1] = static_cast<GLfloat>(valueArray.at(3).toDouble()); + dataMat3[2] = static_cast<GLfloat>(valueArray.at(6).toDouble()); + dataMat3[3] = static_cast<GLfloat>(valueArray.at(1).toDouble()); + dataMat3[4] = static_cast<GLfloat>(valueArray.at(4).toDouble()); + dataMat3[5] = static_cast<GLfloat>(valueArray.at(7).toDouble()); + dataMat3[6] = static_cast<GLfloat>(valueArray.at(2).toDouble()); + dataMat3[7] = static_cast<GLfloat>(valueArray.at(5).toDouble()); + dataMat3[8] = static_cast<GLfloat>(valueArray.at(8).toDouble()); + return QVariant::fromValue(QMatrix3x3(dataMat3.constData())); + case GL_FLOAT_MAT4: + //Matrix4x4 is Column Major ordering + return QVariant(QMatrix4x4(static_cast<GLfloat>(valueArray.at(0).toDouble()), + static_cast<GLfloat>(valueArray.at(1).toDouble()), + static_cast<GLfloat>(valueArray.at(2).toDouble()), + static_cast<GLfloat>(valueArray.at(3).toDouble()), + static_cast<GLfloat>(valueArray.at(4).toDouble()), + static_cast<GLfloat>(valueArray.at(5).toDouble()), + static_cast<GLfloat>(valueArray.at(6).toDouble()), + static_cast<GLfloat>(valueArray.at(7).toDouble()), + static_cast<GLfloat>(valueArray.at(8).toDouble()), + static_cast<GLfloat>(valueArray.at(9).toDouble()), + static_cast<GLfloat>(valueArray.at(10).toDouble()), + static_cast<GLfloat>(valueArray.at(11).toDouble()), + static_cast<GLfloat>(valueArray.at(12).toDouble()), + static_cast<GLfloat>(valueArray.at(13).toDouble()), + static_cast<GLfloat>(valueArray.at(14).toDouble()), + static_cast<GLfloat>(valueArray.at(15).toDouble()))); + case GL_SAMPLER_2D: + return QVariant(valueArray.at(0).toString()); + } + } + return QVariant(); +} + +QAttribute::DataType GLTFParser::accessorTypeFromJSON(int componentType) +{ + if (componentType == GL_BYTE) { + return QAttribute::Byte; + } else if (componentType == GL_UNSIGNED_BYTE) { + return QAttribute::UnsignedByte; + } else if (componentType == GL_SHORT) { + return QAttribute::Short; + } else if (componentType == GL_UNSIGNED_SHORT) { + return QAttribute::UnsignedShort; + } else if (componentType == GL_FLOAT) { + return QAttribute::Float; + } + + //There shouldn't be an invalid case here + qCWarning(GLTFParserLog) << "unsupported accessor type" << componentType; + return QAttribute::Float; +} + +uint GLTFParser::accessorDataSizeFromJson(const QString &type) +{ + QString typeName = type.toUpper(); + if (typeName == "SCALAR") + return 1; + if (typeName == "VEC2") + return 2; + if (typeName == "VEC3") + return 3; + if (typeName == "VEC4") + return 4; + if (typeName == "MAT2") + return 4; + if (typeName == "MAT3") + return 9; + if (typeName == "MAT4") + return 16; + + return 0; +} + +QRenderState *GLTFParser::buildStateEnable(int state) +{ + int type = 0; + //By calling buildState with QJsonValue(), a Render State with + //default values is created. + + if (state == GL_BLEND) { + //It doesn't make sense to handle this state alone + return Q_NULLPTR; + } + + if (state == GL_CULL_FACE) { + return buildState(QStringLiteral("cullFace"), QJsonValue(), type); + } + + if (state == GL_DEPTH_TEST) { + return buildState(QStringLiteral("depthFunc"), QJsonValue(), type); + } + + if (state == GL_POLYGON_OFFSET_FILL) { + return buildState(QStringLiteral("polygonOffset"), QJsonValue(), type); + } + + if (state == GL_SAMPLE_ALPHA_TO_COVERAGE) { + return new QAlphaCoverage(); + } + + if (state == GL_SCISSOR_TEST) { + return buildState(QStringLiteral("scissor"), QJsonValue(), type); + } + + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << state; + + return Q_NULLPTR; +} + +QRenderState* GLTFParser::buildState(const QString& functionName, const QJsonValue &value, int &type) +{ + type = -1; + QJsonArray values = value.toArray(); + + if (functionName == QStringLiteral("blendColor")) { + type = GL_BLEND; + //TODO: support render state blendColor + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName; + return Q_NULLPTR; + } + + if (functionName == QStringLiteral("blendEquationSeparate")) { + type = GL_BLEND; + //TODO: support settings blendEquation alpha + QBlendEquation *blendEquation = new QBlendEquation; + blendEquation->setMode((QBlendEquation::BlendMode)values.at(0).toInt(GL_FUNC_ADD)); + return blendEquation; + } + + if (functionName == QStringLiteral("blendFuncSeparate")) { + type = GL_BLEND; + QBlendStateSeparate *blendState = new QBlendStateSeparate; + blendState->setSrcRGB((QBlendState::Blending)values.at(0).toInt(GL_ONE)); + blendState->setSrcAlpha((QBlendState::Blending)values.at(1).toInt(GL_ONE)); + blendState->setDstRGB((QBlendState::Blending)values.at(2).toInt(GL_ZERO)); + blendState->setDstAlpha((QBlendState::Blending)values.at(3).toInt(GL_ZERO)); + return blendState; + } + + if (functionName == QStringLiteral("colorMask")) { + QColorMask *colorMask = new QColorMask; + colorMask->setRed(values.at(0).toBool(true)); + colorMask->setGreen(values.at(1).toBool(true)); + colorMask->setBlue(values.at(2).toBool(true)); + colorMask->setAlpha(values.at(3).toBool(true)); + return colorMask; + } + + if (functionName == QStringLiteral("cullFace")) { + type = GL_CULL_FACE; + QCullFace *cullFace = new QCullFace; + cullFace->setMode((QCullFace::CullingMode)values.at(0).toInt(GL_BACK)); + return cullFace; + } + + if (functionName == QStringLiteral("depthFunc")) { + type = GL_DEPTH_TEST; + QDepthTest *depthTest = new QDepthTest; + depthTest->setFunc((QDepthTest::DepthFunc)values.at(0).toInt(GL_LESS)); + return depthTest; + } + + if (functionName == QStringLiteral("depthMask")) { + QDepthMask *depthMask = new QDepthMask; + depthMask->setMask(values.at(0).toBool(true)); + } + + if (functionName == QStringLiteral("depthRange")) { + //TODO: support render state depthRange + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName; + return Q_NULLPTR; + } + + if (functionName == QStringLiteral("frontFace")) { + QFrontFace *frontFace = new QFrontFace; + frontFace->setDirection((QFrontFace::FaceDir)values.at(0).toInt(GL_CCW)); + return frontFace; + } + + if (functionName == QStringLiteral("lineWidth")) { + //TODO: support render state lineWidth + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName; + return Q_NULLPTR; + } + + if (functionName == QStringLiteral("polygonOffset")) { + type = GL_POLYGON_OFFSET_FILL; + QPolygonOffset *polygonOffset = new QPolygonOffset; + polygonOffset->setFactor((float)values.at(0).toDouble(0.0f)); + polygonOffset->setUnits((float)values.at(1).toDouble(0.0f)); + return polygonOffset; + } + + if (functionName == QStringLiteral("scissor")) { + type = GL_SCISSOR_TEST; + QScissorTest *scissorTest = new QScissorTest; + scissorTest->setLeft(values.at(0).toDouble(0.0f)); + scissorTest->setBottom(values.at(1).toDouble(0.0f)); + scissorTest->setWidth(values.at(2).toDouble(0.0f)); + scissorTest->setHeight(values.at(3).toDouble(0.0f)); + return scissorTest; + } + + qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName; + return Q_NULLPTR; +} + +} // namespace Qt3D + +QT_END_NAMESPACE diff --git a/src/render/io/gltfparser_p.h b/src/plugins/sceneparsers/gltf/gltfparser_p.h index 0ca5edc28..5aed37f53 100644 --- a/src/render/io/gltfparser_p.h +++ b/src/plugins/sceneparsers/gltf/gltfparser_p.h @@ -38,15 +38,12 @@ #ifndef GLTFPARSER_H #define GLTFPARSER_H -#include <Qt3DRenderer/qmeshdata.h> +#include <QtCore/QJsonDocument> +#include <QtCore/QMultiHash> + #include <Qt3DRenderer/qattribute.h> -#include <Qt3DCore/qentity.h> -#include <Qt3DRenderer/qtechnique.h> #include <Qt3DRenderer/qbuffer.h> -#include <QJsonDocument> -#include <QMultiHash> -#include <Qt3DRenderer/qabstractmesh.h> -#include <QImage> +#include <Qt3DRenderer/qmeshdata.h> #include <Qt3DRenderer/private/abstractsceneparser_p.h> @@ -62,44 +59,103 @@ class QEffect; class QCamera; class QCameraLens; class QAbstractTextureProvider; +class QRenderState; +class QTechnique; +class QParameter; +class QEntity; +class QGeometryRenderer; + +Q_DECLARE_LOGGING_CATEGORY(GLTFParserLog) class GLTFParser : public AbstractSceneParser { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt3DRenderer.GLTFParser") public: GLTFParser(); + ~GLTFParser(); void setBasePath(const QString& path); - bool setJSON( QJsonDocument json ); + bool setJSON( const QJsonDocument &json ); // SceneParserInterface interface - void setSource(const QUrl &source) Q_DECL_OVERRIDE; - bool isExtensionSupported(const QUrl &source) const Q_DECL_OVERRIDE; - - /** - * @brief instantiate Create Nodes based on glTf JSON document - * @return A new scene-graph fragment based on the provided glTf - */ - QEntity *node(const QString &id) Q_DECL_OVERRIDE; - QEntity *scene(const QString &id = QString()) Q_DECL_OVERRIDE; + void setSource(const QUrl &source) Q_DECL_FINAL; + bool isExtensionSupported(const QUrl &source) const Q_DECL_FINAL; + QEntity *node(const QString &id) Q_DECL_FINAL; + QEntity *scene(const QString &id = QString()) Q_DECL_FINAL; private: + class BufferData + { + public: + BufferData(); + + BufferData(QJsonObject json); + + quint64 length; + QString path; + QByteArray *data; + // type if ever useful + }; + + class ParameterData + { + public: + ParameterData(); + ParameterData(QJsonObject json); + + QString semantic; + int type; + }; + + class AccessorData + { + public: + AccessorData(); + AccessorData(const QJsonObject& json); + + QString bufferViewName; + QAttribute::DataType type; + uint dataSize; + int count; + int offset; + int stride; + }; + static bool isGLTFPath(const QString &path); + static void renameFromJson(const QJsonObject& json, QObject * const object ); + static QString standardUniformNamefromSemantic(const QString &semantic); + static QString standardAttributeNameFromSemantic(const QString &semantic); QEntity *defaultScene(); - QMeshDataPtr mesh(const QString &id); QMaterial *material(const QString &id); - QCameraLens *camera(const QString &id); + QCameraLens *camera(const QString &id) const; void parse(); + void cleanup(); + + void processJSONBuffer(const QString &id, const QJsonObject &json); + void processJSONBufferView(const QString &id, const QJsonObject &json); + void processJSONShader(const QString &id, const QJsonObject &jsonObject); + void processJSONProgram(const QString &id, const QJsonObject &jsonObject); + void processJSONTechnique(const QString &id, const QJsonObject &jsonObject); + void processJSONAccessor(const QString &id, const QJsonObject &json); + void processJSONMesh(const QString &id, const QJsonObject &json); + void processJSONImage(const QString &id, const QJsonObject &jsonObject); + void processJSONTexture(const QString &id, const QJsonObject &jsonObject); + + void loadBufferData(); + void unloadBufferData(); + + QFile* resolveLocalData(QString path) const; - void processJSONMesh( QString id, QJsonObject jsonObj ); - void processJSONAccessor(QString id, const QJsonObject &json); - void processJSONBuffer(QString id, const QJsonObject &json); - void processJSONBufferView(QString id, const QJsonObject &json); + QVariant parameterValueFromJSON(int type, const QJsonValue &value) const; + static QAbstractAttribute::DataType accessorTypeFromJSON(int componentType); + static uint accessorDataSizeFromJson(const QString &type); - void processName( const QJsonObject& json, QObject* ins ); + static QRenderState *buildStateEnable(int state); + static QRenderState *buildState(const QString& functionName, const QJsonValue &value, int &type); QJsonDocument m_json; QString m_basePath; @@ -108,25 +164,13 @@ private: // multi-hash because our QMeshData corresponds to a single primitive // in glTf. - QMultiHash<QString, QMeshDataPtr> m_meshDict; + QMultiHash<QString, QGeometryRenderer*> m_meshDict; // GLTF assigns materials at the mesh level, but we do them as siblings, // so record the association here for when we instantiate meshes - QMap<QMeshData*, QString> m_meshMaterialDict; + QMap<QGeometryRenderer*, QString> m_meshMaterialDict; - QMap<QString, QAttribute *> m_attributeDict; - - class BufferData - { - public: - BufferData(); - - BufferData(QJsonObject json); - - quint64 length; - QString path; - // type if ever useful - }; + QMap<QString, AccessorData> m_accessorDict; QMap<QString, QMaterial*> m_materialCache; @@ -137,25 +181,10 @@ private: QMap<QString, QShaderProgram*> m_programs; QMap<QString, QTechnique *> m_techniques; - // glTF doesn't deal in effects, but we need a trivial one to wrap - // up our techniques - QMap<QString, QEffect*> m_effectProxies; + QMap<QParameter*, ParameterData> m_parameterDataDict; QMap<QString, QAbstractTextureProvider*> m_textures; - QMap<QString, QImage> m_images; - - QFile* resolveLocalData(QString path); - - void processJSONShader(QString id, QJsonObject jsonObj); - void processJSONProgram(QString id, QJsonObject jsonObj); - void processJSONTechnique(QString id, QJsonObject jsonObj); - - void processJSONImage(QString id, QJsonObject jsonObj); - void processJSONTexture(QString id, QJsonObject jsonObj); - - QVariant parameterValueFromJSON(QParameter *p, QJsonValue val); - - //Render::RenderState *buildState(const QByteArray& nm, QJsonValue obj); + QMap<QString, QString> m_imagePaths; }; } // namespace Qt3D diff --git a/src/plugins/sceneparsers/sceneparsers.pro b/src/plugins/sceneparsers/sceneparsers.pro index 53899e493..f7a922991 100644 --- a/src/plugins/sceneparsers/sceneparsers.pro +++ b/src/plugins/sceneparsers/sceneparsers.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs config_assimp|win32:!wince*|osx: SUBDIRS += assimp +SUBDIRS += gltf + diff --git a/src/render/frontend/qabstractsceneloader.cpp b/src/render/frontend/qabstractsceneloader.cpp index 4108b81e5..539fdcf5e 100644 --- a/src/render/frontend/qabstractsceneloader.cpp +++ b/src/render/frontend/qabstractsceneloader.cpp @@ -38,7 +38,6 @@ #include "qabstractsceneloader_p.h" #include <Qt3DRenderer/private/renderlogging_p.h> #include <Qt3DRenderer/private/abstractsceneparser_p.h> -#include <Qt3DRenderer/private/gltfparser_p.h> #include <Qt3DCore/qscenepropertychange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/io/gltfparser.cpp b/src/render/io/gltfparser.cpp deleted file mode 100644 index 65c800fb0..000000000 --- a/src/render/io/gltfparser.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "gltfparser_p.h" - -#include "texturedata.h" -#include <Qt3DRenderer/private/renderlogging_p.h> - -#include <Qt3DCore/qentity.h> -#include <qabstractmesh.h> -#include <qmaterial.h> -#include <qtechnique.h> -#include <qshaderprogram.h> -#include <qeffect.h> -#include <Qt3DCore/qcamera.h> -#include <Qt3DCore/qtransform.h> -#include <Qt3DCore/qmatrixtransform.h> -#include <Qt3DCore/qcameralens.h> -#include <Qt3DCore/private/qurlhelper_p.h> -#include <qtexture.h> -#include <qparameter.h> - -#include <QJsonDocument> -#include <QJsonObject> -#include <QJsonArray> -#include <QFile> -#include <QDir> -#include <QFileInfo> -#include <QQuaternion> -#include <QMatrix4x4> -#include <QColor> -#include <QVector2D> -#include <QVector3D> -#include <QUrl> - -// need to move these to somewhere common? -#include <Qt3DRenderer/private/renderstate_p.h> -#include <Qt3DRenderer/private/blendstate_p.h> -#include <private/qabstractmesh_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3D { -namespace { - -const QString KEY_CAMERA = QStringLiteral("camera"); -const QString KEY_CAMERAS = QStringLiteral("cameras"); -const QString KEY_SCENES = QStringLiteral("scenes"); -const QString KEY_NODES = QStringLiteral("nodes"); -const QString KEY_MESHES = QStringLiteral("meshes"); -const QString KEY_CHILDREN = QStringLiteral("children"); -const QString KEY_MATRIX = QStringLiteral("matrix"); -const QString KEY_TYPE = QStringLiteral("type"); -const QString KEY_PERSPECTIVE =QStringLiteral("perspective"); -const QString KEY_NAME = QStringLiteral("name"); -const QString KEY_COUNT = QStringLiteral("count"); -const QString KEY_YFOV = QStringLiteral("yfov"); -const QString KEY_ZNEAR = QStringLiteral("znear"); -const QString KEY_ZFAR = QStringLiteral("zfar"); -const QString KEY_MATERIALS = QStringLiteral("materials"); -const QString KEY_TECHNIQUE = QStringLiteral("technique"); -const QString KEY_VALUES = QStringLiteral("values"); -const QString KEY_BUFFERS = QStringLiteral("buffers"); -const QString KEY_SHADERS = QStringLiteral("shaders"); -const QString KEY_PROGRAMS = QStringLiteral("programs"); -const QString KEY_PROGRAM = QStringLiteral("program"); -const QString KEY_TECHNIQUES = QStringLiteral("techniques"); -const QString KEY_ACCESSORS = QStringLiteral("accessors"); -const QString KEY_IMAGES = QStringLiteral("images"); -const QString KEY_TEXTURES = QStringLiteral("textures"); -const QString KEY_SCENE = QStringLiteral("scene"); -const QString KEY_BUFFER = QStringLiteral("buffer"); -const QString KEY_TARGET = QStringLiteral("target"); -const QString KEY_BYTE_OFFSET = QStringLiteral("byteOffset"); -const QString KEY_BYTE_LENGTH = QStringLiteral("byteLength"); -const QString KEY_BYTE_STRIDE = QStringLiteral("byteStride"); -const QString KEY_PRIMITIVES = QStringLiteral("primitives"); -const QString KEY_PRIMITIVE = QStringLiteral("primitive"); -const QString KEY_MATERIAL = QStringLiteral("material"); -const QString KEY_ATTRIBUTES = QStringLiteral("attributes"); -const QString KEY_INDICES = QStringLiteral("indices"); -const QString KEY_PATH = QStringLiteral("path"); -const QString KEY_FORMAT = QStringLiteral("format"); -const QString KEY_PASSES = QStringLiteral("passes"); -const QString KEY_SOURCE = QStringLiteral("source"); -const QString KEY_SAMPLER = QStringLiteral("sampler"); -const QString KEY_SAMPLERS = QStringLiteral("samplers"); -const QString KEY_LENGTH = QStringLiteral("length"); -const QString KEY_SEMANTIC = QStringLiteral("semantic"); -const QString KEY_STATES = QStringLiteral("states"); -const QString KEY_UNIFORMS = QStringLiteral("uniforms"); -const QString KEY_PARAMETERS = QStringLiteral("parameters"); -const QString KEY_WRAP_S = QStringLiteral("wrapS"); -const QString KEY_MIN_FILTER = QStringLiteral("minFilter"); -const QString KEY_MAG_FILTER = QStringLiteral("magFilter"); - -const QString KEY_INSTANCE_TECHNIQUE = QStringLiteral("instanceTechnique"); -const QString KEY_INSTANCE_PROGRAM = QStringLiteral("instanceProgram"); -const QString KEY_BUFFER_VIEWS = QStringLiteral("bufferViews"); -const QString KEY_BUFFER_VIEW = QStringLiteral("bufferView"); -const QString KEY_VERTEX_SHADER = QStringLiteral("vertexShader"); -const QString KEY_FRAGMENT_SHADER = QStringLiteral("fragmentShader"); -const QString KEY_INTERNAL_FORMAT = QStringLiteral("internalFormat"); - -//Parameter::StandardUniform parseSemanticName(const QByteArray& s) -//{ -// if (s == "MODEL") return Parameter::ModelMatrix; -// if (s == "VIEW") return Parameter::ViewMatrix; -// if (s == "PROJECTION") return Parameter::ProjectionMatrix; -// if (s == "MODELVIEW") return Parameter::ModelView; -// if (s == "MODELVIEWPROJECTION") -// return Parameter::ModelViewProjection; - -// if (s == "MODELINVERSE") return Parameter::ModelInverse; -// if (s == "VIEWINVERSE") return Parameter::ViewInverse; -// if (s == "PROJECTIONINVERSE") -// return Parameter::ProjectionInverse; -// if (s == "MODELVIEWINVERSE") -// return Parameter::ModelViewInverse; -// if (s == "MODELVIEWPROJECTIONINVERSE") -// return Parameter::ModelViewProjectionInverse; - -// if (s == "MODELINVERSETRANSPOSE") -// return Parameter::ModelNormal; -// if (s == "MODELVIEWINVERSETRANSPOSE") -// return Parameter::ModelViewNormal; - -// return Parameter::None; -//} - -//QParameter::OpenGLTypes parseType(const QByteArray &s) -//{ -// if (s == "BYTE") return QParameter::Undefined; -// if (s == "BYTE_VEC2") return QParameter::Undefined; -// if (s == "BYTE_VEC3") return QParameter::Undefined; -// if (s == "BYTE_VEC4") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC2") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC3") return QParameter::Undefined; -// if (s == "UNSIGNED_BYTE_VEC4") return QParameter::Undefined; -// if (s == "SHORT") return QParameter::Undefined; -// if (s == "SHORT_VEC2") return QParameter::Undefined; -// if (s == "SHORT_VEC3") return QParameter::Undefined; -// if (s == "SHORT_VEC4") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC2") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC3") return QParameter::Undefined; -// if (s == "UNSIGNED_SHORT_VEC4") return QParameter::Undefined; -// if (s == "FLOAT") return QParameter::Float; -// if (s == "FLOAT_VEC2") return QParameter::FloatVec2; -// if (s == "FLOAT_VEC3") return QParameter::FloatVec3; -// if (s == "FLOAT_VEC4") return QParameter::FloatVec4; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat2; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat3; -// if (s == "FLOAT_MAT2") return QParameter::FloatMat4; -// if (s == "INT") return QParameter::Int; -// if (s == "INT_VEC2") return QParameter::IntVec2; -// if (s == "INT_VEC3") return QParameter::IntVec3; -// if (s == "INT_VEC4") return QParameter::IntVec4; -// if (s == "BOOL") return QParameter::Bool; -// if (s == "BOOL_VEC2") return QParameter::BoolVec2; -// if (s == "BOOL_VEC3") return QParameter::BoolVec3; -// if (s == "BOOL_VEC4") return QParameter::BoolVec4; - -// return QParameter::Undefined; -//} - -QAbstractAttribute::DataType typeFromGLType(GLint dataType, uint &dataCount) -{ - switch (dataType) { - - case GL_UNSIGNED_SHORT: - dataCount = 1; - return QAbstractAttribute::UnsignedShort; - - case GL_UNSIGNED_BYTE: - dataCount = 1; - return QAbstractAttribute::UnsignedByte; - - case GL_UNSIGNED_INT: - dataCount = 1; - return QAbstractAttribute::UnsignedInt; - - case GL_SHORT: - dataCount = 1; - return QAbstractAttribute::Short; - - case GL_BYTE: - dataCount = 1; - return QAbstractAttribute::Byte; - - case GL_INT: - dataCount = 1; - return QAbstractAttribute::Int; - - case GL_FLOAT: - dataCount = 1; - break; - - case GL_FLOAT_VEC2: - dataCount = 2; - break; - - case GL_FLOAT_VEC3: - dataCount = 3; - break; - - case GL_FLOAT_VEC4: - dataCount = 4; - break; - -// TO DO: Handle doubles - - default: - Q_UNREACHABLE(); - } - - return QAbstractAttribute::Float; -} - -} // of anonymous namespace - -class GLTFParserMeshPrivate; - -class GLTFParserMeshFunctor : public QAbstractMeshFunctor -{ -public: - explicit GLTFParserMeshFunctor(QMeshDataPtr meshData = QMeshDataPtr()); - QMeshDataPtr operator ()() Q_DECL_OVERRIDE; - bool operator ==(const QAbstractMeshFunctor &other) const Q_DECL_OVERRIDE; - QT3D_FUNCTOR(GLTFParserMeshFunctor) -private: - QMeshDataPtr m_meshData; -}; - -class GLTFParserMesh : public QAbstractMesh -{ - Q_OBJECT -public: - explicit GLTFParserMesh(QNode *parent = 0); - - void setData(QMeshDataPtr data); - QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_FINAL; - -protected: - void copy(const QNode *ref) Q_DECL_FINAL; - -private: - QT3D_CLONEABLE(GLTFParserMesh) - Q_DECLARE_PRIVATE(GLTFParserMesh) -}; - -class GLTFParserMeshPrivate : public QAbstractMeshPrivate -{ -public: - GLTFParserMeshPrivate() - : QAbstractMeshPrivate() - {} - - Q_DECLARE_PUBLIC(GLTFParserMesh) - QMeshDataPtr m_meshData; -}; - -GLTFParser::GLTFParser() : AbstractSceneParser(), - m_parseDone(false) -{ -} - -bool GLTFParser::isGLTFPath(const QString& path) -{ - QFileInfo finfo(path); - if (!finfo.exists()) - return false; - - // might need to detect other things in the future, but would - // prefer to avoid doing a full parse. - return (finfo.suffix().toLower() == QStringLiteral("json")); -} - -void GLTFParser::setBasePath(const QString& path) -{ - m_basePath = path; -} - -bool GLTFParser::setJSON( QJsonDocument json ) -{ - if ( !json.isObject() ) { - return false; - } - - m_json = json; - m_parseDone = false; - - m_meshDict.clear(); - m_attributeDict.clear(); - m_defaultScene.clear(); - - return true; -} - -/*! - * Sets the \a path used by the parser to load the scene file. - * If the file is valid, parsing is automatically triggered. - */ -void GLTFParser::setSource(const QUrl &source) -{ - const QString path = QUrlHelper::urlToLocalFileOrQrc(source); - QFileInfo finfo(path); - if (!finfo.exists()) { - qWarning() << "missing file:" << path; - return; - } - QFile f(path); - f.open(QIODevice::ReadOnly); - - if (!setJSON(QJsonDocument::fromJson(f.readAll()))) { - qWarning() << "not a JSON document"; - return; - } - - setBasePath(finfo.dir().absolutePath()); -} - -/*! - * Returns true if the extension of \a path is supported by the - * GLTF parser. - */ -bool GLTFParser::isExtensionSupported(const QUrl &source) const -{ - const QString path = QUrlHelper::urlToLocalFileOrQrc(source); - return GLTFParser::isGLTFPath(path); -} - -QMeshDataPtr GLTFParser::mesh(const QString &id) -{ - parse(); - if (m_meshDict.contains(id)) - return m_meshDict.value(id); - - qWarning() << "Unknown mesh" << id << "in GLTF file" << m_basePath; - return QMeshDataPtr(); -} - -QEntity* GLTFParser::defaultScene() -{ - parse(); - if (m_defaultScene.isEmpty()) { - qWarning() << Q_FUNC_INFO << "no default scene"; - return NULL; - } - - return scene(m_defaultScene); -} - -QEntity* GLTFParser::scene(const QString &id) -{ - parse(); - - QJsonObject scenes = m_json.object().value(KEY_SCENES).toObject(); - if (!scenes.contains(id)) { - qWarning() << "GLTF: no such scene" << id << "in file" << m_basePath; - return defaultScene(); - } - - QJsonObject sceneObj = scenes.value(id).toObject(); - QEntity* sceneEntity = new QEntity; - foreach (QJsonValue nnv, sceneObj.value(KEY_NODES).toArray()) { - QString nodeName = nnv.toString(); - QEntity* child = node(nodeName); - if (!child) - continue; - child->setParent(sceneEntity); - } - - return sceneEntity; -} - -QEntity* GLTFParser::node(const QString &id) -{ - QJsonObject nodes = m_json.object().value(KEY_NODES).toObject(); - if (!nodes.contains(id)) { - qWarning() << "unknown node" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QJsonObject jsonObj = nodes.value(id).toObject(); - QEntity* result( new QEntity ); - parse(); - - if ( jsonObj.contains(KEY_CHILDREN) ) - { - foreach (QJsonValue c, jsonObj.value(KEY_CHILDREN).toArray()) { - QEntity* child = node(c.toString()); - if (!child) - continue; - child->setParent(result); - } - } - - if ( jsonObj.contains(KEY_MESHES) ) - { - typedef QList<GLTFParserMesh *> MeshList; - QMap<QString, MeshList> materialDict; - - foreach (QJsonValue m, jsonObj.value(KEY_MESHES).toArray()) - { - if (!m_meshDict.contains(m.toString())) { - qWarning() << "node" << id << "references unknown mesh" << m.toString(); - continue; - } - - foreach (QMeshDataPtr md, m_meshDict.values(m.toString())) { - QString matId = m_meshMaterialDict[md.data()]; - GLTFParserMesh* meshComp = new GLTFParserMesh; - meshComp->setData(md); - materialDict[matId].append(meshComp); - } - } - - if (materialDict.size() == 1) { - // common case - result->addComponent(material(materialDict.firstKey())); - foreach (GLTFParserMesh* m, materialDict.first()) - result->addComponent(m); - } else { - // need to make a child entity per material - foreach (QString matId, materialDict.keys()) { - QEntity* subEntity(new QEntity); - subEntity->setParent(result); - - subEntity->addComponent(material(matId)); - foreach (GLTFParserMesh* m, materialDict.value(matId)) - subEntity->addComponent(m); - } // of distinct material iteration - } // of multiple materials case - } - - processName(jsonObj, result); - - if ( jsonObj.contains(KEY_MATRIX) ) - { - QMatrix4x4 m(Qt::Uninitialized); - - QJsonArray matrixValues = jsonObj.value(KEY_MATRIX).toArray(); - for (int i=0; i<16; ++i) { - double v = matrixValues.at( i ).toDouble(); - m(i % 4, i >> 2) = v; - } - - // ADD MATRIX TRANSFORM COMPONENT TO ENTITY - QTransform *trans = new QTransform(); - trans->addTransform(new QMatrixTransform(m)); - result->addComponent(trans); - } - - if ( jsonObj.contains(KEY_CAMERA) ) - { - QCameraLens* cam = camera( jsonObj.value(KEY_CAMERA).toString() ); - if (!cam) { - qWarning() << "failed to build camera:" << jsonObj.value(KEY_CAMERA) - << "on node" << id; - } else { - result->addComponent(cam); - } - } // of have camera attribute - - return result; -} - -// Get rid of miniwindef.h clobbering legal variable names -#if defined(near) -#undef near -#endif - -#if defined(far) -#undef far -#endif - -QCameraLens* GLTFParser::camera(const QString &id) -{ - parse(); - QJsonObject cams = m_json.object().value(KEY_CAMERAS).toObject(); - if (!cams.contains(id)) { - qWarning() << "unknown camera" << id << "in GLTF file" << m_basePath; - return Q_NULLPTR; - } - - QJsonObject jsonObj = cams.value(id).toObject(); - QByteArray camTy = jsonObj.value(KEY_TYPE).toString().toUtf8(); - - if (camTy == "perspective") { - if (!jsonObj.contains(KEY_PERSPECTIVE)) { - qWarning() << "camera:" << id << "missing 'perspective' object"; - return Q_NULLPTR; - } - - QJsonObject pObj = jsonObj.value(KEY_PERSPECTIVE).toObject(); - double yfov = pObj.value(KEY_YFOV).toDouble(); - double near = pObj.value(KEY_ZNEAR).toDouble(); - double far = pObj.value(KEY_ZFAR).toDouble(); - - QCameraLens* result = new QCameraLens; - result->setPerspectiveProjection(yfov, 1.0, near, far); - return result; - } else if (camTy == "orthographic") { - qWarning() << Q_FUNC_INFO << "implement me"; - - return Q_NULLPTR; - } else { - qWarning() << "camera:" << id << "has unsupported type:" << camTy; - return Q_NULLPTR; - } -} - -QMaterial* GLTFParser::material(const QString &id) -{ - parse(); - - if (m_materialCache.contains(id)) - return m_materialCache.value(id); - - QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject(); - if (!mats.contains(id)) { - qWarning() << "unknown material" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QJsonObject jsonObj = mats.value(id).toObject(); - - QJsonObject tech = jsonObj.value(KEY_INSTANCE_TECHNIQUE).toObject(); - QString tname = tech.value(KEY_TECHNIQUE).toString(); - if (!m_techniques.contains(tname)) { - qWarning() << "unknown technique" << tname << - "for material" << id << "in GLTF file" << m_basePath; - return NULL; - } - - QTechnique *technique = m_techniques.value(tname); - if (!m_effectProxies.contains(tname)) { - QEffect* eff = new QEffect; - eff->setObjectName(tname); - eff->addTechnique(technique); - m_effectProxies[tname] = eff; - } - - QMaterial* mat = new QMaterial; - mat->setEffect(m_effectProxies[tname]); - - processName(jsonObj, mat); - -// QJsonObject values = tech.value(KEY_VALUES).toObject(); -// foreach (QString vName, values.keys()) { -// QParameter* param = technique->parameterForName(vName); -// if (!param) { -// qWarning() << "unknown parameter:" << vName << "in technique" << tname -// << "processing material" << id; -// continue; -// } - -// if (param->isTextureType()) { -// QString textureId = values.value(vName).toString(); -// if (!m_textures.contains(textureId)) { -// qWarning() << "unknown texture" << textureId << "for parameter" << vName -// << "of material" << id; -// } else { -// mat->setTextureParameter(vName, m_textures.value(textureId)); -// } -// } else { -// // QVariant var = parameterValueFromJSON(param, values.value(vName)); -// mat->addParameter(param); -// } -// } // of material technique-instance values iteration - - m_materialCache[id] = mat; - return mat; -} - -void GLTFParser::parse() -{ - if (m_parseDone) - return; - - QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject(); - foreach (QString nm, buffers.keys()) { - processJSONBuffer( nm, buffers.value(nm).toObject() ); - } - - QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject(); - foreach (QString nm, views.keys()) { - processJSONBufferView( nm, views.value(nm).toObject() ); - } - - QJsonObject shaders = m_json.object().value(KEY_SHADERS).toObject(); - foreach (QString nm, shaders.keys()) { - processJSONShader( nm, shaders.value(nm).toObject() ); - } - - QJsonObject programs = m_json.object().value(KEY_PROGRAMS).toObject(); - foreach (QString nm, programs.keys()) { - processJSONProgram( nm, programs.value(nm).toObject() ); - } - - QJsonObject techniques = m_json.object().value(KEY_TECHNIQUES).toObject(); - foreach (QString nm, techniques.keys()) { - processJSONTechnique( nm, techniques.value(nm).toObject() ); - } - - QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject(); - foreach (QString nm, attrs.keys()) { - processJSONAccessor( nm, attrs.value(nm).toObject() ); - } - - QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject(); - foreach (QString nm, meshes.keys()) { - processJSONMesh( nm, meshes.value(nm).toObject() ); - } - - QJsonObject images = m_json.object().value(KEY_IMAGES).toObject(); - foreach (QString nm, images.keys()) { - processJSONImage( nm, images.value(nm).toObject() ); - } - - QJsonObject textures = m_json.object().value(KEY_TEXTURES).toObject(); - foreach (QString nm, textures.keys()) { - processJSONTexture(nm, textures.value(nm).toObject() ); - } - - m_defaultScene = m_json.object().value(KEY_SCENE).toString(); - m_parseDone = true; -} - -void GLTFParser::processJSONBuffer( QString id, const QJsonObject& json ) -{ - // simply cache buffers for lookup by buffer-views - m_bufferDatas[id] = BufferData(json); -} - -void GLTFParser::processJSONBufferView( QString id, const QJsonObject& json ) -{ - QString bufName = json.value(KEY_BUFFER).toString(); - if (!m_bufferDatas.contains(bufName)) { - qWarning() << "unknown buffer:" << bufName << "processing view:" << id; - return; - } - - int target = json.value(KEY_TARGET).toInt(); - QBuffer::BufferType ty(QBuffer::VertexBuffer); - - switch (target) { - case GL_ARRAY_BUFFER: ty = QBuffer::VertexBuffer; break; - case GL_ELEMENT_ARRAY_BUFFER: ty = QBuffer::IndexBuffer; break; - default: - qWarning() << Q_FUNC_INFO << "buffer" << id << "unsupported target:" << target; - return; - } - - quint64 offset = 0; - if (json.contains(KEY_BYTE_OFFSET)) { - offset = json.value(KEY_BYTE_OFFSET).toInt(); - qCDebug(Render::Io) << "bv:" << id << "has offset:" << offset; - } - - quint64 len = json.value(KEY_BYTE_LENGTH).toInt(); - QFile* f = resolveLocalData(m_bufferDatas[bufName].path); - if (!f->seek(offset)) { - qWarning() << "failed to seek to offset in file for bufferView:" << id << offset; - } - - QByteArray bytes = f->read(len); - if (bytes.count() != (int) len) { - qWarning() << "failed to read sufficient bytes from:" << m_bufferDatas[bufName].path - << "for view" << id; - } - delete f; - - QBuffer *b(new QBuffer(ty)); - b->setData(bytes); - m_buffers[id] = b; -} - -void GLTFParser::processJSONAccessor( QString id, const QJsonObject& json ) -{ - QString bvName = json.value(KEY_BUFFER_VIEW).toString(); - if (!m_buffers.contains(bvName)) { - qWarning() << "unknown buffer-view:" << bvName << "processing accessor:" << id; - return; - } - - QBuffer *buf = m_buffers.value(bvName); - int offset = 0, stride = 0; - int type = json.value(KEY_TYPE).toInt(); - int count = json.value(KEY_COUNT).toInt(); - - if ( json.contains(KEY_BYTE_OFFSET)) - offset = json.value(KEY_BYTE_OFFSET).toInt(); - if ( json.contains(KEY_BYTE_STRIDE)) - stride = json.value(KEY_BYTE_STRIDE).toInt(); - - uint dataSize = 0; - QAttribute::DataType dataType = typeFromGLType(type, dataSize); - - QAttribute *attr( new QAttribute( buf, dataType, dataSize, count, offset, stride ) ); - m_attributeDict[id] = attr; -} - -void GLTFParser::processJSONMesh( QString id, QJsonObject jsonObj ) -{ - QJsonArray primsArray = jsonObj.value(KEY_PRIMITIVES).toArray(); - Q_FOREACH (QJsonValue primVal, primsArray) { - QJsonObject primObj = primVal.toObject(); - int type = primObj.value(KEY_PRIMITIVE).toInt(); - QString material = primObj.value(KEY_MATERIAL).toString(); - - if ( material.isEmpty()) { - qCWarning(Render::Io) << "malformed primitive on " << id << ", missing material value" - << material; - continue; - } - - QMeshDataPtr md(new QMeshData(static_cast<QMeshData::PrimitiveType>(type))); - m_meshMaterialDict[md.data()] = material; - - QJsonObject attrs = primObj.value(KEY_ATTRIBUTES).toObject(); - Q_FOREACH (QString attrName, attrs.keys()) { - QString k = attrs.value(attrName).toString(); - if (!m_attributeDict.contains(k)) { - qCWarning(Render::Io) << "unknown attribute accessor:" << k << "on mesh" << id; - continue; - } - - md->addAttribute(attrName, m_attributeDict[k]); - - // qCDebug(Render::rIo) << "DUMP of:" << attrName; - // m_attributeDict[k]->dump(20); - } - - if ( primObj.contains(KEY_INDICES)) { - QString k = primObj.value(KEY_INDICES).toString(); - if (!m_attributeDict.contains(k)) { - qCWarning(Render::Io) << "unknown index accessor:" << k << "on mesh" << id; - } else { - md->setIndexAttribute(m_attributeDict[k]); - // m_attributeDict[k]->dump(100); - } - } // of has indices - - m_meshDict.insert( id, md ); - } // of primitives iteration -} - -void GLTFParser::processName(const QJsonObject &json, QObject *ins) -{ - if ( json.contains(KEY_NAME) ) - { - ins->setObjectName( json.value(KEY_NAME).toString() ); - } -} - -void GLTFParser::processJSONProgram( QString id, QJsonObject jsonObj) -{ - QShaderProgram* prog = new QShaderProgram; - prog->setObjectName(id); - - QString fragName = jsonObj.value(KEY_FRAGMENT_SHADER).toString(), - vertName = jsonObj.value(KEY_VERTEX_SHADER).toString(); - if (!m_shaderPaths.contains(fragName) || !m_shaderPaths.contains(vertName)) { - qCWarning(Render::Io) << Q_FUNC_INFO << "program:" << id << "missing shader:" << - fragName << vertName; - return; - } - - prog->setFragmentShaderCode(Qt3D::QShaderProgram::loadSource(QUrl(m_shaderPaths[fragName]))); - prog->setVertexShaderCode(Qt3D::QShaderProgram::loadSource(QUrl(m_shaderPaths[vertName]))); - m_programs[id] = prog; -} - -void GLTFParser::processJSONShader( QString id, QJsonObject jsonObj) -{ - // shaders are trivial for the moment, defer the real work - // to the program section - QString path = jsonObj.value(KEY_PATH).toString(); - - QFileInfo info(m_basePath, path); - if (!info.exists()) { - qCWarning(Render::Io) << "can't find shader" << id << "from path" << path; - return; - } - - m_shaderPaths[id] = info.absoluteFilePath(); -} - -void GLTFParser::processJSONImage( QString id, QJsonObject jsonObj) -{ - QString path = jsonObj.value(KEY_PATH).toString(); - QFileInfo info(m_basePath, path); - if (!info.exists()) { - qCWarning(Render::Io)<< "can't find image" << id << "from path" << path; - return; - } - - QImage img(info.absoluteFilePath()); - if (img.isNull()) { - qCWarning(Render::Io) << "failed to load image:" << info.absoluteFilePath(); - return; - } - - m_images[id] = img; -} - -void GLTFParser::processJSONTexture( QString id, QJsonObject jsonObj) -{ - Q_UNUSED(id); - Q_UNUSED(jsonObj); -// int target = jsonObj.value(KEY_TARGET).toInt(); -// QAbstractTextureProvider* tex = new QAbstractTextureProvider(static_cast<QAbstractTextureProvider::Target>(target)); - - -// // TODO: Choose suitable internal format - may vary on OpenGL context type -// //int pixelFormat = jsonObj.value(KEY_FORMAT).toInt(); -// //int internalFormat = jsonObj.value(KEY_INTERNAL_FORMAT).toInt(); - -// tex->setFormat(QAbstractTextureProvider::RGBA8_UNorm /* static_cast<QOpenGLTexture::TextureFormat>(internalFormat)*/); - -// QString samplerId = jsonObj.value(KEY_SAMPLER).toString(); -// QString source = jsonObj.value(KEY_SOURCE).toString(); -// if (!m_images.contains(source)) { -// qCWarning(Render::Io) << "texture" << id << "references missing image" << source; -// return; -// } - -// tex->setFromQImage(m_images[source]); - -// QJsonObject samplersDict(m_json.object().value(KEY_SAMPLERS).toObject()); -// if (!samplersDict.contains(samplerId)) { -// qCWarning(Render::Io) << "texture" << id << "references unknown sampler" << samplerId; -// return; -// } - -// QJsonObject sampler = samplersDict.value(samplerId).toObject(); - -// tex->setWrapMode(QTextureWrapMode(static_cast<QTextureWrapMode::WrapMode>(sampler.value(KEY_WRAP_S).toInt()))); -// tex->setMinificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MIN_FILTER).toInt())); -// tex->setMagnificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MAG_FILTER).toInt())); - -// m_textures[id] = tex; -} - -void GLTFParser::processJSONTechnique( QString id, QJsonObject jsonObj ) -{ - QTechnique *t = new QTechnique; - t->setObjectName(id); - - QHash<QString, QParameter*> paramDict; - QJsonObject params = jsonObj.value(KEY_PARAMETERS).toObject(); - Q_FOREACH (QString pname, params.keys()) { - QJsonObject po = params.value(pname).toObject(); - - // int dataType = po.value(KEY_TYPE).toInt(); - QString semantic = po.value(KEY_SEMANTIC).toString(); - // The Standard has changed, it doesn't return the raw int value for a type - // But a string -// QParameter* p = new QParameter(pname, parseType(po.value(KEY_TYPE).toString().toUtf8()), t); -// Parameter::StandardUniform su = parseSemanticName(semantic.toUtf8()); -// if (su != Parameter::None) { -// p->setStandardUniform(su); -// } else { -// // should really verify it's an attribute parameter? -// // but what would be the way to do that? -// // check the accessor dict? -// p->setMeshAttributeName(semantic); -// } - -// t->addParameter(p); - -// paramDict[pname] = p; - } // of parameters iteration - - QJsonObject passes = jsonObj.value(KEY_PASSES).toObject(); - Q_FOREACH (QString pname, passes.keys()) { - QJsonObject po = passes.value(pname).toObject(); - QJsonObject ip = po.value(KEY_INSTANCE_PROGRAM).toObject(); - - QString programName = ip.value(KEY_PROGRAM).toString(); - if (!m_programs.contains(programName)) { - qWarning() << Q_FUNC_INFO << "technique" << id << "pass" << pname - << ": missing program" << programName; - continue; - } - - QRenderPass* pass = new QRenderPass; - pass->setShaderProgram(m_programs[programName]); - - QJsonObject attrs = ip.value(KEY_ATTRIBUTES).toObject(); - Q_FOREACH ( QString attrName, attrs.keys() ) { - QString pname = attrs.value(attrName).toString(); - // TO DO : Correct that - // pass->addAttributeBinding(paramDict[pname], attrName); - } // of program-instance attributes - - QJsonObject uniforms = ip.value(KEY_UNIFORMS).toObject(); - Q_FOREACH (QString uniformName, uniforms.keys()) { - QString pname = uniforms.value(uniformName).toString(); - // TO DO : Correct that - // pass->addUniformBinding(paramDict[pname], uniformName); - } // of program-instance attributes - - // TODO: Use public state api only here -// QJsonObject states = po.value(KEY_STATES).toObject(); -// Render::RenderStateSet* ss = new Render::RenderStateSet; - -// Q_FOREACH (QString stateName, states.keys()) { -// Render::RenderState* s= buildState(stateName.toUtf8(), states.value(stateName)); -// if (!s) -// continue; - -// ss->addState(s); -// } // of program-instance attributes - -// pass->setStateSet(ss); - t->addPass(pass); - } // of passes iteration - - m_techniques[id] = t; -} - -//Render::RenderState* GLTFParser::buildState(const QByteArray& nm, QJsonValue v) -//{ -// if (nm == "blendEnable") { -// return NULL; // will see a blendEquation spec too -// } - -// if (nm == "blendFunc") { -// QJsonObject obj = v.toObject(); -// GLenum srcF = static_cast<GLenum>(obj.value(QStringLiteral("sfactor")).toInt()); -// GLenum dstF = static_cast<GLenum>(obj.value(QStringLiteral("dfactor")).toInt()); -// return Render::BlendState::getOrCreate(srcF, dstF); -// } - -// if (nm == "blendEquation") { -// return Render::BlendEquation::getOrCreate(static_cast<GLenum>(v.toInt())); -// } - -// if (nm == "cullFaceEnable" && v.toInt()) { -// return Render::CullFace::getOrCreate(GL_BACK); -// } - -// if (nm == "depthTestEnable" && v.toInt()) { -// return Render::DepthTest::getOrCreate(GL_LESS); -// } - -// if (nm == "depthMask") { -// return Render::DepthMask::getOrCreate(v.toInt() ? GL_TRUE : GL_FALSE); -// } - -// qCWarning(Render::Io) << Q_FUNC_INFO << "unsupported gltf state:" << nm; -// return NULL; -//} - -QFile *GLTFParser::resolveLocalData(QString path) -{ - QDir d(m_basePath); - Q_ASSERT(d.exists()); - - QString absPath = d.absoluteFilePath(path); - QFile* f = new QFile(absPath); - f->open(QIODevice::ReadOnly); - return f; -} - -GLTFParser::BufferData::BufferData() : - length(0) -{ -} - -GLTFParser::BufferData::BufferData(QJsonObject json) -{ - path = json.value(KEY_PATH).toString(); - length = json.value(KEY_LENGTH).toInt(); - // url -} - -QVariant GLTFParser::parameterValueFromJSON(QParameter* p, QJsonValue val) -{ - Q_UNUSED(p); - Q_UNUSED(val); -// switch (p->datatype()) { -// case QParameter::Bool: -// return val.toBool(); - -// case QParameter::Float: -// return val.toDouble(); - -// case QParameter::FloatVec2: { -// QJsonArray a = val.toArray(); -// return QVector2D(a[0].toDouble(), a[1].toDouble()); -// } - -// case QParameter::FloatVec3: { -// QJsonArray a = val.toArray(); -// return QVector3D(a[0].toDouble(), a[1].toDouble(), a[3].toDouble()); -// } - -// case QParameter::FloatVec4: { -// QJsonArray a = val.toArray(); -// return QVector4D(a[0].toDouble(), -// a[1].toDouble(), -// a[2].toDouble(), -// a[3].toDouble()); -// } - -// case QParameter::FloatMat4: { -// QJsonArray a = val.toArray(); - -// QMatrix4x4 m(Qt::Uninitialized); -// for (int i=0; i<16; ++i) { -// m(i % 4, i / 4) = a[i].toDouble(); -// } -// return m; -// } - -// default: -// qCWarning(Render::Io) << Q_FUNC_INFO << "unhandled type:" << QString::number(p->datatype(), 16); -// } - - return QVariant(); -} - -void GLTFParserMesh::copy(const QNode *ref) -{ - QAbstractMesh::copy(ref); - const GLTFParserMesh *gltfMesh = static_cast<const GLTFParserMesh*>(ref); - d_func()->m_meshData = gltfMesh->d_func()->m_meshData; -} - -GLTFParserMesh::GLTFParserMesh(QNode *parent) - : QAbstractMesh(*new GLTFParserMeshPrivate, parent) -{ -} - - -void GLTFParserMesh::setData(QMeshDataPtr data) -{ - Q_D(GLTFParserMesh); - d->m_meshData = data; - QAbstractMesh::update(); -} - -QAbstractMeshFunctorPtr GLTFParserMesh::meshFunctor() const -{ - Q_D(const GLTFParserMesh); - return QAbstractMeshFunctorPtr(new GLTFParserMeshFunctor(d->m_meshData)); -} - -GLTFParserMeshFunctor::GLTFParserMeshFunctor(QMeshDataPtr meshData) - : QAbstractMeshFunctor() - , m_meshData(meshData) -{ -} - -QMeshDataPtr GLTFParserMeshFunctor::operator ()() -{ - return m_meshData; -} - -bool GLTFParserMeshFunctor::operator ==(const QAbstractMeshFunctor &) const -{ - return false; -} - -} // namespace Qt3D - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(Qt3D::GLTFParserMeshFunctor) - -#include "gltfparser.moc" diff --git a/src/render/io/render-io.pri b/src/render/io/render-io.pri index c96e4617e..6ac63d9c5 100644 --- a/src/render/io/render-io.pri +++ b/src/render/io/render-io.pri @@ -1,7 +1,6 @@ INCLUDEPATH += $$PWD HEADERS += \ - $$PWD/gltfparser_p.h \ $$PWD/objloader_p.h \ $$PWD/texturedata.h \ $$PWD/abstractsceneparser_p.h \ @@ -16,7 +15,6 @@ HEADERS += \ $$PWD/qgeometryfunctor.h SOURCES += \ - $$PWD/gltfparser.cpp \ $$PWD/objloader.cpp \ $$PWD/texturedata.cpp \ $$PWD/abstractsceneparser.cpp \ |