diff options
Diffstat (limited to 'tests/auto')
108 files changed, 13827 insertions, 641 deletions
diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index 421ecfdd5..1226f9498 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -13,7 +13,10 @@ SUBDIRS += \ qkeyframeanimation \ qmorphinganimation \ qmorphtarget \ - qvertexblendanimation + qvertexblendanimation \ + qclock \ + qskeletonmapping \ + qcallbackmapping qtConfig(private_tests) { SUBDIRS += \ @@ -35,5 +38,7 @@ qtConfig(private_tests) { clipblendvalue \ animationutils \ qabstractanimation \ + clock \ + skeleton \ findrunningclipanimatorsjob } diff --git a/tests/auto/animation/animationutils/animationutils.qrc b/tests/auto/animation/animationutils/animationutils.qrc index ddaeab7f1..0b499ed76 100644 --- a/tests/auto/animation/animationutils/animationutils.qrc +++ b/tests/auto/animation/animationutils/animationutils.qrc @@ -4,5 +4,6 @@ <file>clip2.json</file> <file>clip3.json</file> <file>clip4.json</file> + <file>clip5.json</file> </qresource> </RCC> diff --git a/tests/auto/animation/animationutils/clip5.json b/tests/auto/animation/animationutils/clip5.json new file mode 100644 index 000000000..50a848f03 --- /dev/null +++ b/tests/auto/animation/animationutils/clip5.json @@ -0,0 +1,1401 @@ +{ + "animations": [ + { + "animationName": "SkeletonAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 3 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 3 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 3 + } + ] + } + ] +} diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 36e954a85..5ec8c7d60 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -30,6 +30,7 @@ #include <Qt3DAnimation/private/animationclip_p.h> #include <Qt3DAnimation/private/animationutils_p.h> #include <Qt3DAnimation/private/blendedclipanimator_p.h> +#include <Qt3DAnimation/private/clock_p.h> #include <Qt3DAnimation/private/channelmapper_p.h> #include <Qt3DAnimation/private/channelmapping_p.h> #include <Qt3DAnimation/private/clipblendvalue_p.h> @@ -51,6 +52,7 @@ using namespace Qt3DAnimation::Animation; Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) Q_DECLARE_METATYPE(QVector<ChannelMapping *>) +Q_DECLARE_METATYPE(Clock *) Q_DECLARE_METATYPE(ChannelMapper *) Q_DECLARE_METATYPE(AnimationClip *) Q_DECLARE_METATYPE(QVector<MappingData>) @@ -61,6 +63,7 @@ Q_DECLARE_METATYPE(ClipEvaluationData) Q_DECLARE_METATYPE(ClipAnimator *) Q_DECLARE_METATYPE(BlendedClipAnimator *) Q_DECLARE_METATYPE(QVector<ChannelNameAndType>) +Q_DECLARE_METATYPE(QVector<AnimationCallbackAndValue>) namespace { @@ -122,6 +125,12 @@ bool fuzzyCompare(float x1, float x2) } } +class DummyCallback : public Qt3DAnimation::QAnimationCallback +{ +public: + void valueChanged(const QVariant &) override { } +}; + } // anonymous @@ -140,11 +149,25 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setTargetId(targetId); channelMapping->setProperty(property); channelMapping->setPropertyName(propertyName); channelMapping->setChannelName(channelName); channelMapping->setType(type); + channelMapping->setMappingType(ChannelMapping::ChannelMappingType); + return channelMapping; + } + + ChannelMapping *createChannelMapping(Handler *handler, + const Qt3DCore::QNodeId skeletonId) + { + auto channelMappingId = Qt3DCore::QNodeId::createId(); + ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); + setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); + channelMapping->setSkeletonId(skeletonId); + channelMapping->setMappingType(ChannelMapping::SkeletonMappingType); return channelMapping; } @@ -238,9 +261,19 @@ public: return node; } + Skeleton *createSkeleton(Handler *handler, int jointCount) + { + auto skeletonId = Qt3DCore::QNodeId::createId(); + Skeleton *skeleton = handler->skeletonManager()->getOrCreateResource(skeletonId); + setPeerId(skeleton, skeletonId); + skeleton->setJointCount(jointCount); + return skeleton; + } + private Q_SLOTS: void checkBuildPropertyMappings_data() { + QTest::addColumn<Handler *>("handler"); QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); @@ -248,12 +281,14 @@ private Q_SLOTS: // Single ChannelMapping { - auto channelMapping = new ChannelMapping(); - channelMapping->setChannelName("Location"); - channelMapping->setTargetId(Qt3DCore::QNodeId::createId()); - channelMapping->setProperty(QLatin1String("translation")); - channelMapping->setPropertyName("translation"); - channelMapping->setType(static_cast<int>(QVariant::Vector3D)); + Handler *handler = new Handler(); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); QVector<ChannelMapping *> channelMappings = { channelMapping }; @@ -289,6 +324,7 @@ private Q_SLOTS: QVector<MappingData> expectedResults = { expectedMapping }; QTest::newRow("single mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -297,40 +333,42 @@ private Q_SLOTS: // Multiple ChannelMappings { - auto locationMapping = new ChannelMapping(); - locationMapping->setChannelName("Location"); - locationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - locationMapping->setProperty(QLatin1String("translation")); - locationMapping->setPropertyName("translation"); - locationMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto metalnessMapping = new ChannelMapping(); - metalnessMapping->setChannelName("Metalness"); - metalnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - metalnessMapping->setProperty(QLatin1String("metalness")); - metalnessMapping->setPropertyName("metalness"); - metalnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto baseColorMapping = new ChannelMapping(); - baseColorMapping->setChannelName("BaseColor"); - baseColorMapping->setTargetId(Qt3DCore::QNodeId::createId()); - baseColorMapping->setProperty(QLatin1String("baseColor")); - baseColorMapping->setPropertyName("baseColor"); - baseColorMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto roughnessMapping = new ChannelMapping(); - roughnessMapping->setChannelName("Roughness"); - roughnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - roughnessMapping->setProperty(QLatin1String("roughness")); - roughnessMapping->setPropertyName("roughness"); - roughnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto rotationMapping = new ChannelMapping(); - rotationMapping->setChannelName("Rotation"); - rotationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - rotationMapping->setProperty(QLatin1String("rotation")); - rotationMapping->setPropertyName("rotation"); - rotationMapping->setType(static_cast<int>(QVariant::Quaternion)); + Handler *handler = new Handler(); + + auto locationMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + + auto metalnessMapping = createChannelMapping(handler, + QLatin1String("Metalness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("metalness"), + "metalness", + static_cast<int>(QVariant::Double)); + + auto baseColorMapping = createChannelMapping(handler, + QLatin1String("BaseColor"), + Qt3DCore::QNodeId::createId(), + QLatin1String("baseColor"), + "baseColor", + static_cast<int>(QVariant::Vector3D)); + + auto roughnessMapping = createChannelMapping(handler, + QLatin1String("Roughness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("roughness"), + "roughness", + static_cast<int>(QVariant::Double)); + + auto rotationMapping = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotation"), + "rotation", + static_cast<int>(QVariant::Quaternion)); QVector<ChannelMapping *> channelMappings = { locationMapping, metalnessMapping, @@ -399,6 +437,77 @@ private Q_SLOTS: expectedRotationMapping }; QTest::newRow("multiple mappings") + << handler + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + + // Single skeleton mapping + { + Handler *handler = new Handler(); + const int jointCount = 4; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + + QVector<ChannelMapping *> channelMappings = { channelMapping }; + + // Create a few channels in the format description + QVector<ChannelNameAndType> channelNamesAndTypes; + for (int i = 0; i < jointCount; ++i) { + channelNamesAndTypes.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + channelNamesAndTypes.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + channelNamesAndTypes.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + // And the matching indices + QVector<ComponentIndices> channelComponentIndices; + channelComponentIndices.push_back({ 0, 1, 2 }); + channelComponentIndices.push_back({ 3, 4, 5, 6 }); + channelComponentIndices.push_back({ 7, 8, 9 }); + + channelComponentIndices.push_back({ 10, 11, 12 }); + channelComponentIndices.push_back({ 13, 14, 15, 16 }); + channelComponentIndices.push_back({ 17, 18, 19 }); + + channelComponentIndices.push_back({ 20, 21, 22 }); + channelComponentIndices.push_back({ 23, 24, 25, 26 }); + channelComponentIndices.push_back({ 27, 28, 29 }); + + channelComponentIndices.push_back({ 30, 31, 32 }); + channelComponentIndices.push_back({ 33, 34, 35, 36 }); + channelComponentIndices.push_back({ 37, 38, 39 }); + + QVector<MappingData> expectedResults; + int componentIndicesIndex = 0; + for (int i = 0; i < jointCount; ++i) { + MappingData locationMapping; + locationMapping.targetId = channelMapping->skeletonId(); + locationMapping.propertyName = "translation"; + locationMapping.type = static_cast<int>(QVariant::Vector3D); + locationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + locationMapping.jointIndex = i; + + MappingData rotationMapping; + rotationMapping.targetId = channelMapping->skeletonId(); + rotationMapping.propertyName = "rotation"; + rotationMapping.type = static_cast<int>(QVariant::Quaternion); + rotationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + rotationMapping.jointIndex = i; + + MappingData scaleMapping; + scaleMapping.targetId = channelMapping->skeletonId(); + scaleMapping.propertyName = "scale"; + scaleMapping.type = static_cast<int>(QVariant::Vector3D); + scaleMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + scaleMapping.jointIndex = i; + + expectedResults << locationMapping << rotationMapping << scaleMapping; + } + + QTest::newRow("single skeleton mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -409,6 +518,7 @@ private Q_SLOTS: void checkBuildPropertyMappings() { // GIVEN + QFETCH(Handler *, handler); QFETCH(QVector<ChannelMapping *>, channelMappings); QFETCH(QVector<ChannelNameAndType>, channelNamesAndTypes); QFETCH(QVector<ComponentIndices>, channelComponentIndices); @@ -426,6 +536,7 @@ private Q_SLOTS: const auto expectedMapping = expectedResults[i]; QCOMPARE(actualMapping.targetId, expectedMapping.targetId); + QCOMPARE(actualMapping.jointIndex, expectedMapping.jointIndex); QCOMPARE(actualMapping.propertyName, expectedMapping.propertyName); QCOMPARE(actualMapping.type, expectedMapping.type); QCOMPARE(actualMapping.channelIndices.size(), expectedMapping.channelIndices.size()); @@ -433,338 +544,142 @@ private Q_SLOTS: QCOMPARE(actualMapping.channelIndices[j], expectedMapping.channelIndices[j]); } } + + // Cleanup + delete handler; } - void checkLocalTimeFromGlobalTime_data() + void checkLocalTimeFromElapsedTime_data() { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("elapsedTime"); + QTest::addColumn<double>("currentTime"); QTest::addColumn<double>("playbackRate"); QTest::addColumn<double>("duration"); QTest::addColumn<int>("loopCount"); + QTest::addColumn<int>("currentLoop"); QTest::addColumn<double>("expectedLocalTime"); QTest::addColumn<int>("expectedCurrentLoop"); - double globalTime; - double globalStartTime; + double elapsedTime; + double currentTime; double playbackRate; double duration; int loopCount; + int currentLoop; double expectedLocalTime; int expectedCurrentLoop; - globalTime = 0.0; - globalStartTime = 0.0; + elapsedTime = 0.0; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.5; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.0; - globalStartTime = 0.0; + elapsedTime = 1.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedLocalTime = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 1.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 2; - expectedLocalTime = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedLocalTime = 0.5; + currentLoop = 0; + expectedLocalTime = 0.1; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 3.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedLocalTime = 1.5; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; + duration = 1.0; loopCount = 2; - expectedLocalTime = 2.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + currentLoop = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 1; // We clamp at end of final loop + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; + elapsedTime = 0.5; + currentTime = 0.6; + playbackRate = 0.1; duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.5; + loopCount = 2; + currentLoop = 1; + expectedLocalTime = 0.65; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; } - void checkLocalTimeFromGlobalTime() + void checkLocalTimeFromElapsedTime() { // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); + QFETCH(double, elapsedTime); + QFETCH(double, currentTime); QFETCH(double, playbackRate); QFETCH(double, duration); QFETCH(int, loopCount); + QFETCH(int, currentLoop); QFETCH(double, expectedLocalTime); QFETCH(int, expectedCurrentLoop); // WHEN - int actualCurrentLoop = 0; - double actualLocalTime = localTimeFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); + int actualCurrentLoop = currentLoop; + double actualLocalTime = localTimeFromElapsedTime(currentTime, + elapsedTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); // THEN QCOMPARE(actualCurrentLoop, expectedCurrentLoop); QCOMPARE(actualLocalTime, expectedLocalTime); } - void checkPhaseFromGlobalTime_data() - { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); - QTest::addColumn<double>("playbackRate"); - QTest::addColumn<double>("duration"); - QTest::addColumn<int>("loopCount"); - QTest::addColumn<double>("expectedPhase"); - QTest::addColumn<int>("expectedCurrentLoop"); - - double globalTime; - double globalStartTime; - double playbackRate; - double duration; - int loopCount; - double expectedPhase; - int expectedCurrentLoop; - - globalTime = 0.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 3.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 0.75; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 1.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - } - - void checkPhaseFromGlobalTime() - { - // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); - QFETCH(double, playbackRate); - QFETCH(double, duration); - QFETCH(int, loopCount); - QFETCH(double, expectedPhase); - QFETCH(int, expectedCurrentLoop); - - // WHEN - int actualCurrentLoop = 0; - double actualPhase = phaseFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); - - // THEN - QCOMPARE(actualCurrentLoop, expectedCurrentLoop); - QCOMPARE(actualPhase, expectedPhase); - } - void checkPreparePropertyChanges_data() { QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); @@ -1034,6 +949,117 @@ private Q_SLOTS: } } + void checkPrepareCallbacks_data() + { + QTest::addColumn<QVector<MappingData>>("mappingData"); + QTest::addColumn<QVector<float>>("channelResults"); + QTest::addColumn<QVector<AnimationCallbackAndValue> >("expectedValues"); + + QVector<MappingData> mappingData; + QVector<float> channelResults; + QVector<AnimationCallbackAndValue> expectedValues; + + // vec3 + { + DummyCallback callback; // safe since the object is never used, just the address + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "translation"; + mapping.type = static_cast<int>(QVariant::Vector3D); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2; + mapping.callback = &callback; + mapping.callbackFlags = 0; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant::fromValue<QVector3D>(QVector3D(1.0f, 2.0f, 3.0f)); + expectedValues.push_back(cbv); + + QTest::newRow("vec3 translation, no flags") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + + // double + { + DummyCallback callback; + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "something"; + mapping.type = static_cast<int>(QVariant::Double); + mapping.channelIndices = QVector<int>() << 0; + mapping.callback = &callback; + mapping.callbackFlags = 0; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant(double(1.0)); + expectedValues.push_back(cbv); + + QTest::newRow("double, no flags") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + + // float, set a flag + { + DummyCallback callback; + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "opacity"; + mapping.type = static_cast<int>(QMetaType::Float); + mapping.channelIndices = QVector<int>() << 0; + mapping.callback = &callback; + mapping.callbackFlags = Qt3DAnimation::QAnimationCallback::OnThreadPool; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 0.5f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant(float(0.5f)); + expectedValues.push_back(cbv); + + QTest::newRow("float, OnThreadPool") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + } + + void checkPrepareCallbacks() + { + // GIVEN + QFETCH(QVector<MappingData>, mappingData); + QFETCH(QVector<float>, channelResults); + QFETCH(QVector<AnimationCallbackAndValue>, expectedValues); + + // WHEN + QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(mappingData, channelResults); + + // THEN + QCOMPARE(callbacks.size(), expectedValues.size()); + for (int i = 0; i < callbacks.size(); ++i) { + auto expected = expectedValues[i]; + auto actual = callbacks[i]; + + QCOMPARE(actual.callback, expected.callback); + QCOMPARE(actual.flags, expected.flags); + QCOMPARE(actual.value, expected.value); + } + } + void checkEvaluateClipAtLocalTime_data() { QTest::addColumn<Handler *>("handler"); @@ -1284,6 +1310,31 @@ private Q_SLOTS: QVector<char> suffixes; QVector<int> expectedResults; + // already sorted vec3, no component names, with and without offset + { + channel = Channel(); + channel.name = QLatin1String("Location"); + channel.channelComponents.resize(3); + // leave 'name' empty + + dataType = static_cast<int>(QVariant::Vector3D); + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector<int>() << 0 << 1 << 2); + + QTest::newRow("vec3 location, pre-sorted, no component names, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 4; + expectedResults = (QVector<int>() << 4 << 5 << 6); + QTest::newRow("vec3 location, pre-sorted, no component names, offset = 4") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + } + // vec3 with and without offset { channel = Channel(); @@ -1622,6 +1673,7 @@ private Q_SLOTS: AnimationClip *clip; AnimatorEvaluationData animatorData; ClipEvaluationData clipData; + auto* clock = new Clock; { handler = new Handler(); @@ -1629,11 +1681,13 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 0; - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 0; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, @@ -1650,18 +1704,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration()+1)*1e09; // +1 to ensure beyond end + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = duration") + QTest::newRow("clip1.json, elapsedTime = duration + 1") << handler << clip << animatorData << clipData; } @@ -1671,18 +1727,43 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 0; // Infinite loops auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 2.0 * clip->duration() * 1.0e9; - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 2.0 * clip->duration() * 1.0e9; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = false; - QTest::newRow("clip1.json, globalTime = 2 * duration, loops = infinite") + QTest::newRow("clip1.json, elapsedTime = 2 * duration, loops = infinite") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 2; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, elapsedTime = 2 * duration + 1, loops = 2") << handler << clip << animatorData << clipData; } @@ -1692,18 +1773,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 2; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(1); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = 2 * duration + 1, loops = 2") + QTest::newRow("clip1.json, elapsedTime = duration + 1, loops = 2, current_loop = 1") << handler << clip << animatorData << clipData; } } @@ -1732,12 +1815,12 @@ private Q_SLOTS: { QTest::addColumn<Handler *>("handler"); QTest::addColumn<ClipAnimator *>("animator"); - QTest::addColumn<qint64>("globalTimeNS"); + QTest::addColumn<qint64>("elapsedTime"); QTest::addColumn<AnimatorEvaluationData>("expectedAnimatorData"); Handler *handler; ClipAnimator *animator; - qint64 globalTimeNS; + qint64 elapsedTimeNS; AnimatorEvaluationData expectedAnimatorData; { @@ -1745,15 +1828,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1761,15 +1843,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 5; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 5") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 5") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1777,15 +1858,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 5000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 5.0; - QTest::newRow("globalStartTime = 0, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 5, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1793,15 +1873,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 3000000000; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 2000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 3.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 2.0; - QTest::newRow("globalStartTime = 3, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 3, elapsedTime = 2, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } } @@ -1810,17 +1889,16 @@ private Q_SLOTS: // GIVEN QFETCH(Handler *, handler); QFETCH(ClipAnimator *, animator); - QFETCH(qint64, globalTimeNS); + QFETCH(qint64, elapsedTime); QFETCH(AnimatorEvaluationData, expectedAnimatorData); // WHEN - AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, globalTimeNS); + AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, elapsedTime); // THEN QCOMPARE(actualAnimatorData.loopCount, expectedAnimatorData.loopCount); QVERIFY(fuzzyCompare(actualAnimatorData.playbackRate, expectedAnimatorData.playbackRate) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.startTime, expectedAnimatorData.startTime) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.globalTime, expectedAnimatorData.globalTime) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.elapsedTime, expectedAnimatorData.elapsedTime) == true); // Cleanup delete handler; @@ -2304,6 +2382,27 @@ private Q_SLOTS: QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults; } + + { + auto handler = new Handler(); + const int jointCount = 10; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + auto channelMapper = createChannelMapper(handler, + QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + + QVector<ChannelNameAndType> expectedResults; + for (int i = 0; i < jointCount; ++i) { + expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + expectedResults.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QTest::addRow("Skeleton, 10 joints") << handler << channelMapper << expectedResults; + } } void checkBuildRequiredChannelsAndTypes() @@ -2369,6 +2468,35 @@ private Q_SLOTS: QTest::newRow("vec3 location, quaterion rotation, pbr metal-rough") << allChannels << expectedResults; } + + { + QVector<ChannelNameAndType> allChannels; + const int jointCount = 4; + for (int i = 0; i < jointCount; ++i) { + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + allChannels.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QVector<ComponentIndices> expectedResults; + expectedResults.push_back({ 0, 1, 2 }); + expectedResults.push_back({ 3, 4, 5, 6 }); + expectedResults.push_back({ 7, 8, 9 }); + + expectedResults.push_back({ 10, 11, 12 }); + expectedResults.push_back({ 13, 14, 15, 16 }); + expectedResults.push_back({ 17, 18, 19 }); + + expectedResults.push_back({ 20, 21, 22 }); + expectedResults.push_back({ 23, 24, 25, 26 }); + expectedResults.push_back({ 27, 28, 29 }); + + expectedResults.push_back({ 30, 31, 32 }); + expectedResults.push_back({ 33, 34, 35, 36 }); + expectedResults.push_back({ 37, 38, 39 }); + + QTest::newRow("skeleton, 4 joints") << allChannels << expectedResults; + } } void checkAssignChannelComponentIndices() @@ -2517,6 +2645,54 @@ private Q_SLOTS: QTest::newRow("location, rotation, albedo (missing), metal-rough") << targetChannels << targetIndices << clip << expectedResults; } + + { + QVector<ChannelNameAndType> targetChannels; + const int jointCount = 4; + for (int i = 0; i < jointCount; ++i) { + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + targetChannels.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2 }); + targetIndices.push_back({ 3, 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + + targetIndices.push_back({ 10, 11, 12 }); + targetIndices.push_back({ 13, 14, 15, 16 }); + targetIndices.push_back({ 17, 18, 19 }); + + targetIndices.push_back({ 20, 21, 22 }); + targetIndices.push_back({ 23, 24, 25, 26 }); + targetIndices.push_back({ 27, 28, 29 }); + + targetIndices.push_back({ 30, 31, 32 }); + targetIndices.push_back({ 33, 34, 35, 36 }); + targetIndices.push_back({ 37, 38, 39 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip5.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 4, 6, 5, // Location, joint 0 (y/z swapped in clip5.json) + 0, 1, 3, 2, // Rotation, joint 0 (y/z swapped in clip5.json) + 7, 8, 9, // Scale, joint 0 + 14, 16, 15, // Location, joint 1 (y/z swapped in clip5.json) + 10, 11, 13, 12, // Rotation, joint 1 (y/z swapped in clip5.json) + 17, 18, 19, // Scale, joint 1 + 24, 26, 25, // Location, joint 2 (y/z swapped in clip5.json) + 20, 21, 23, 22, // Rotation, joint 2 (y/z swapped in clip5.json) + 27, 28, 29, // Scale, joint 2 + 34, 36, 35, // Location, joint 3 (y/z swapped in clip5.json) + 30, 31, 33, 32, // Rotation, joint 3 (y/z swapped in clip5.json) + 37, 38, 39 }; // Scale, joint 3 + + QTest::newRow("skeleton (SQT), 4 joints") + << targetChannels << targetIndices << clip << expectedResults; + } } void checkGenerateClipFormatIndices() diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index 3265de167..c0e1581f9 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -63,7 +63,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); @@ -82,6 +83,7 @@ private Q_SLOTS: backendBlendedClipAnimator.setMapperId(Qt3DCore::QNodeId::createId()); backendBlendedClipAnimator.setRunning(true); backendBlendedClipAnimator.setStartTime(28); + backendBlendedClipAnimator.setLastLocalTime(0.28); backendBlendedClipAnimator.cleanup(); // THEN @@ -89,7 +91,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp index 478406336..a947d4a2d 100644 --- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp +++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp @@ -31,8 +31,10 @@ #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/channelmapping_p.h> #include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/qskeletonmapping.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> #include <Qt3DCore/qentity.h> +#include <Qt3DCore/qskeleton.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -66,6 +68,23 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), mapping.channelName()); QCOMPARE(backendMapping.targetId(), mapping.target()->id()); QCOMPARE(backendMapping.property(), mapping.property()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); + + // GIVEN + Qt3DAnimation::Animation::ChannelMapping backendSkeletonMapping; + backendSkeletonMapping.setHandler(&handler); + Qt3DAnimation::QSkeletonMapping skeletonMapping; + auto skeleton = new Qt3DCore::QSkeleton; + skeletonMapping.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&skeletonMapping, &backendSkeletonMapping); + + // THEN + QCOMPARE(backendSkeletonMapping.peerId(), skeletonMapping.id()); + QCOMPARE(backendSkeletonMapping.isEnabled(), skeletonMapping.isEnabled()); + QCOMPARE(backendSkeletonMapping.skeletonId(), skeletonMapping.skeleton()->id()); + QCOMPARE(backendSkeletonMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::SkeletonMappingType); } void checkInitialAndCleanedUpState() @@ -81,6 +100,8 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); // GIVEN Qt3DAnimation::QChannelMapping mapping; @@ -91,6 +112,7 @@ private Q_SLOTS: // WHEN simulateInitialization(&mapping, &backendMapping); + backendMapping.setSkeletonId(Qt3DCore::QNodeId::createId()); backendMapping.cleanup(); // THEN @@ -98,6 +120,8 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); } void checkPropertyChanges() @@ -146,6 +170,16 @@ private Q_SLOTS: // THEN QCOMPARE(backendMapping.property(), property); + + // WHEN + const auto skeletonId = Qt3DCore::QNodeId::createId(); + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("skeleton"); + updateChange->setValue(QVariant::fromValue(skeletonId)); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.skeletonId(), skeletonId); } }; diff --git a/tests/auto/animation/clipanimator/tst_clipanimator.cpp b/tests/auto/animation/clipanimator/tst_clipanimator.cpp index e837a2a82..168cba050 100644 --- a/tests/auto/animation/clipanimator/tst_clipanimator.cpp +++ b/tests/auto/animation/clipanimator/tst_clipanimator.cpp @@ -30,6 +30,7 @@ #include <Qt3DAnimation/private/clipanimator_p.h> #include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qclipanimator.h> +#include <Qt3DAnimation/qclock.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -50,8 +51,10 @@ private Q_SLOTS: backendAnimator.setHandler(&handler); Qt3DAnimation::QClipAnimator animator; auto clip = new Qt3DAnimation::QAnimationClipLoader(); + auto clock = new Qt3DAnimation::QClock(); animator.setClip(clip); + animator.setClock(clock); animator.setLoopCount(10); // WHEN @@ -61,6 +64,7 @@ private Q_SLOTS: QCOMPARE(backendAnimator.peerId(), animator.id()); QCOMPARE(backendAnimator.isEnabled(), animator.isEnabled()); QCOMPARE(backendAnimator.clipId(), clip->id()); + QCOMPARE(backendAnimator.clockId(), clock->id()); QCOMPARE(backendAnimator.isRunning(), animator.isRunning()); QCOMPARE(backendAnimator.loops(), animator.loopCount()); } @@ -76,23 +80,28 @@ private Q_SLOTS: QVERIFY(backendAnimator.peerId().isNull()); QCOMPARE(backendAnimator.isEnabled(), false); QCOMPARE(backendAnimator.clipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAnimator.clockId(), Qt3DCore::QNodeId()); QCOMPARE(backendAnimator.isRunning(), false); QCOMPARE(backendAnimator.loops(), 1); // GIVEN Qt3DAnimation::QClipAnimator animator; auto clip = new Qt3DAnimation::QAnimationClipLoader(); + auto clock = new Qt3DAnimation::QClock(); animator.setClip(clip); + animator.setClock(clock); animator.setRunning(true); animator.setLoopCount(25); // WHEN simulateInitialization(&animator, &backendAnimator); backendAnimator.setClipId(Qt3DCore::QNodeId::createId()); + backendAnimator.setClockId(Qt3DCore::QNodeId::createId()); backendAnimator.cleanup(); // THEN QCOMPARE(backendAnimator.clipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAnimator.clockId(), Qt3DCore::QNodeId()); QCOMPARE(backendAnimator.isEnabled(), false); QCOMPARE(backendAnimator.isRunning(), false); QCOMPARE(backendAnimator.loops(), 1); @@ -126,6 +135,16 @@ private Q_SLOTS: QCOMPARE(backendAnimator.clipId(), newClip->id()); // WHEN + auto clock = new Qt3DAnimation::QClock(); + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("clock"); + updateChange->setValue(QVariant::fromValue(clock->id())); + backendAnimator.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendAnimator.clockId(), clock->id()); + + // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setPropertyName("running"); updateChange->setValue(true); diff --git a/tests/auto/animation/clock/clock.pro b/tests/auto/animation/clock/clock.pro new file mode 100644 index 000000000..26b7a4b21 --- /dev/null +++ b/tests/auto/animation/clock/clock.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_clock + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_clock.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/clock/tst_clock.cpp b/tests/auto/animation/clock/tst_clock.cpp new file mode 100644 index 000000000..a81adfe7b --- /dev/null +++ b/tests/auto/animation/clock/tst_clock.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qclock.h> +#include <Qt3DAnimation/private/clock_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +class tst_Clock: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + Qt3DAnimation::QClock clock; + + clock.setPlaybackRate(10.5); + + // WHEN + simulateInitialization(&clock, &backendClock); + + // THEN + QCOMPARE(backendClock.playbackRate(), clock.playbackRate()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + + // THEN + QCOMPARE(backendClock.playbackRate(), 1.0); + + // GIVEN + Qt3DAnimation::QClock clock; + clock.setPlaybackRate(10.5); + + // WHEN + simulateInitialization(&clock, &backendClock); + backendClock.cleanup(); + + // THEN + QCOMPARE(backendClock.playbackRate(), 1.0); + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendClock.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClock.isEnabled(), newValue); + } + { + // WHEN + const double newPlaybackRateValue = 2.0; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("playbackRate"); + change->setValue(newPlaybackRateValue); + backendClock.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClock.playbackRate(), newPlaybackRateValue); + } + } +}; + +QTEST_APPLESS_MAIN(tst_Clock) + +#include "tst_clock.moc" diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp index 79d18b7cf..ce37ffc76 100644 --- a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -72,6 +72,7 @@ public: channelMapping->setPropertyName(propertyName); channelMapping->setChannelName(channelName); channelMapping->setType(type); + channelMapping->setMappingType(ChannelMapping::ChannelMappingType); return channelMapping; } diff --git a/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro new file mode 100644 index 000000000..2ec002878 --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qcallbackmapping + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qcallbackmapping.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp new file mode 100644 index 000000000..6a1c8da8c --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qcallbackmapping.h> +#include <Qt3DAnimation/private/qcallbackmapping_p.h> +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class DummyCallback : public Qt3DAnimation::QAnimationCallback +{ +public: + void valueChanged(const QVariant &) override { } +}; + +class tst_QCallbackMapping : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + // THEN + QCOMPARE(mapping.channelName(), QString()); + QCOMPARE(mapping.callback(), static_cast<Qt3DAnimation::QAnimationCallback *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + { + // WHEN + QSignalSpy spy(&mapping, SIGNAL(channelNameChanged(QString))); + const QString newValue(QStringLiteral("Rotation")); + mapping.setChannelName(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mapping.setChannelName(newValue); + + // THEN + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + auto newValue = new DummyCallback(); + mapping.setCallback(QVariant::Quaternion, newValue); + + // THEN - no signals for callback + QCOMPARE(mapping.callback(), newValue); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + auto callback = new DummyCallback(); + + mapping.setChannelName(QStringLiteral("Location")); + mapping.setCallback(QVariant::Vector3D, callback); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), true); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + + // WHEN + mapping.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), false); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QCallbackMapping mapping; + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "channelName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toString(), mapping.channelName()); + + arbiter.events.clear(); + + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + auto callback = new DummyCallback(); + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 3); + auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), QVariant::Vector3D); + + change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callback"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(reinterpret_cast<DummyCallback *>(change->value().value<void *>()), callback); + + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callbackFlags"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), static_cast<int>(Qt3DAnimation::QAnimationCallback::OnThreadPool)); + + arbiter.events.clear(); + + // WHEN + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QCallbackMapping) + +#include "tst_qcallbackmapping.moc" diff --git a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp index 9d356de4c..cab5fda6f 100644 --- a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp +++ b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp @@ -29,6 +29,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qchannelmapping.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -142,13 +143,14 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for target - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); const Qt3DAnimation::QChannelMappingData data = creationChangeData->data; QCOMPARE(mapping.id(), creationChangeData->subjectId()); QCOMPARE(mapping.isEnabled(), true); QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::ChannelMapping); QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); @@ -166,13 +168,14 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for target - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); const Qt3DAnimation::QChannelMappingData data = creationChangeData->data; QCOMPARE(mapping.id(), creationChangeData->subjectId()); QCOMPARE(mapping.isEnabled(), false); QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::ChannelMapping); QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); diff --git a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp index 1ed4b8f13..6a46b7008 100644 --- a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp +++ b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp @@ -30,6 +30,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qclock.h> #include <Qt3DAnimation/qclipanimator.h> #include <Qt3DAnimation/private/qanimationclip_p.h> #include <Qt3DAnimation/private/qclipanimator_p.h> @@ -49,6 +50,7 @@ private Q_SLOTS: { qRegisterMetaType<Qt3DAnimation::QAbstractAnimationClip*>(); qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(); + qRegisterMetaType<Qt3DAnimation::QClock*>(); } void checkDefaultConstruction() @@ -59,6 +61,7 @@ private Q_SLOTS: // THEN QCOMPARE(animator.clip(), static_cast<Qt3DAnimation::QAbstractAnimationClip *>(nullptr)); QCOMPARE(animator.channelMapper(), static_cast<Qt3DAnimation::QChannelMapper *>(nullptr)); + QCOMPARE(animator.clock(), static_cast<Qt3DAnimation::QClock*>(nullptr)); QCOMPARE(animator.loopCount(), 1); } @@ -111,6 +114,27 @@ private Q_SLOTS: { // WHEN + QSignalSpy spy(&animator, SIGNAL(clockChanged(Qt3DAnimation::QClock *))); + auto clock = new Qt3DAnimation::QClock(); + animator.setClock(clock); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(animator.clock(), clock); + QCOMPARE(clock->parent(), &animator); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animator.setClock(clock); + + // THEN + QCOMPARE(animator.clock(), clock); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN QSignalSpy spy(&animator, SIGNAL(loopCountChanged(int))); const int newValue = 5; animator.setLoopCount(newValue); @@ -138,6 +162,8 @@ private Q_SLOTS: animator.setClip(clip); auto mapper = new Qt3DAnimation::QChannelMapper(); animator.setChannelMapper(mapper); + auto clock = new Qt3DAnimation::QClock(); + animator.setClock(clock); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -148,7 +174,7 @@ private Q_SLOTS: // THEN { - QCOMPARE(creationChanges.size(), 3); + QCOMPARE(creationChanges.size(), 4); const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClipAnimatorData>>(creationChanges.first()); const Qt3DAnimation::QClipAnimatorData data = creationChangeData->data; @@ -159,6 +185,7 @@ private Q_SLOTS: QCOMPARE(animator.metaObject(), creationChangeData->metaObject()); QCOMPARE(animator.clip()->id(), data.clipId); QCOMPARE(animator.channelMapper()->id(), data.mapperId); + QCOMPARE(animator.clock()->id(), data.clockId); QCOMPARE(animator.loopCount(), data.loops); } @@ -171,7 +198,7 @@ private Q_SLOTS: // THEN { - QCOMPARE(creationChanges.size(), 3); + QCOMPARE(creationChanges.size(), 4); const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClipAnimatorData>>(creationChanges.first()); @@ -240,6 +267,32 @@ private Q_SLOTS: QCOMPARE(arbiter.events.size(), 0); } + // GIVEN + auto clock = new Qt3DAnimation::QClock; + { + // WHEN + animator.setClock(clock); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "clock"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clock->id()); + + arbiter.events.clear(); + } + + { + // WHEN + animator.setClock(clock); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + { // WHEN animator.setLoopCount(10); diff --git a/tests/auto/animation/qclock/qclock.pro b/tests/auto/animation/qclock/qclock.pro new file mode 100644 index 000000000..2b1194860 --- /dev/null +++ b/tests/auto/animation/qclock/qclock.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qclock + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qclock.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qclock/tst_qclock.cpp b/tests/auto/animation/qclock/tst_qclock.cpp new file mode 100644 index 000000000..34c70da7b --- /dev/null +++ b/tests/auto/animation/qclock/tst_qclock.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DAnimation/qclock.h> +#include <Qt3DAnimation/private/qclock_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class tst_QClock : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QClock*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QClock clock; + + // THEN + QCOMPARE(clock.playbackRate(), 1.0); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QClock clock; + + // WHEN + QSignalSpy spy(&clock, SIGNAL(playbackRateChanged(double))); + const double newValue = 5.5; + clock.setPlaybackRate(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(clock.playbackRate(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + clock.setPlaybackRate(newValue); + + // THEN + QCOMPARE(clock.playbackRate(), newValue); + QCOMPARE(spy.count(), 0); + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QClock clock; + clock.setPlaybackRate(10.f); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clock); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClockData>>(creationChanges.first()); + const Qt3DAnimation::QClockData data = creationChangeData->data; + + QCOMPARE(clock.id(), creationChangeData->subjectId()); + QCOMPARE(clock.isEnabled(), true); + QCOMPARE(clock.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clock.metaObject(), creationChangeData->metaObject()); + QCOMPARE(clock.playbackRate(), data.playbackRate); + } + + // WHEN + clock.setEnabled(false); + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clock); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClockData>>(creationChanges.first()); + + QCOMPARE(clock.id(), creationChangeData->subjectId()); + QCOMPARE(clock.isEnabled(), false); + QCOMPARE(clock.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clock.metaObject(), creationChangeData->metaObject()); + } + } + + void checkPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QClock clock; + arbiter.setArbiterOnNode(&clock); + + { + // WHEN + clock.setPlaybackRate(10.5); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "playbackRate"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<double>(), clock.playbackRate()); + + arbiter.events.clear(); + } + + { + // WHEN + clock.setPlaybackRate(10.5f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QClock) + +#include "tst_qclock.moc" diff --git a/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro b/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro new file mode 100644 index 000000000..c00252557 --- /dev/null +++ b/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qskeletonmapping + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qskeletonmapping.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp new file mode 100644 index 000000000..452292e9e --- /dev/null +++ b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qskeletonmapping.h> +#include <Qt3DAnimation/private/qskeletonmapping_p.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class tst_QSkeletonMapping : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DCore::QAbstractSkeleton*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + + // THEN + QCOMPARE(mapping.skeleton(), static_cast<Qt3DCore::QAbstractSkeleton *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + + { + // WHEN + QSignalSpy spy(&mapping, SIGNAL(skeletonChanged(Qt3DCore::QAbstractSkeleton*))); + auto newValue = new Qt3DCore::QSkeleton(); + mapping.setSkeleton(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mapping.skeleton(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mapping.setSkeleton(newValue); + + // THEN + QCOMPARE(mapping.skeleton(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + auto target = new Qt3DCore::QSkeleton; + + mapping.setSkeleton(target); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for skeleton + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QSkeletonMappingData>>(creationChanges.first()); + const Qt3DAnimation::QSkeletonMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), true); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::SkeletonMapping); + QCOMPARE(mapping.skeleton()->id(), data.skeletonId); + } + + // WHEN + mapping.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for skeleton + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QSkeletonMappingData>>(creationChanges.first()); + const Qt3DAnimation::QSkeletonMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), false); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::SkeletonMapping); + QCOMPARE(mapping.skeleton()->id(), data.skeletonId); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QSkeletonMapping mapping; + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + auto target = new Qt3DCore::QSkeleton(); + mapping.setSkeleton(target); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "skeleton"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), mapping.skeleton()->id()); + + arbiter.events.clear(); + + // WHEN + mapping.setSkeleton(target); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QSkeletonMapping) + +#include "tst_qskeletonmapping.moc" diff --git a/tests/auto/animation/skeleton/skeleton.pro b/tests/auto/animation/skeleton/skeleton.pro new file mode 100644 index 000000000..b36278bdf --- /dev/null +++ b/tests/auto/animation/skeleton/skeleton.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_skeleton + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_skeleton.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/skeleton/tst_skeleton.cpp b/tests/auto/animation/skeleton/tst_skeleton.cpp new file mode 100644 index 000000000..9e3cfef6d --- /dev/null +++ b/tests/auto/animation/skeleton/tst_skeleton.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DAnimation/private/skeleton_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; +using namespace Qt3DAnimation; +using namespace Qt3DAnimation::Animation; + +class tst_Skeleton : public QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + QSkeleton skeleton; + auto rootJoint = new QJoint(); + rootJoint->setName(QLatin1String("rootJoint")); + auto childJoint = new QJoint(); + childJoint->setName(QLatin1String("childJoint")); + rootJoint->addChildJoint(childJoint); + skeleton.setRootJoint(rootJoint); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + + // THEN - nothing mirrored from frontend + QCOMPARE(backendSkeleton.peerId(), skeleton.id()); + QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled()); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + + // THEN + QVERIFY(backendSkeleton.peerId().isNull()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + + // GIVEN + const QVector<QString> names = (QVector<QString>() + << QLatin1String("root") + << QLatin1String("child1") + << QLatin1String("child2")); + const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt()); + + // WHEN + backendSkeleton.setJointNames(names); + backendSkeleton.setJointLocalPoses(localPoses); + backendSkeleton.cleanup(); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + } + + void checkPropertyChanges() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange = QPropertyUpdatedChangePtr::create(QNodeId()); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), true); + + // GIVEN + const QVector<QString> names = (QVector<QString>() + << QLatin1String("root") + << QLatin1String("child1") + << QLatin1String("child2")); + const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt()); + + // WHEN + JointNamesAndLocalPoses namesAndPoses; + namesAndPoses.names = names; + namesAndPoses.localPoses = localPoses; + + updateChange = QPropertyUpdatedChangePtr::create(QNodeId()); + updateChange->setPropertyName("jointNamesAndLocalPoses"); + updateChange->setValue(QVariant::fromValue(namesAndPoses)); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.jointNames(), names); + QCOMPARE(backendSkeleton.jointLocalPoses(), localPoses); + } +}; + +QTEST_APPLESS_MAIN(tst_Skeleton) + +#include "tst_skeleton.moc" diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index cc7e5590a..2d7ec9cb3 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -3,15 +3,17 @@ TEMPLATE = subdirs SUBDIRS = \ coretest \ core \ - render \ - quick3d \ - cmake \ - input \ - animation \ - extras + cmake installed_cmake.depends = cmake +QT_FOR_CONFIG += 3dcore +qtConfig(qt3d-render): SUBDIRS += render +qtConfig(qt3d-input): SUBDIRS += input +qtConfig(qt3d-animation): SUBDIRS += animation +qtConfig(qt3d-extras): SUBDIRS += extras +qtConfig(qt3d-render):qtConfig(qt3d-input): SUBDIRS += quick3d + for(subdir, SUBDIRS) { !equals(subdir, coretest) { $${subdir}.depends += coretest diff --git a/tests/auto/core/aspectcommanddebugger/tst_aspectcommanddebugger.cpp b/tests/auto/core/aspectcommanddebugger/tst_aspectcommanddebugger.cpp index 1bcaced2c..f13fa2e03 100644 --- a/tests/auto/core/aspectcommanddebugger/tst_aspectcommanddebugger.cpp +++ b/tests/auto/core/aspectcommanddebugger/tst_aspectcommanddebugger.cpp @@ -29,16 +29,13 @@ #include <QtTest/QTest> #include <Qt3DCore/private/aspectcommanddebugger_p.h> -#ifdef QT3D_JOBS_RUN_STATS using namespace Qt3DCore::Debug; -#endif class tst_AspectCommandDebugger : public QObject { Q_OBJECT private slots: -#ifdef QT3D_JOBS_RUN_STATS void checkReadBufferInitialState() { // GIVEN @@ -92,7 +89,6 @@ private slots: QCOMPARE(buffer.size(), 16 * 1024); QCOMPARE(hugeFakeData, QByteArray(buffer.buffer.constData(), 1024 * 16)); } -#endif }; QTEST_APPLESS_MAIN(tst_AspectCommandDebugger) diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro index 3595755d6..25440ce0e 100644 --- a/tests/auto/core/core.pro +++ b/tests/auto/core/core.pro @@ -11,14 +11,27 @@ SUBDIRS = \ qaspectjob \ qchangearbiter \ qscene \ - qservicelocator + qservicelocator \ + qjoint \ + qskeletonloader \ + qskeleton \ + qarmature qtConfig(private_tests) { SUBDIRS += \ - qentity \ - qframeallocator \ - qtransform \ - threadpooler \ - aspectcommanddebugger \ - qpostman + qentity \ + qframeallocator \ + qtransform \ + threadpooler \ + qpostman \ + vector4d_base \ + vector3d_base + + QT_FOR_CONFIG += 3dcore-private + qtConfig(qt3d-profile-jobs): SUBDIRS += aspectcommanddebugger + qtConfig(qt3d-simd-sse2) { + SUBDIRS += \ + vector4d_sse \ + vector3d_sse + } } diff --git a/tests/auto/core/qarmature/qarmature.pro b/tests/auto/core/qarmature/qarmature.pro new file mode 100644 index 000000000..1d4769310 --- /dev/null +++ b/tests/auto/core/qarmature/qarmature.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_qarmature + +QT += core-private 3dcore 3dcore-private testlib + +CONFIG += testcase + +SOURCES += tst_qarmature.cpp + +include(../common/common.pri) diff --git a/tests/auto/core/qarmature/tst_qarmature.cpp b/tests/auto/core/qarmature/tst_qarmature.cpp new file mode 100644 index 000000000..f624b998f --- /dev/null +++ b/tests/auto/core/qarmature/tst_qarmature.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qarmature.h> +#include <Qt3DCore/private/qarmature_p.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/qpropertyupdatedchange.h> + +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> + +#include "testpostmanarbiter.h" + +using namespace Qt3DCore; + +class tst_QArmature: public QObject +{ + Q_OBJECT +public: + tst_QArmature() + { + qRegisterMetaType<Qt3DCore::QAbstractSkeleton*>(); + } + +private Q_SLOTS: + + void checkCreationChange_data() + { + QTest::addColumn<QArmature *>("armature"); + + QArmature *defaultConstructed = new QArmature(); + QTest::newRow("defaultConstructed") << defaultConstructed; + + QArmature *armatureWithSkeleton = new QArmature(); + armatureWithSkeleton->setSkeleton(new QSkeleton()); + QTest::newRow("skeletonWithOneJoint") << armatureWithSkeleton; + } + + void checkCreationChange() + { + // GIVEN + QFETCH(QArmature *, armature); + + // WHEN + QNodeCreatedChangeGenerator creationChangeGenerator(armature); + QVector<QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); + + const int skeletonCount = armature->skeleton() ? 1 : 0; + + // THEN + QCOMPARE(creationChanges.size(), 1 + skeletonCount); + + const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QArmatureData>>(creationChanges.first()); + const QArmatureData &data = creationChangeData->data; + + // THEN + QCOMPARE(armature->id(), creationChangeData->subjectId()); + QCOMPARE(armature->isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(armature->metaObject(), creationChangeData->metaObject()); + if (armature->skeleton()) { + QCOMPARE(armature->skeleton()->id(), data.skeletonId); + } + } + + void checkPropertyUpdates() + { + // GIVEN + TestArbiter arbiter; + QScopedPointer<QArmature> armature(new QArmature()); + arbiter.setArbiterOnNode(armature.data()); + + // WHEN + QSkeleton *skeleton = new QSkeleton(armature.data()); + QCoreApplication::processEvents(); + arbiter.events.clear(); + + armature->setSkeleton(skeleton); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "skeleton"); + QCOMPARE(change->value().value<QNodeId>(), skeleton->id()); + QCOMPARE(change->type(), PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + armature->setSkeleton(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "skeleton"); + QCOMPARE(change->value().value<QNodeId>(), QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + void checkSkeletonBookkeeping() + { + // GIVEN + QScopedPointer<QArmature> armature(new QArmature); + { + // WHEN + QSkeleton skeleton; + armature->setSkeleton(&skeleton); + + // THEN + QCOMPARE(skeleton.parent(), armature.data()); + QCOMPARE(armature->skeleton(), &skeleton); + } + // THEN (Should not crash and parameter be unset) + QVERIFY(armature->skeleton() == nullptr); + + { + // WHEN + QArmature someOtherArmature; + QScopedPointer<QSkeleton> skeleton(new QSkeleton(&someOtherArmature)); + armature->setSkeleton(skeleton.data()); + + // THEN + QCOMPARE(skeleton->parent(), &someOtherArmature); + QCOMPARE(armature->skeleton(), skeleton.data()); + + // WHEN + armature.reset(); + skeleton.reset(); + + // THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QArmature) + +#include "tst_qarmature.moc" diff --git a/tests/auto/core/qjoint/qjoint.pro b/tests/auto/core/qjoint/qjoint.pro new file mode 100644 index 000000000..e25d57102 --- /dev/null +++ b/tests/auto/core/qjoint/qjoint.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qjoint + +QT += 3dcore 3dcore-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qjoint.cpp + +include(../common/common.pri) diff --git a/tests/auto/core/qjoint/tst_qjoint.cpp b/tests/auto/core/qjoint/tst_qjoint.cpp new file mode 100644 index 000000000..ec1a45f90 --- /dev/null +++ b/tests/auto/core/qjoint/tst_qjoint.cpp @@ -0,0 +1,413 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/private/qjoint_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; + +class tst_QJoint : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + QJoint joint; + + // THEN + QCOMPARE(joint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(joint.rotation(), QQuaternion()); + QCOMPARE(joint.translation(), QVector3D(0.0f, 0.0f, 0.0f)); + QCOMPARE(joint.inverseBindMatrix(), QMatrix4x4()); + QCOMPARE(joint.rotationX(), 0.0f); + QCOMPARE(joint.rotationY(), 0.0f); + QCOMPARE(joint.rotationZ(), 0.0f); + } + + void checkPropertyChanges() + { + // GIVEN + QJoint joint; + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(scaleChanged(QVector3D))); + const QVector3D newValue(2.5f, 2.0f, 1.3f); + joint.setScale(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(joint.scale(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + joint.setScale(newValue); + + // THEN + QCOMPARE(joint.scale(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); + const auto newValue = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 45.0f); + joint.setRotation(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(joint.rotation(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + joint.setRotation(newValue); + + // THEN + QCOMPARE(joint.rotation(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(translationChanged(QVector3D))); + const QVector3D newValue(1.0f, 2.0f, 3.0f); + joint.setTranslation(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(joint.translation(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + joint.setTranslation(newValue); + + // THEN + QCOMPARE(joint.translation(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(inverseBindMatrixChanged(QMatrix4x4))); + QMatrix4x4 newValue; + newValue.scale(3.5f); + joint.setInverseBindMatrix(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(joint.inverseBindMatrix(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + joint.setInverseBindMatrix(newValue); + + // THEN + QCOMPARE(joint.inverseBindMatrix(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); + QSignalSpy spyEuler(&joint, SIGNAL(rotationXChanged(float))); + const auto newValue = 45.0f; + const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(newValue, 0.0f, 0.0f); + joint.setRotationX(newValue); + + // THEN + QVERIFY(spy.isValid()); + QVERIFY(spyEuler.isValid()); + QCOMPARE(joint.rotationX(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 1); + QCOMPARE(spyEuler.count(), 1); + + // WHEN + spy.clear(); + spyEuler.clear(); + joint.setRotationX(newValue); + + // THEN + QCOMPARE(joint.rotationX(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 0); + QCOMPARE(spyEuler.count(), 0); + + joint.setRotationX(0.0f); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); + QSignalSpy spyEuler(&joint, SIGNAL(rotationYChanged(float))); + const auto newValue = 45.0f; + const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(0.0f, newValue, 0.0f); + joint.setRotationY(newValue); + + // THEN + QVERIFY(spy.isValid()); + QVERIFY(spyEuler.isValid()); + QCOMPARE(joint.rotationY(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 1); + QCOMPARE(spyEuler.count(), 1); + + // WHEN + spy.clear(); + spyEuler.clear(); + joint.setRotationY(newValue); + + // THEN + QCOMPARE(joint.rotationY(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 0); + QCOMPARE(spyEuler.count(), 0); + + joint.setRotationY(0.0f); + } + + { + // WHEN + joint.setToIdentity(); + QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); + QSignalSpy spyEuler(&joint, SIGNAL(rotationZChanged(float))); + const auto newValue = 45.0f; + const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(0.0f, 0.0f, newValue); + joint.setRotationZ(newValue); + + // THEN + QVERIFY(spy.isValid()); + QVERIFY(spyEuler.isValid()); + QCOMPARE(joint.rotationZ(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 1); + QCOMPARE(spyEuler.count(), 1); + + // WHEN + spy.clear(); + spyEuler.clear(); + joint.setRotationZ(newValue); + + // THEN + QCOMPARE(joint.rotationZ(), newValue); + QCOMPARE(joint.rotation(), newValueAsQuaternion); + QCOMPARE(spy.count(), 0); + QCOMPARE(spyEuler.count(), 0); + + joint.setRotationZ(0.0f); + } + } + + void checkCreationData() + { + // GIVEN + QJoint joint; + + joint.setScale(QVector3D(3.5f, 2.0f, 1.3f)); + joint.setRotation(QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 30.0f)); + joint.setTranslation(QVector3D(3.0f, 2.0f, 1.0f)); + QMatrix4x4 ibm; + ibm.scale(5.2f); + joint.setInverseBindMatrix(ibm); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&joint); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData + = qSharedPointerCast<QNodeCreatedChange<QJointData>>(creationChanges.first()); + const QJointData data = creationChangeData->data; + + QCOMPARE(joint.id(), creationChangeData->subjectId()); + QCOMPARE(joint.isEnabled(), true); + QCOMPARE(joint.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(joint.metaObject(), creationChangeData->metaObject()); + QCOMPARE(joint.scale(), data.scale); + QCOMPARE(joint.rotation(), data.rotation); + QCOMPARE(joint.translation(), data.translation); + QCOMPARE(joint.inverseBindMatrix(), data.inverseBindMatrix); + } + + // WHEN + joint.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&joint); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData + = qSharedPointerCast<QNodeCreatedChange<QJointData>>(creationChanges.first()); + const QJointData data = creationChangeData->data; + + QCOMPARE(joint.id(), creationChangeData->subjectId()); + QCOMPARE(joint.isEnabled(), false); + QCOMPARE(joint.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(joint.metaObject(), creationChangeData->metaObject()); + QCOMPARE(joint.scale(), data.scale); + QCOMPARE(joint.rotation(), data.rotation); + QCOMPARE(joint.translation(), data.translation); + QCOMPARE(joint.inverseBindMatrix(), data.inverseBindMatrix); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + QJoint joint; + arbiter.setArbiterOnNode(&joint); + + { + // WHEN + joint.setScale(QVector3D(2.0f, 1.0f, 3.0f)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "scale"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<QVector3D>(), joint.scale()); + + arbiter.events.clear(); + + // WHEN + joint.setScale(QVector3D(2.0f, 1.0f, 3.0f)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + const auto newValue = QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 1.0f, 45.0f); + joint.setRotation(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "rotation"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<QQuaternion>(), newValue); + + arbiter.events.clear(); + + // WHEN + joint.setRotation(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + const QVector3D newValue(1.0f, 2.0f, 3.0f); + joint.setTranslation(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "translation"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<QVector3D>(), newValue); + + arbiter.events.clear(); + + // WHEN + joint.setTranslation(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + QMatrix4x4 newValue; + newValue.rotate(90.0f, 1.0f, 0.0f, 0.0f); + joint.setInverseBindMatrix(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "inverseBindMatrix"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<QMatrix4x4>(), newValue); + + arbiter.events.clear(); + + // WHEN + joint.setInverseBindMatrix(newValue); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QJoint) + +#include "tst_qjoint.moc" diff --git a/tests/auto/core/qskeleton/qskeleton.pro b/tests/auto/core/qskeleton/qskeleton.pro new file mode 100644 index 000000000..3bbb48a3c --- /dev/null +++ b/tests/auto/core/qskeleton/qskeleton.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_qskeleton + +QT += core-private 3dcore 3dcore-private testlib + +CONFIG += testcase + +SOURCES += tst_qskeleton.cpp + +include(../common/common.pri) diff --git a/tests/auto/core/qskeleton/tst_qskeleton.cpp b/tests/auto/core/qskeleton/tst_qskeleton.cpp new file mode 100644 index 000000000..f66e07cbe --- /dev/null +++ b/tests/auto/core/qskeleton/tst_qskeleton.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/private/qskeleton_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qpropertynodeaddedchange.h> +#include <Qt3DCore/qpropertynoderemovedchange.h> + +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> + +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; + +class tst_QSkeleton: public QSkeleton +{ + Q_OBJECT +public: + tst_QSkeleton() + { + qRegisterMetaType<Qt3DCore::QJoint*>(); + } + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + QSkeleton skeleton; + + // THEN + QCOMPARE(skeleton.jointCount(), 0); + } + + void checkCreationChange_data() + { + QTest::addColumn<QSkeleton *>("skeleton"); + + QSkeleton *defaultConstructed = new QSkeleton(); + QTest::newRow("defaultConstructed") << defaultConstructed; + + QSkeleton *skeletonWithOneJoint = new QSkeleton(); + skeletonWithOneJoint->setRootJoint(new QJoint()); + QTest::newRow("skeletonWithOneJoint") << skeletonWithOneJoint; + } + + void checkCreationChange() + { + // GIVEN + QFETCH(QSkeleton *, skeleton); + + // WHEN + QNodeCreatedChangeGenerator creationChangeGenerator(skeleton); + QVector<QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); + + const int jointCount = skeleton->rootJoint() ? 1 : 0; + + // THEN + QCOMPARE(creationChanges.size(), 1 + jointCount); + + const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonData>>(creationChanges.first()); + const QSkeletonData &data = creationChangeData->data; + + // THEN + QCOMPARE(skeleton->id(), creationChangeData->subjectId()); + QCOMPARE(skeleton->isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(skeleton->metaObject(), creationChangeData->metaObject()); + if (skeleton->rootJoint()) { + QCOMPARE(skeleton->rootJoint()->id(), data.rootJointId); + } + } + + void checkPropertyUpdates() + { + // GIVEN + TestArbiter arbiter; + QScopedPointer<QSkeleton> skeleton(new QSkeleton()); + arbiter.setArbiterOnNode(skeleton.data()); + + // WHEN + QJoint *joint = new QJoint(skeleton.data()); + QCoreApplication::processEvents(); + arbiter.events.clear(); + + skeleton->setRootJoint(joint); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "rootJoint"); + QCOMPARE(change->value().value<QNodeId>(), joint->id()); + QCOMPARE(change->type(), PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + skeleton->setRootJoint(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "rootJoint"); + QCOMPARE(change->value().value<QNodeId>(), QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + void checkRootJointBookkeeping() + { + // GIVEN + QScopedPointer<QSkeleton> skeleton(new QSkeleton); + { + // WHEN + QJoint joint; + skeleton->setRootJoint(&joint); + + // THEN + QCOMPARE(joint.parent(), skeleton.data()); + QCOMPARE(skeleton->rootJoint(), &joint); + } + // THEN (Should not crash and parameter be unset) + QVERIFY(skeleton->rootJoint() == nullptr); + + { + // WHEN + QSkeleton someOtherSkeleton; + QScopedPointer<QJoint> joint(new QJoint(&someOtherSkeleton)); + skeleton->setRootJoint(joint.data()); + + // THEN + QCOMPARE(joint->parent(), &someOtherSkeleton); + QCOMPARE(skeleton->rootJoint(), joint.data()); + + // WHEN + skeleton.reset(); + joint.reset(); + + // THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper) + } + } + + void checkJointCountPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(jointCountChanged(int))); + const int newJointCount = 99; + + // THEN + QVERIFY(spy.isValid()); + + // WHEN + auto valueChange = QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + valueChange->setPropertyName("jointCount"); + valueChange->setValue(QVariant(newJointCount)); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(jointCount(), newJointCount); + + // WHEN + spy.clear(); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(jointCount(), newJointCount); + } +}; + +QTEST_MAIN(tst_QSkeleton) + +#include "tst_qskeleton.moc" diff --git a/tests/auto/core/qskeletonloader/qskeletonloader.pro b/tests/auto/core/qskeletonloader/qskeletonloader.pro new file mode 100644 index 000000000..6172906c2 --- /dev/null +++ b/tests/auto/core/qskeletonloader/qskeletonloader.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qskeletonloader + +QT += 3dcore 3dcore-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qskeletonloader.cpp + +include(../common/common.pri) diff --git a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp new file mode 100644 index 000000000..1386429d4 --- /dev/null +++ b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/private/qskeletonloader_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; + +class tst_QSkeletonLoader : public QSkeletonLoader +{ + Q_OBJECT + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + QSkeletonLoader skeleton; + + // THEN + QCOMPARE(skeleton.source(), QUrl()); + QCOMPARE(skeleton.status(), QSkeletonLoader::NotReady); + QCOMPARE(skeleton.isCreateJointsEnabled(), false); + } + + void checkPropertyChanges() + { + // GIVEN + QSkeletonLoader skeleton; + + { + // WHEN + QSignalSpy spy(&skeleton, SIGNAL(sourceChanged(QUrl))); + const QUrl newValue(QStringLiteral("qrc:/zergling.skel")); + skeleton.setSource(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(skeleton.source(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + skeleton.setSource(newValue); + + // THEN + QCOMPARE(skeleton.source(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&skeleton, SIGNAL(createJointsEnabledChanged(bool))); + const bool newValue(true); + skeleton.setCreateJointsEnabled(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(skeleton.isCreateJointsEnabled(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + skeleton.setCreateJointsEnabled(newValue); + + // THEN + QCOMPARE(skeleton.isCreateJointsEnabled(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + QSkeletonLoader skeleton; + + skeleton.setSource(QUrl(QStringLiteral("http://someRemoteURL.com/dem-bones.skel"))); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + QNodeCreatedChangeGenerator creationChangeGenerator(&skeleton); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonLoaderData>>(creationChanges.first()); + const QSkeletonLoaderData data = creationChangeData->data; + + QCOMPARE(skeleton.id(), creationChangeData->subjectId()); + QCOMPARE(skeleton.isEnabled(), true); + QCOMPARE(skeleton.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(skeleton.metaObject(), creationChangeData->metaObject()); + QCOMPARE(skeleton.source(), data.source); + QCOMPARE(skeleton.isCreateJointsEnabled(), data.createJoints); + } + + // WHEN + skeleton.setEnabled(false); + + { + QNodeCreatedChangeGenerator creationChangeGenerator(&skeleton); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonLoaderData>>(creationChanges.first()); + const QSkeletonLoaderData data = creationChangeData->data; + + QCOMPARE(skeleton.id(), creationChangeData->subjectId()); + QCOMPARE(skeleton.isEnabled(), false); + QCOMPARE(skeleton.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(skeleton.metaObject(), creationChangeData->metaObject()); + QCOMPARE(skeleton.source(), data.source); + QCOMPARE(skeleton.isCreateJointsEnabled(), data.createJoints); + } + } + + void checkPropertyUpdates() + { + // GIVEN + TestArbiter arbiter; + QSkeletonLoader skeleton; + arbiter.setArbiterOnNode(&skeleton); + + { + // WHEN + skeleton.setSource(QUrl(QStringLiteral("qrc:/hydralisk.skel"))); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "source"); + QCOMPARE(change->type(), PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + skeleton.setSource(QStringLiteral("qrc:/hydralisk.skel")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + + { + // WHEN + skeleton.setCreateJointsEnabled(true); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "createJointsEnabled"); + QCOMPARE(change->type(), PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + skeleton.setCreateJointsEnabled(true); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkStatusPropertyUpdate() + { + // GIVEN + qRegisterMetaType<Qt3DCore::QSkeletonLoader::Status>("Status"); + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(statusChanged(Status))); + const QSkeletonLoader::Status newStatus = QSkeletonLoader::Error; + + // THEN + QVERIFY(spy.isValid()); + + // WHEN + QPropertyUpdatedChangePtr valueChange(new QPropertyUpdatedChange(QNodeId())); + valueChange->setPropertyName("status"); + valueChange->setValue(QVariant::fromValue(newStatus)); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + + // WHEN + spy.clear(); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + } + + void checkRootJointPropertyUpdate() + { + // GIVEN + qRegisterMetaType<Qt3DCore::QJoint*>(); + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(rootJointChanged(Qt3DCore::QJoint*))); + std::unique_ptr<QJoint> root(new QJoint()); + + // THEN + QVERIFY(spy.isValid()); + QVERIFY(rootJoint() == nullptr); + + // WHEN + auto valueChange = QJointChangePtr::create(id()); + valueChange->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); + valueChange->setPropertyName("rootJoint"); + valueChange->data = std::move(root); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 1); + QVERIFY(rootJoint() != nullptr); + } +}; + +QTEST_MAIN(tst_QSkeletonLoader) + +#include "tst_qskeletonloader.moc" diff --git a/tests/auto/core/vector3d_base/tst_vector3d_base.cpp b/tests/auto/core/vector3d_base/tst_vector3d_base.cpp new file mode 100644 index 000000000..c3e5390a9 --- /dev/null +++ b/tests/auto/core/vector3d_base/tst_vector3d_base.cpp @@ -0,0 +1,705 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <Qt3DCore/private/vector3d_p.h> + +class tst_Vector3D_Base: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // GIVEN + QVector3D vec3; + + // THEN + QCOMPARE(vec3.x(), 0.0f); + QCOMPARE(vec3.y(), 0.0f); + QCOMPARE(vec3.z(), 0.0f); + } + + void checkExplicitConstruction() + { + // GIVEN + QVector3D vec3(427.0f, 454.0f, 383.0f); + + // THEN + QCOMPARE(vec3.x(), 427.0f); + QCOMPARE(vec3.y(), 454.0f); + QCOMPARE(vec3.z(), 383.0f); + } + + void checkSelfAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << 1.0f << 5.0f << 8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << 0.0f << 0.0f << 0.0f; + } + + void checkSelfAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo += QVector3D(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << -1.0f << -5.0f << -8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << -10.0f << 16.0f << -8.0f; + } + + void checkSelfSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo -= QVector3D(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 16.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -25.0f << -64.0f << 16.0f; + } + + void checkSelfMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo *= QVector3D(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 0.25f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -1.0f << -1.0f << 1.0f; + } + + void checkSelfDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo /= QVector3D(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f + << 0.0f << 0.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -1.0f << 4.0f << -5.0f; + } + + void checkSelfDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo /= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f + << 1.0f + << 0.0f << -3.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -25.0f << 100.0f << -125.0f; + } + + void checkSelfMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D vo(xO, yO, zO); + + // WHEN + vo *= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << 1.0f << 5.0f << 8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << 0.0f << 0.0f << 0.0f; + } + + void checkAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + QVector3D v1(xA, yA, zA); + + // WHEN + QVector3D v2 = v0 + v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << -1.0f << -5.0f << -8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << -10.0f << 16.0f << -8.0f; + } + + void checkSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + QVector3D v1(xA, yA, zA); + + // WHEN + QVector3D v2 = v0 - v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 16.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -25.0f << -64.0f << 16.0f; + } + + void checkMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + QVector3D v1(xA, yA, zA); + + // WHEN + QVector3D v2 = v0 * v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 0.25f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -1.0f << -1.0f << 1.0f; + } + + void checkDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + QVector3D v1(xA, yA, zA); + + // WHEN + QVector3D v2 = v0 / v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f + << 0.0f << 0.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -1.0f << 4.0f << -5.0f; + } + + void checkDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + + // WHEN + QVector3D v2 = v0 / factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f + << 1.0f + << 0.0f << -3.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -25.0f << 100.0f << -125.0f; + } + + void checkMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + QVector3D v0(xO, yO, zO); + + // WHEN + QVector3D v2 = v0 * factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkEquality() + { + { + // GIVEN + QVector3D v0; + QVector3D v1; + + // THEN + QVERIFY(v0 == v1); + } + { + // GIVEN + QVector3D v0(1.0f, 2.0f, -5.0f); + QVector3D v1(1.0f, 2.0f, -5.0f); + + // THEN + QVERIFY(v0 == v1); + } + } + + void checkInequality() + { + { + // GIVEN + QVector3D v0; + QVector3D v1; + + // THEN + QVERIFY(!(v0 != v1)); + } + { + // GIVEN + QVector3D v0(1.0f, 2.0f, -5.0f); + QVector3D v1(1.0f, 5.0f, -5.0f); + + // THEN + QVERIFY(v0 != v1); + } + } + + void checkToQQVector3D() + { + { + // GIVEN + QVector3D v0; + + // WHEN + QVector3D v1 = v0; + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + } + { + // GIVEN + QVector3D v0(1.0f, 2.0f, -5.0f); + + // WHEN + QVector3D v1 = v0; + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + } + } +}; + +QTEST_MAIN(tst_Vector3D_Base) + +#include "tst_vector3d_base.moc" diff --git a/tests/auto/core/vector3d_base/vector3d_base.pro b/tests/auto/core/vector3d_base/vector3d_base.pro new file mode 100644 index 000000000..fa1ee87df --- /dev/null +++ b/tests/auto/core/vector3d_base/vector3d_base.pro @@ -0,0 +1,7 @@ +TARGET = tst_vector3d_base +CONFIG += testcase +QT += testlib 3dcore 3dcore-private + +SOURCES += \ + tst_vector3d_base.cpp + diff --git a/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp b/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp new file mode 100644 index 000000000..be9fbc347 --- /dev/null +++ b/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp @@ -0,0 +1,816 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <Qt3DCore/private/vector3d_sse_p.h> + +using namespace Qt3DCore; + +class tst_Vector3D_SSE: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // GIVEN + Vector3D_SSE vec3; + + // THEN + QCOMPARE(vec3.x(), 0.0f); + QCOMPARE(vec3.y(), 0.0f); + QCOMPARE(vec3.z(), 0.0f); + } + + void checkExplicitConstruction() + { + // GIVEN + Vector3D_SSE vec3(427.0f, 454.0f, 383.0f); + + // THEN + QCOMPARE(vec3.x(), 427.0f); + QCOMPARE(vec3.y(), 454.0f); + QCOMPARE(vec3.z(), 383.0f); + } + + void checkSetters() + { + // GIVEN + Vector3D_SSE vec3; + + // WHEN + vec3.setX(427.0f); + vec3.setY(454.0f); + vec3.setZ(383.0f); + + // THEN + QCOMPARE(vec3.x(), 427.0f); + QCOMPARE(vec3.y(), 454.0f); + QCOMPARE(vec3.z(), 383.0f); + } + + + void checkSelfAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << 1.0f << 5.0f << 8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << 0.0f << 0.0f << 0.0f; + } + + void checkSelfAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo += Vector3D_SSE(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << -1.0f << -5.0f << -8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << -10.0f << 16.0f << -8.0f; + } + + void checkSelfSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo -= Vector3D_SSE(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 16.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -25.0f << -64.0f << 16.0f; + } + + void checkSelfMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo *= Vector3D_SSE(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 0.25f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -1.0f << -1.0f << 1.0f; + } + + void checkSelfDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo /= Vector3D_SSE(xA, yA, zA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f + << 0.0f << 0.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -1.0f << 4.0f << -5.0f; + } + + void checkSelfDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo /= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkSelfMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f + << 1.0f + << 0.0f << -3.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -25.0f << 100.0f << -125.0f; + } + + void checkSelfMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE vo(xO, yO, zO); + + // WHEN + vo *= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + } + + void checkAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << 1.0f << 5.0f << 8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << 0.0f << 0.0f << 0.0f; + } + + void checkAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + Vector3D_SSE v1(xA, yA, zA); + + // WHEN + Vector3D_SSE v2 = v0 + v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f + << -1.0f << -5.0f << -8.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f + << 5.0f << -8.0f << 4.0f + << -10.0f << 16.0f << -8.0f; + } + + void checkSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + Vector3D_SSE v1(xA, yA, zA); + + // WHEN + Vector3D_SSE v2 = v0 - v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 16.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -25.0f << -64.0f << 16.0f; + } + + void checkMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + Vector3D_SSE v1(xA, yA, zA); + + // WHEN + Vector3D_SSE v2 = v0 * v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f << 5.0f << 8.0f + << 0.0f << 0.0f << 0.25f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f + << 5.0f << -8.0f << 4.0f + << -1.0f << -1.0f << 1.0f; + } + + void checkDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + Vector3D_SSE v1(xA, yA, zA); + + // WHEN + Vector3D_SSE v2 = v0 / v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f + << 1.0f + << 0.0f << 0.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -1.0f << 4.0f << -5.0f; + } + + void checkDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + + // WHEN + Vector3D_SSE v2 = v0 / factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f + << 1.0f + << 0.0f << -3.0f << 2.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f + << 5.0f + << -25.0f << 100.0f << -125.0f; + } + + void checkMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + + // GIVEN + Vector3D_SSE v0(xO, yO, zO); + + // WHEN + Vector3D_SSE v2 = v0 * factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + } + + void checkEquality() + { + { + // GIVEN + Vector3D_SSE v0; + Vector3D_SSE v1; + + // THEN + QVERIFY(v0 == v1); + } + { + // GIVEN + Vector3D_SSE v0(1.0f, 2.0f, -5.0f); + Vector3D_SSE v1(1.0f, 2.0f, -5.0f); + + // THEN + QVERIFY(v0 == v1); + } + } + + void checkInequality() + { + { + // GIVEN + Vector3D_SSE v0; + Vector3D_SSE v1; + + // THEN + QVERIFY(!(v0 != v1)); + } + { + // GIVEN + Vector3D_SSE v0(1.0f, 2.0f, -5.0f); + Vector3D_SSE v1(1.0f, 5.0f, -5.0f); + + // THEN + QVERIFY(v0 != v1); + } + } + + void checkToQVector3D_SSE() + { + { + // GIVEN + Vector3D_SSE v0; + + // WHEN + QVector3D v1 = v0.toQVector3D(); + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + } + { + // GIVEN + Vector3D_SSE v0(1.0f, 2.0f, -5.0f); + + // WHEN + QVector3D v1 = v0.toQVector3D(); + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + } + } + + void checkLengthSquared() + { + { + // GIVEN + Vector3D_SSE v0(10.0f, 10.0f, 10.0f); + + // THEN + QCOMPARE(v0.lengthSquared(), 300.0f); + } + { + // GIVEN + Vector3D_SSE v0(3.0f, 1.0f, 2.0f); + + // THEN + QCOMPARE(v0.lengthSquared(), 14.0f); + } + } + + void checkLength() + { + { + // GIVEN + Vector3D_SSE v0(3.0f, 0.0f, 0.0f); + + // THEN + QCOMPARE(v0.length(), 3.0f); + } + { + // GIVEN + Vector3D_SSE v0(0.0f, 10.0f, 0.0f); + + // THEN + QCOMPARE(v0.length(), 10.0f); + } + { + // GIVEN + Vector3D_SSE v0(0.0f, 0.0f, 9.0f); + + // THEN + QCOMPARE(v0.length(), 9.0f); + } + } + + void checkNormalize() + { + { + // GIVEN + Vector3D_SSE v0(10.0f, 0.0f, 0.0f); + + // WHEN + v0.normalize(); + + // THEN + QCOMPARE(v0, Vector3D_SSE(1.0f, 0.0f, 0.0f)); + } + { + // GIVEN + Vector3D_SSE v0(3.0f, 0.0f, 3.0f); + + // WHEN + v0.normalize(); + + // THEN + // (0.707107 == sqrt(2) / 2) + Vector3D_SSE v2(0.707107f, 0.0f, 0.707107f); + QCOMPARE(qFuzzyCompare(v0, v2), true); + } + } + + void checkNormalized() + { + + } + + void checkIsNull() + { + { + // GIVEN + Vector3D_SSE v0; + + // THEN + QVERIFY(v0.isNull()); + } + { + // GIVEN + Vector3D_SSE v0(1.0f, 1.0f, 1.0f); + + // THEN + QVERIFY(!v0.isNull()); + } + } +}; + +QTEST_APPLESS_MAIN(tst_Vector3D_SSE) + +#include "tst_vector3d_sse.moc" diff --git a/tests/auto/core/vector3d_sse/vector3d_sse.pro b/tests/auto/core/vector3d_sse/vector3d_sse.pro new file mode 100644 index 000000000..6afc4a863 --- /dev/null +++ b/tests/auto/core/vector3d_sse/vector3d_sse.pro @@ -0,0 +1,8 @@ +TARGET = tst_vector3d_sse +CONFIG += testcase simd +QT += testlib 3dcore 3dcore-private + +SOURCES += \ + tst_vector3d_sse.cpp + +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 diff --git a/tests/auto/core/vector4d_base/tst_vector4d_base.cpp b/tests/auto/core/vector4d_base/tst_vector4d_base.cpp new file mode 100644 index 000000000..e152625fe --- /dev/null +++ b/tests/auto/core/vector4d_base/tst_vector4d_base.cpp @@ -0,0 +1,785 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <Qt3DCore/private/vector4d_p.h> + +class tst_Vector4D_Base: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // GIVEN + QVector4D vec4; + + // THEN + QCOMPARE(vec4.x(), 0.0f); + QCOMPARE(vec4.y(), 0.0f); + QCOMPARE(vec4.z(), 0.0f); + QCOMPARE(vec4.w(), 0.0f); + } + + void checkExplicitConstruction() + { + // GIVEN + QVector4D vec4(427.0f, 454.0f, 383.0f, 350.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 454.0f); + QCOMPARE(vec4.z(), 383.0f); + QCOMPARE(vec4.w(), 350.0f); + } + + void checkSelfAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 1.0f << 5.0f << 8.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << 0.0f << 0.0f << 0.0f << 0.0f; + } + + void checkSelfAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo += QVector4D(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << -1.0f << -5.0f << -8.0f << 5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << -10.0f << 16.0f << -8.0f << 12.0f; + } + + void checkSelfSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo -= QVector4D(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 16.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -25.0f << -64.0f << 16.0f << 36.0f; + } + + void checkSelfMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo *= QVector4D(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 0.25f << -0.20f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -1.0f << -1.0f << 1.0f << 1.0f; + } + + void checkSelfDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo /= QVector4D(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << 0.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -1.0f << 4.0f << -5.0f << 2.0f; + } + + void checkSelfDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo /= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << -3.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -25.0f << 100.0f << -125.0f << 50.0f; + } + + void checkSelfMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D vo(xO, yO, zO, wO); + + // WHEN + vo *= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 1.0f << 5.0f << 8.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << 0.0f << 0.0f << 0.0f << 0.0f; + } + + void checkAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + QVector4D v1(xA, yA, zA, wA); + + // WHEN + QVector4D v2 = v0 + v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << -1.0f << -5.0f << -8.0f << 5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << -10.0f << 16.0f << -8.0f << 12.0f; + } + + void checkSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + QVector4D v1(xA, yA, zA, wA); + + // WHEN + QVector4D v2 = v0 - v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 16.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -25.0f << -64.0f << 16.0f << 36.0f; + } + + void checkMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + QVector4D v1(xA, yA, zA, wA); + + // WHEN + QVector4D v2 = v0 * v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 0.25f << -0.20f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -1.0f << -1.0f << 1.0f << 1.0f; + } + + void checkDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + QVector4D v1(xA, yA, zA, wA); + + // WHEN + QVector4D v2 = v0 / v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << 0.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -1.0f << 4.0f << -5.0f << 2.0f; + } + + void checkDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + + // WHEN + QVector4D v2 = v0 / factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << -3.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -25.0f << 100.0f << -125.0f << 50.0f; + } + + void checkMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + QVector4D v0(xO, yO, zO, wO); + + // WHEN + QVector4D v2 = v0 * factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkEquality() + { + { + // GIVEN + QVector4D v0; + QVector4D v1; + + // THEN + QVERIFY(v0 == v1); + } + { + // GIVEN + QVector4D v0(1.0f, 2.0f, -5.0f, 10.0f); + QVector4D v1(1.0f, 2.0f, -5.0f, 10.0f); + + // THEN + QVERIFY(v0 == v1); + } + } + + void checkInequality() + { + { + // GIVEN + QVector4D v0; + QVector4D v1; + + // THEN + QVERIFY(!(v0 != v1)); + } + { + // GIVEN + QVector4D v0(1.0f, 2.0f, -5.0f, 10.0f); + QVector4D v1(1.0f, 5.0f, -5.0f, 10.0f); + + // THEN + QVERIFY(v0 != v1); + } + } + + void checkToQQVector4D() + { + { + // GIVEN + QVector4D v0; + + // WHEN + QVector4D v1 = v0; + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + QCOMPARE(v0.w(), v1.w()); + } + { + // GIVEN + QVector4D v0(1.0f, 2.0f, -5.0f, 10.0f); + + // WHEN + QVector4D v1 = v0; + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + QCOMPARE(v0.w(), v1.w()); + } + } +}; + +QTEST_APPLESS_MAIN(tst_Vector4D_Base) + +#include "tst_vector4d_base.moc" diff --git a/tests/auto/core/vector4d_base/vector4d_base.pro b/tests/auto/core/vector4d_base/vector4d_base.pro new file mode 100644 index 000000000..9afaff092 --- /dev/null +++ b/tests/auto/core/vector4d_base/vector4d_base.pro @@ -0,0 +1,7 @@ +TARGET = tst_vector4d_base +CONFIG += testcase + +SOURCES += \ + tst_vector4d_base.cpp + +QT += testlib 3dcore 3dcore-private diff --git a/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp b/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp new file mode 100644 index 000000000..e7b58c8cf --- /dev/null +++ b/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp @@ -0,0 +1,830 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <Qt3DCore/private/vector4d_sse_p.h> +#include <Qt3DCore/qt3dcore-config.h> + +using namespace Qt3DCore; + +class tst_Vector4D_SSE: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void defaultConstruction() + { + // GIVEN + Vector4D_SSE vec4; + + // THEN + QCOMPARE(vec4.x(), 0.0f); + QCOMPARE(vec4.y(), 0.0f); + QCOMPARE(vec4.z(), 0.0f); + QCOMPARE(vec4.w(), 0.0f); + } + + void checkExplicitConstruction() + { + // GIVEN + Vector4D_SSE vec4(427.0f, 454.0f, 383.0f, 350.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 454.0f); + QCOMPARE(vec4.z(), 383.0f); + QCOMPARE(vec4.w(), 350.0f); + } + + void checkSetters() + { + // GIVEN + Vector4D_SSE vec4; + + // WHEN + vec4.setX(427.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 0.0f); + QCOMPARE(vec4.z(), 0.0f); + QCOMPARE(vec4.w(), 0.0f); + + // WHEN + vec4.setY(454.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 454.0f); + QCOMPARE(vec4.z(), 0.0f); + QCOMPARE(vec4.w(), 0.0f); + + // WHEN + vec4.setZ(383.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 454.0f); + QCOMPARE(vec4.z(), 383.0f); + QCOMPARE(vec4.w(), 0.0f); + + // WHEN + vec4.setW(350.0f); + + // THEN + QCOMPARE(vec4.x(), 427.0f); + QCOMPARE(vec4.y(), 454.0f); + QCOMPARE(vec4.z(), 383.0f); + QCOMPARE(vec4.w(), 350.0f); + } + + void checkSelfAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 1.0f << 5.0f << 8.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << 0.0f << 0.0f << 0.0f << 0.0f; + } + + void checkSelfAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo += Vector4D_SSE(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << -1.0f << -5.0f << -8.0f << 5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << -10.0f << 16.0f << -8.0f << 12.0f; + } + + void checkSelfSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo -= Vector4D_SSE(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 16.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -25.0f << -64.0f << 16.0f << 36.0f; + } + + void checkSelfMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo *= Vector4D_SSE(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 0.25f << -0.20f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -1.0f << -1.0f << 1.0f << 1.0f; + } + + void checkSelfDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo /= Vector4D_SSE(xA, yA, zA, wA); + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << 0.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -1.0f << 4.0f << -5.0f << 2.0f; + } + + void checkSelfDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo /= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkSelfMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << -3.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -25.0f << 100.0f << -125.0f << 50.0f; + } + + void checkSelfMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE vo(xO, yO, zO, wO); + + // WHEN + vo *= factor; + + // THEN + QCOMPARE(vo.x(), xR); + QCOMPARE(vo.y(), yR); + QCOMPARE(vo.z(), zR); + QCOMPARE(vo.w(), wR); + } + + void checkAddition_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 1.0f << 5.0f << 8.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << 0.0f << 0.0f << 0.0f << 0.0f; + } + + void checkAddition() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + Vector4D_SSE v1(xA, yA, zA, wA); + + // WHEN + Vector4D_SSE v2 = v0 + v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkSubstraction_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 0.0f << 0.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << -1.0f << -5.0f << -8.0f << 5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << -4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << -6.0f + << -10.0f << 16.0f << -8.0f << 12.0f; + } + + void checkSubstraction() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + Vector4D_SSE v1(xA, yA, zA, wA); + + // WHEN + Vector4D_SSE v2 = v0 - v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkMultiplication_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 16.0f << -5.0f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -25.0f << -64.0f << 16.0f << 36.0f; + } + + void checkMultiplication() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + Vector4D_SSE v1(xA, yA, zA, wA); + + // WHEN + Vector4D_SSE v2 = v0 * v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkDivision_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("xA"); + QTest::addColumn<float>("yA"); + QTest::addColumn<float>("zA"); + QTest::addColumn<float>("wA"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f << 5.0f << 8.0f << -5.0f + << 0.0f << 0.0f << 0.25f << -0.20f; + + QTest::newRow("sample_2") << -5.0f << 8.0f << 4.0f << 6.0f + << 5.0f << -8.0f << 4.0f << 6.0f + << -1.0f << -1.0f << 1.0f << 1.0f; + } + + void checkDivision() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, xA); + QFETCH(float, yA); + QFETCH(float, zA); + QFETCH(float, wA); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + Vector4D_SSE v1(xA, yA, zA, wA); + + // WHEN + Vector4D_SSE v2 = v0 / v1; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkDivisionFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << 0.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << 0.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -1.0f << 4.0f << -5.0f << 2.0f; + } + + void checkDivisionFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + + // WHEN + Vector4D_SSE v2 = v0 / factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkMultiplicationFactor_data() + { + QTest::addColumn<float>("xO"); + QTest::addColumn<float>("yO"); + QTest::addColumn<float>("zO"); + QTest::addColumn<float>("wO"); + + QTest::addColumn<float>("factor"); + + QTest::addColumn<float>("xR"); + QTest::addColumn<float>("yR"); + QTest::addColumn<float>("zR"); + QTest::addColumn<float>("wR"); + + QTest::newRow("sample_1") << 0.0f << -3.0f << 2.0f << 1.0f + << 1.0f + << 0.0f << -3.0f << 2.0f << 1.0f; + + QTest::newRow("sample_2") << -5.0f << 20.0f << -25.0f << 10.0f + << 5.0f + << -25.0f << 100.0f << -125.0f << 50.0f; + } + + void checkMultiplicationFactor() + { + QFETCH(float, xO); + QFETCH(float, yO); + QFETCH(float, zO); + QFETCH(float, wO); + + QFETCH(float, factor); + + QFETCH(float, xR); + QFETCH(float, yR); + QFETCH(float, zR); + QFETCH(float, wR); + + // GIVEN + Vector4D_SSE v0(xO, yO, zO, wO); + + // WHEN + Vector4D_SSE v2 = v0 * factor; + + // THEN + QCOMPARE(v2.x(), xR); + QCOMPARE(v2.y(), yR); + QCOMPARE(v2.z(), zR); + QCOMPARE(v2.w(), wR); + } + + void checkEquality() + { + { + // GIVEN + Vector4D_SSE v0; + Vector4D_SSE v1; + + // THEN + QVERIFY(v0 == v1); + } + { + // GIVEN + Vector4D_SSE v0(1.0f, 2.0f, -5.0f, 10.0f); + Vector4D_SSE v1(1.0f, 2.0f, -5.0f, 10.0f); + + // THEN + QVERIFY(v0 == v1); + } + } + + void checkInequality() + { + { + // GIVEN + Vector4D_SSE v0; + Vector4D_SSE v1; + + // THEN + QVERIFY(!(v0 != v1)); + } + { + // GIVEN + Vector4D_SSE v0(1.0f, 2.0f, -5.0f, 10.0f); + Vector4D_SSE v1(1.0f, 5.0f, -5.0f, 10.0f); + + // THEN + QVERIFY(v0 != v1); + } + } + + void checkToQVector4D_SSE() + { + { + // GIVEN + Vector4D_SSE v0; + + // WHEN + QVector4D v1 = v0.toQVector4D(); + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + QCOMPARE(v0.w(), v1.w()); + } + { + // GIVEN + Vector4D_SSE v0(1.0f, 2.0f, -5.0f, 10.0f); + + // WHEN + QVector4D v1 = v0.toQVector4D(); + + // THEN + QCOMPARE(v0.x(), v1.x()); + QCOMPARE(v0.y(), v1.y()); + QCOMPARE(v0.z(), v1.z()); + QCOMPARE(v0.w(), v1.w()); + } + } +}; + +QTEST_APPLESS_MAIN(tst_Vector4D_SSE) + +#include "tst_vector4d_sse.moc" diff --git a/tests/auto/core/vector4d_sse/vector4d_sse.pro b/tests/auto/core/vector4d_sse/vector4d_sse.pro new file mode 100644 index 000000000..76c425548 --- /dev/null +++ b/tests/auto/core/vector4d_sse/vector4d_sse.pro @@ -0,0 +1,9 @@ +TARGET = tst_vector4d_sse +CONFIG += testcase simd + +SOURCES += \ + tst_vector4d_sse.cpp + +QT += testlib 3dcore 3dcore-private + +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 diff --git a/tests/auto/quick3d/3dcore/3dcore.qml b/tests/auto/quick3d/3dcore/3dcore.qml index df9dd429b..72514591c 100644 --- a/tests/auto/quick3d/3dcore/3dcore.qml +++ b/tests/auto/quick3d/3dcore/3dcore.qml @@ -29,6 +29,7 @@ import Qt3D.Core 2.0 as QQ3Core20 import Qt3D.Core 2.9 as QQ3Core29 +import Qt3D.Core 2.10 as QQ3Core210 import QtQuick 2.0 Item { @@ -42,4 +43,8 @@ Item { QQ3Core20.QuaternionAnimation {} //Qt3DCore::Quick::QQuaternionAnimation QQ3Core29.Entity {} //Qt3DCore::QEntity, Qt3DCore::Quick::Quick3DEntity + + QQ3Core210.Armature {} + QQ3Core210.SkeletonLoader {} + QQ3Core210.Joint {} } diff --git a/tests/auto/quick3d/3drender/3drender.qml b/tests/auto/quick3d/3drender/3drender.qml index 92461fe8d..112031282 100644 --- a/tests/auto/quick3d/3drender/3drender.qml +++ b/tests/auto/quick3d/3drender/3drender.qml @@ -29,6 +29,7 @@ import Qt3D.Render 2.0 as QQ3Render20 import Qt3D.Render 2.1 as QQ3Render21 +import Qt3D.Render 2.10 as QQ3Render210 import QtQuick 2.0 Item { @@ -120,6 +121,7 @@ Item { QQ3Render20.DispatchCompute {} //Qt3DRender::QDispatchCompute QQ3Render21.RenderCapture {} //Qt3DRender::QRenderCapture //QQ3Render21.RenderCaptureReply // (uncreatable) Qt3DRender::QRenderCaptureReply + QQ3Render210.ProximityFilter {} //Q3DRender::QProximityFilter // RenderTarget QQ3Render20.RenderTargetOutput {} //Qt3DRender::QRenderTargetOutput diff --git a/tests/auto/render/armature/armature.pro b/tests/auto/render/armature/armature.pro new file mode 100644 index 000000000..fc8d69eaa --- /dev/null +++ b/tests/auto/render/armature/armature.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_armature + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_armature.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/armature/tst_armature.cpp b/tests/auto/render/armature/tst_armature.cpp new file mode 100644 index 000000000..2c481db7a --- /dev/null +++ b/tests/auto/render/armature/tst_armature.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/armature_p.h> +#include <Qt3DCore/qarmature.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +class tst_Armature: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Armature backendArmature; + QArmature armature; + auto skeleton = new QSkeleton; + + armature.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&armature, &backendArmature); + + // THEN + QCOMPARE(backendArmature.peerId(), armature.id()); + QCOMPARE(backendArmature.isEnabled(), armature.isEnabled()); + QCOMPARE(backendArmature.skeletonId(), skeleton->id()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Armature backendArmature; + + // THEN + QVERIFY(backendArmature.peerId().isNull()); + QCOMPARE(backendArmature.isEnabled(), false); + QCOMPARE(backendArmature.skeletonId(), Qt3DCore::QNodeId()); + + // GIVEN + QArmature armature; + auto skeleton = new QSkeleton(); + armature.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&armature, &backendArmature); + backendArmature.cleanup(); + + // THEN + QCOMPARE(backendArmature.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendArmature.isEnabled(), false); + } + + void checkPropertyChanges() + { + // GIVEN + Armature backendArmature; + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendArmature.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendArmature.isEnabled(), true); + + // WHEN + auto newSkeleton = new QSkeleton(); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("skeleton"); + updateChange->setValue(QVariant::fromValue(newSkeleton->id())); + backendArmature.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendArmature.skeletonId(), newSkeleton->id()); + } +}; + +QTEST_APPLESS_MAIN(tst_Armature) + +#include "tst_armature.moc" diff --git a/tests/auto/render/blitframebuffer/blitframebuffer.pro b/tests/auto/render/blitframebuffer/blitframebuffer.pro new file mode 100644 index 000000000..39531ae9a --- /dev/null +++ b/tests/auto/render/blitframebuffer/blitframebuffer.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_blitframebuffer + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_blitframebuffer.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp new file mode 100644 index 000000000..6c70b0e95 --- /dev/null +++ b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qblitframebuffer.h> +#include <Qt3DRender/private/qblitframebuffer_p.h> +#include <Qt3DRender/private/blitframebuffer_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_BlitFramebuffer : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + + // THEN + QCOMPARE(backendBlitFramebuffer.nodeType(), Qt3DRender::Render::FrameGraphNode::BlitFramebuffer); + QCOMPARE(backendBlitFramebuffer.isEnabled(), false); + QVERIFY(backendBlitFramebuffer.peerId().isNull()); + QVERIFY(backendBlitFramebuffer.sourceRenderTargetId().isNull()); + QVERIFY(backendBlitFramebuffer.destinationRenderTargetId().isNull()); + QCOMPARE(backendBlitFramebuffer.sourceRect(), QRect()); + QCOMPARE(backendBlitFramebuffer.destinationRect(), QRect()); + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(backendBlitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Linear); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DRender::QRenderTarget sourceTarget; + Qt3DRender::QRenderTarget destinationTarget; + Qt3DRender::QBlitFramebuffer blitFramebuffer; + blitFramebuffer.setSource(&sourceTarget); + blitFramebuffer.setDestination(&destinationTarget); + blitFramebuffer.setSourceRect(QRect(0,0,1,1)); + blitFramebuffer.setDestinationRect(QRect(0,0,1,1)); + blitFramebuffer.setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + blitFramebuffer.setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + blitFramebuffer.setInterpolationMethod(Qt3DRender::QBlitFramebuffer::Nearest); + + { + // WHEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer); + + // THEN + QCOMPARE(backendBlitFramebuffer.isEnabled(), true); + QCOMPARE(backendBlitFramebuffer.peerId(), blitFramebuffer.id()); + QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), sourceTarget.id()); + QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), destinationTarget.id()); + QCOMPARE(backendBlitFramebuffer.sourceRect(), QRect(0,0,1,1)); + QCOMPARE(backendBlitFramebuffer.destinationRect(), QRect(0,0,1,1)); + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(backendBlitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Nearest); + } + { + // WHEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + blitFramebuffer.setEnabled(false); + simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer); + + // THEN + QCOMPARE(backendBlitFramebuffer.peerId(), blitFramebuffer.id()); + QCOMPARE(backendBlitFramebuffer.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + TestRenderer renderer; + backendBlitFramebuffer.setRenderer(&renderer); + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.isEnabled(), newValue); + } + { + // WHEN + const Qt3DRender::QRenderTarget sourceRenderTarget; + const Qt3DCore::QNodeId newValue = sourceRenderTarget.id(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceRenderTarget"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), newValue); + } + { + // WHEN + const Qt3DRender::QRenderTarget destinationRenderTarget; + const Qt3DCore::QNodeId newValue = destinationRenderTarget.id(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationRenderTarget"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), newValue); + } + { + // WHEN + const auto newValue = QRect(0,0,1,1); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceRect"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceRect(), newValue); + } + { + // WHEN + const auto newValue = QRect(0,0,1,1); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationRect"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationRect(), newValue); + } + { + // WHEN + const auto newValue = Qt3DRender::QRenderTargetOutput::Color1; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceAttachmentPoint"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), newValue); + } + { + // WHEN + const auto newValue = Qt3DRender::QRenderTargetOutput::Color1; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationAttachmentPoint"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), newValue); + } + } + +}; + +QTEST_MAIN(tst_BlitFramebuffer) + +#include "tst_blitframebuffer.moc" diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 6fa7960fe..f9a54c8bf 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -73,18 +73,20 @@ private Q_SLOTS: Qt3DRender::Render::Buffer renderBuffer; Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; + buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy); buffer.setData(QByteArrayLiteral("Corvette")); buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(883))); // WHEN + renderBuffer.setRenderer(&renderer); renderBuffer.setManager(&bufferManager); simulateInitialization(&buffer, &renderBuffer); // THEN QCOMPARE(renderBuffer.peerId(), buffer.id()); QCOMPARE(renderBuffer.isDirty(), true); - QCOMPARE(renderBuffer.type(), buffer.type()); QCOMPARE(renderBuffer.usage(), buffer.usage()); QCOMPARE(renderBuffer.data(), buffer.data()); QCOMPARE(renderBuffer.dataGenerator(), buffer.dataGenerator()); @@ -102,7 +104,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.peerId().isNull()); @@ -110,7 +111,7 @@ private Q_SLOTS: QVERIFY(renderBuffer.pendingBufferUpdates().empty()); // GIVEN - Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); + Qt3DRender::QBuffer buffer; buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy); buffer.setData(QByteArrayLiteral("C7")); buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73))); @@ -129,7 +130,6 @@ private Q_SLOTS: renderBuffer.sceneChangeEvent(updateChange); // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy); QCOMPARE(renderBuffer.isDirty(), true); QCOMPARE(renderBuffer.data(), QByteArrayLiteral("C7")); @@ -141,7 +141,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.dataGenerator().isNull()); @@ -156,27 +155,14 @@ private Q_SLOTS: renderBuffer.setRenderer(&renderer); // THEN - QVERIFY(renderBuffer.type() != Qt3DRender::QBuffer::IndexBuffer); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.usage() != Qt3DRender::QBuffer::DynamicRead); QVERIFY(!renderBuffer.isDirty()); + QVERIFY(!(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty)); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::IndexBuffer)); - updateChange->setPropertyName("type"); - renderBuffer.sceneChangeEvent(updateChange); - - // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); - QVERIFY(renderer.dirtyBits() != 0); - QVERIFY(renderBuffer.isDirty()); - - renderBuffer.unsetDirty(); - QVERIFY(!renderBuffer.isDirty()); - - // WHEN - updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::DynamicRead)); updateChange->setPropertyName("usage"); renderBuffer.sceneChangeEvent(updateChange); @@ -185,6 +171,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicRead); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -201,6 +190,10 @@ private Q_SLOTS: QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1); renderBuffer.pendingBufferUpdates().clear(); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -215,6 +208,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.dataGenerator(), functor); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -228,6 +224,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.isSyncData(), true); QVERIFY(!renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + // WHEN TestArbiter arbiter; Qt3DCore::QBackendNodePrivate::get(&renderBuffer)->setArbiter(&arbiter); @@ -258,6 +257,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, 2); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); } @@ -268,8 +270,10 @@ private Q_SLOTS: Qt3DRender::Render::Buffer renderBuffer; Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; // WHEN + renderBuffer.setRenderer(&renderer); renderBuffer.setManager(&bufferManager); simulateInitialization(&buffer, &renderBuffer); @@ -285,6 +289,27 @@ private Q_SLOTS: QVERIFY(buffers.first() == renderBuffer.peerId()); QVERIFY(bufferManager.takeBuffersToRelease().empty()); } + + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::Buffer renderBuffer; + Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); + Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; + + renderBuffer.setRenderer(&renderer); + renderBuffer.setManager(&bufferManager); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&buffer, &renderBuffer); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::BuffersDirty); + } }; diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 74f529fa0..031ca214b 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -60,6 +60,7 @@ public: QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE { return QVector<Qt3DCore::QAspectJobPtr>(); } Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr syncTextureLoadingJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } + Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Qt3DRender::Render::Entity *root) Q_DECL_OVERRIDE { Q_UNUSED(factory); Q_UNUSED(root); } Qt3DRender::Render::Entity *sceneRoot() const Q_DECL_OVERRIDE { return nullptr; } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const Q_DECL_OVERRIDE { return nullptr; } diff --git a/tests/auto/render/ddstextures/data/16x16-etc1.pkm b/tests/auto/render/ddstextures/data/16x16-etc1.pkm Binary files differnew file mode 100644 index 000000000..62ae2a11f --- /dev/null +++ b/tests/auto/render/ddstextures/data/16x16-etc1.pkm diff --git a/tests/auto/render/ddstextures/data/16x16-etc2.pkm b/tests/auto/render/ddstextures/data/16x16-etc2.pkm Binary files differnew file mode 100644 index 000000000..be391113e --- /dev/null +++ b/tests/auto/render/ddstextures/data/16x16-etc2.pkm diff --git a/tests/auto/render/ddstextures/ddstextures.pro b/tests/auto/render/ddstextures/ddstextures.pro index e81fd80d8..62456561f 100644 --- a/tests/auto/render/ddstextures/ddstextures.pro +++ b/tests/auto/render/ddstextures/ddstextures.pro @@ -30,7 +30,9 @@ OTHER_FILES = \ data/16x16x1-6-lumi.dds \ data/16x16x1-6-lumi-nomips.dds \ data/16x16x1-6-rgb.dds \ - data/16x16x1-6-rgb-nomips.dds + data/16x16x1-6-rgb-nomips.dds \ + data/16x16-etc1.pkm \ + data/16x16-etc2.pkm TESTDATA = data/* diff --git a/tests/auto/render/ddstextures/tst_ddstextures.cpp b/tests/auto/render/ddstextures/tst_ddstextures.cpp index 4d9a1fb32..1f33f20e2 100644 --- a/tests/auto/render/ddstextures/tst_ddstextures.cpp +++ b/tests/auto/render/ddstextures/tst_ddstextures.cpp @@ -73,6 +73,8 @@ void tst_DdsTextures::ddsImageData() { "data/16x16x1-6-bc1-dx10.dds", 16, 16, 1, 6, 5, QOpenGLTexture::RGBA_DXT1 }, { "data/16x16x1-6-bc3-nomips-dx10.dds", 16, 16, 1, 6, 1, QOpenGLTexture::RGBA_DXT5 }, { "data/16x16x1-6-bc3-dx10.dds", 16, 16, 1, 6, 5, QOpenGLTexture::RGBA_DXT5 }, + { "data/16x16-etc1.pkm", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC1 }, + { "data/16x16-etc2.pkm", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC2 }, }; for (unsigned i = 0; i < sizeof(textures)/sizeof(*textures); i++) { diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index d1a222c92..6ad958451 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/QGeometryRenderer> #include <Qt3DRender/QObjectPicker> #include <Qt3DRender/QComputeCommand> +#include <Qt3DCore/QArmature> #include "testrenderer.h" @@ -62,6 +63,7 @@ QNodeId materialUuid(Entity *entity) { return entity->componentUuid<Material>(); QNodeId geometryRendererUuid(Entity *entity) { return entity->componentUuid<GeometryRenderer>(); } QNodeId objectPickerUuid(Entity *entity) { return entity->componentUuid<ObjectPicker>(); } QNodeId computeJobUuid(Entity *entity) { return entity->componentUuid<ComputeCommand>(); } +QNodeId armatureUuid(Entity *entity) { return entity->componentUuid<Armature>(); } QVector<QNodeId> layersUuid(Entity *entity) { return entity->componentsUuid<Layer>(); } QVector<QNodeId> shadersUuid(Entity *entity) { return entity->componentsUuid<ShaderData>(); } @@ -89,7 +91,8 @@ private slots: << new QLayer << new QShaderData << new QComputeCommand - << new QEnvironmentLight; + << new QEnvironmentLight + << new QArmature; QTest::newRow("all components") << components; } @@ -116,8 +119,10 @@ private slots: QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(entity.componentUuid<Armature>().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); + QVERIFY(entity.layerIds().isEmpty()); // WHEN Q_FOREACH (QComponent *component, components) { @@ -144,10 +149,13 @@ private slots: QVERIFY(!entity.componentsUuid<Layer>().isEmpty()); QVERIFY(!entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(!entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(!entity.componentUuid<Armature>().isNull()); QVERIFY(entity.isBoundingVolumeDirty()); QVERIFY(!entity.childrenHandles().isEmpty()); + QVERIFY(!entity.layerIds().isEmpty()); QVERIFY(renderer.dirtyBits() != 0); - bool containsAll = entity.containsComponentsOfType<Transform, CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand>(); + bool containsAll = entity.containsComponentsOfType<Transform, + CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand, Armature>(); QVERIFY(containsAll); // WHEN @@ -163,9 +171,12 @@ private slots: QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(entity.componentUuid<Armature>().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); - containsAll = entity.containsComponentsOfType<Transform, CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand>(); + QVERIFY(entity.layerIds().isEmpty()); + containsAll = entity.containsComponentsOfType<Transform, + CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand, Armature>(); QVERIFY(!containsAll); } @@ -191,6 +202,9 @@ private slots: component = new QComputeCommand; QTest::newRow("computeJob") << component << reinterpret_cast<void*>(computeJobUuid); + + component = new QArmature; + QTest::newRow("armature") << component << reinterpret_cast<void*>(armatureUuid); } void shouldHandleSingleComponentEvents() diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST index c9313fd62..22cb59fab 100644 --- a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST +++ b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST @@ -1,4 +1,5 @@ -[checkRunRendererNotRunning] -windows -[checkRunRendererRunning] +#[checkRunRendererNotRunning] +#windows +#[checkRunRendererRunning] +#QTBUG-64271 windows diff --git a/tests/auto/render/geometry/tst_geometry.cpp b/tests/auto/render/geometry/tst_geometry.cpp index 6a8746f47..958edfd09 100644 --- a/tests/auto/render/geometry/tst_geometry.cpp +++ b/tests/auto/render/geometry/tst_geometry.cpp @@ -54,6 +54,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::Geometry renderGeometry; + TestRenderer renderer; Qt3DRender::QGeometry geometry; Qt3DRender::QAttribute attr1; @@ -66,6 +67,7 @@ private Q_SLOTS: geometry.addAttribute(&attr3); geometry.addAttribute(&attr4); geometry.setBoundingVolumePositionAttribute(&attr1); + renderGeometry.setRenderer(&renderer); // WHEN simulateInitialization(&geometry, &renderGeometry); @@ -80,10 +82,31 @@ private Q_SLOTS: QCOMPARE(geometry.attributes().at(i)->id(), renderGeometry.attributes().at(i)); } + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::Geometry renderGeometry; + Qt3DRender::QGeometry geometry; + TestRenderer renderer; + + renderGeometry.setRenderer(&renderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&geometry, &renderGeometry); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty); + } + void checkInitialAndCleanedUpState() { // GIVEN + TestRenderer renderer; Qt3DRender::Render::Geometry renderGeometry; + renderGeometry.setRenderer(&renderer); // THEN QCOMPARE(renderGeometry.isDirty(), false); @@ -131,6 +154,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.attributes().count(), 1); QVERIFY(renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometry.unsetDirty(); QVERIFY(!renderGeometry.isDirty()); @@ -143,6 +168,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.attributes().count(), 0); QVERIFY(renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometry.unsetDirty(); QVERIFY(!renderGeometry.isDirty()); @@ -157,6 +184,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.boundingPositionAttribute(), boundingAttrId); QVERIFY(!renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } }; diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp index d9ed000ab..af074def0 100644 --- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp +++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp @@ -85,11 +85,13 @@ private Q_SLOTS: Qt3DRender::QGeometry geometry; Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200)); Qt3DRender::Render::GeometryRendererManager geometryRendererManager; + TestRenderer renderer; geometryRenderer.setInstanceCount(1584); geometryRenderer.setVertexCount(1609); geometryRenderer.setIndexOffset(750); geometryRenderer.setFirstInstance(883); + geometryRenderer.setIndexBufferByteOffset(96); geometryRenderer.setRestartIndexValue(65536); geometryRenderer.setPrimitiveRestartEnabled(true); geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches); @@ -98,6 +100,7 @@ private Q_SLOTS: geometryRenderer.setEnabled(false); // WHEN + renderGeometryRenderer.setRenderer(&renderer); renderGeometryRenderer.setManager(&geometryRendererManager); simulateInitialization(&geometryRenderer, &renderGeometryRenderer); @@ -108,6 +111,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), geometryRenderer.vertexCount()); QCOMPARE(renderGeometryRenderer.indexOffset(), geometryRenderer.indexOffset()); QCOMPARE(renderGeometryRenderer.firstInstance(), geometryRenderer.firstInstance()); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), geometryRenderer.indexBufferByteOffset()); QCOMPARE(renderGeometryRenderer.restartIndexValue(), geometryRenderer.restartIndexValue()); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), geometryRenderer.primitiveRestartEnabled()); QCOMPARE(renderGeometryRenderer.primitiveType(), geometryRenderer.primitiveType()); @@ -131,6 +135,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 0); QCOMPARE(renderGeometryRenderer.indexOffset(), 0); QCOMPARE(renderGeometryRenderer.firstInstance(), 0); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0); QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false); QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles); @@ -141,12 +146,13 @@ private Q_SLOTS: Qt3DRender::QGeometryRenderer geometryRenderer; Qt3DRender::QGeometry geometry; Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200)); - + TestRenderer renderer; geometryRenderer.setInstanceCount(454); geometryRenderer.setVertexCount(350); geometryRenderer.setIndexOffset(427); geometryRenderer.setFirstInstance(383); + geometryRenderer.setIndexBufferByteOffset(96); geometryRenderer.setRestartIndexValue(555); geometryRenderer.setPrimitiveRestartEnabled(true); geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches); @@ -155,6 +161,7 @@ private Q_SLOTS: geometryRenderer.setEnabled(true); // WHEN + renderGeometryRenderer.setRenderer(&renderer); renderGeometryRenderer.setManager(&geometryRendererManager); simulateInitialization(&geometryRenderer, &renderGeometryRenderer); renderGeometryRenderer.cleanup(); @@ -166,6 +173,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 0); QCOMPARE(renderGeometryRenderer.indexOffset(), 0); QCOMPARE(renderGeometryRenderer.firstInstance(), 0); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0); QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false); QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles); @@ -191,7 +199,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometryRenderer.instanceCount(), 2); QVERIFY(renderGeometryRenderer.isDirty()); - QVERIFY(renderer.dirtyBits() != 0); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -206,6 +215,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 56); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -219,6 +231,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.indexOffset(), 65); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -232,6 +247,25 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.firstInstance(), 82); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + renderGeometryRenderer.unsetDirty(); + QVERIFY(!renderGeometryRenderer.isDirty()); + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("indexBufferByteOffset"); + updateChange->setValue(96); + renderGeometryRenderer.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 96); + QVERIFY(renderGeometryRenderer.isDirty()); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -245,6 +279,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.restartIndexValue(), 46); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -258,6 +295,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), true); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -271,6 +311,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::LineLoop); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -285,9 +328,23 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryFactory(), factory); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); + // WHEN we set an identical factory again + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("geometryFactory"); + Qt3DRender::QGeometryFactoryPtr factory2(new TestFactory(1450)); + updateChange->setValue(QVariant::fromValue(factory2)); + renderGeometryRenderer.sceneChangeEvent(updateChange); + + // THEN not dirty and still uses original factory + QCOMPARE(renderGeometryRenderer.geometryFactory(), factory); + QVERIFY(!renderGeometryRenderer.isDirty()); + // WHEN DummyGeometry geometry; const Qt3DCore::QNodeId geometryId = geometry.id(); @@ -300,6 +357,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryId(), geometryId); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -313,6 +373,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryId(), Qt3DCore::QNodeId()); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -326,6 +389,27 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.isEnabled(), true); QVERIFY(!renderGeometryRenderer.isDirty()); } + + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::GeometryRendererManager geometryRendererManager; + Qt3DRender::Render::GeometryRenderer renderGeometryRenderer; + Qt3DRender::QGeometryRenderer geometryRenderer; + TestRenderer renderer; + + renderGeometryRenderer.setRenderer(&renderer); + renderGeometryRenderer.setManager(&geometryRendererManager); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&geometryRenderer, &renderGeometryRenderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty); + } }; QTEST_APPLESS_MAIN(tst_RenderGeometryRenderer) diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp index afd56e9bd..584b675ee 100644 --- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp +++ b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp @@ -33,8 +33,10 @@ #include <Qt3DRender/private/attachmentpack_p.h> #include <QtOpenGLExtensions/QOpenGLExtensions> #include <QOpenGLContext> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_2_0> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #ifndef QT_OPENGL_ES_2 @@ -612,6 +614,33 @@ private Q_SLOTS: // Not supported by GL2 } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1019,6 +1048,51 @@ private Q_SLOTS: // Not available in 3.2 } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -1438,6 +1512,18 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void readBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp index 1414d13b0..648eaaddb 100644 --- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp +++ b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl3_2_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_3_2_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) @@ -139,6 +141,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 150 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "uniform ColorArray\n" \ "{\n" \ @@ -146,7 +149,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -823,6 +826,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1318,6 +1350,61 @@ private Q_SLOTS: // Not available in 3.2 } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2028,6 +2115,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp index eea0e9f14..06a3c41cd 100644 --- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp +++ b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl3_3_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_3_3_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) @@ -138,6 +140,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 330 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "uniform ColorArray\n" \ "{\n" \ @@ -145,7 +148,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -922,6 +925,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1417,6 +1449,61 @@ private Q_SLOTS: QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2128,6 +2215,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp index 84d261659..5a96cf116 100644 --- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl4_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_4_3_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_4_3) @@ -60,11 +62,12 @@ const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( "layout(location = 1) in vec3 vertexPosition;\n" \ "layout(location = 2) in vec2 vertexTexCoord;\n" \ "layout(location = 3) in int vertexColorIndex;\n" \ + "layout(location = 4) in double vertexTexCoordScale;\n" \ "out vec2 texCoord;\n" \ "flat out int colorIndex;\n" \ "void main()\n" \ "{\n" \ - " texCoord = vertexTexCoord;\n" \ + " texCoord = vec2(vertexTexCoordScale * vertexTexCoord);\n" \ " colorIndex = vertexColorIndex;\n" \ " gl_Position = vec4(vertexPosition, 1.0);\n" \ "}\n"); @@ -139,6 +142,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 430 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "layout(binding = 2, std140) uniform ColorArray\n" \ "{\n" \ @@ -146,7 +150,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -1020,6 +1024,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1507,6 +1540,71 @@ private Q_SLOTS: QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + GLint texCoordScaleLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoordScale"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + QOpenGLBuffer scaleBuffer(QOpenGLBuffer::VertexBuffer); + scaleBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + scaleBuffer.create(); + scaleBuffer.allocate(vertexCount * sizeof(double)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + scaleBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_DOUBLE, texCoordScaleLocation, 1, GL_DOUBLE, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2196,6 +2294,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/joint/joint.pro b/tests/auto/render/joint/joint.pro new file mode 100644 index 000000000..9428ab5fd --- /dev/null +++ b/tests/auto/render/joint/joint.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_joint + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_joint.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/joint/tst_joint.cpp b/tests/auto/render/joint/tst_joint.cpp new file mode 100644 index 000000000..13aa915d2 --- /dev/null +++ b/tests/auto/render/joint/tst_joint.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/joint_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> +#include <Qt3DCore/qpropertynodeaddedchange.h> +#include <Qt3DCore/qpropertynoderemovedchange.h> +#include <QtGui/qmatrix4x4.h> +#include <QtGui/qvector3d.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> +#include <testrenderer.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +class tst_Joint : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + QJoint joint; + + joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); + joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); + joint.setRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f)); + QMatrix4x4 inverseBind; + inverseBind.rotate(-45.0f, 1.0f, 0.0, 0.0f); + joint.setInverseBindMatrix(inverseBind); + + QVector<QJoint *> childJoints; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + joint.addChildJoint(childJoint); + childJoints.push_back(childJoint); + } + + // WHEN + simulateInitialization(&joint, &backendJoint); + + // THEN + QCOMPARE(backendJoint.peerId(), joint.id()); + QCOMPARE(backendJoint.isEnabled(), joint.isEnabled()); + QCOMPARE(backendJoint.translation(), joint.translation()); + QCOMPARE(backendJoint.rotation(), joint.rotation()); + QCOMPARE(backendJoint.scale(), joint.scale()); + QCOMPARE(backendJoint.inverseBindMatrix(), joint.inverseBindMatrix()); + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + + // THEN + QVERIFY(backendJoint.peerId().isNull()); + QCOMPARE(backendJoint.isEnabled(), false); + QCOMPARE(backendJoint.translation(), QVector3D()); + QCOMPARE(backendJoint.rotation(), QQuaternion()); + QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); + QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); + QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); + + // GIVEN + QJoint joint; + joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); + joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); + joint.setRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f)); + QMatrix4x4 inverseBind; + inverseBind.rotate(-45.0f, 1.0f, 0.0, 0.0f); + joint.setInverseBindMatrix(inverseBind); + + QVector<QJoint *> childJoints; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + joint.addChildJoint(childJoint); + childJoints.push_back(childJoint); + } + + // WHEN + simulateInitialization(&joint, &backendJoint); + backendJoint.cleanup(); + + // THEN + QCOMPARE(backendJoint.isEnabled(), false); + QCOMPARE(backendJoint.translation(), QVector3D()); + QCOMPARE(backendJoint.rotation(), QQuaternion()); + QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); + QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); + QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); + } + + void checkPropertyChanges() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.isEnabled(), true); + + // WHEN + const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("translation"); + updateChange->setValue(newTranslation); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.translation(), newTranslation); + + // WHEN + const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("rotation"); + updateChange->setValue(newRotation); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.rotation(), newRotation); + + // WHEN + const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("scale"); + updateChange->setValue(newScale); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.scale(), newScale); + + // WHEN + QMatrix4x4 newInverseBind; + newInverseBind.scale(5.4f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("inverseBindMatrix"); + updateChange->setValue(newInverseBind); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind); + + // WHEN + QVector<QJoint *> childJoints; + QPropertyNodeAddedChangePtr nodeAddedChange; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + childJoints.push_back(childJoint); + + nodeAddedChange.reset(new QPropertyNodeAddedChange(QNodeId(), childJoint)); + nodeAddedChange->setPropertyName("childJoint"); + backendJoint.sceneChangeEvent(nodeAddedChange); + } + + // THEN + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + + QPropertyNodeRemovedChangePtr nodeRemovedChange; + for (int i = 0; i < 10; ++i) { + // WHEN + const auto childJoint = childJoints.takeLast(); + + nodeRemovedChange.reset(new QPropertyNodeRemovedChange(QNodeId(), childJoint)); + nodeRemovedChange->setPropertyName("childJoint"); + backendJoint.sceneChangeEvent(nodeAddedChange); + + // THEN + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + } + } +}; + +QTEST_APPLESS_MAIN(tst_Joint) + +#include "tst_joint.moc" diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index c66b85c8c..c2651c477 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -34,6 +34,7 @@ #include <Qt3DRender/private/filterlayerentityjob_p.h> #include <Qt3DRender/private/updatetreeenabledjob_p.h> #include <Qt3DRender/qlayer.h> +#include <Qt3DRender/qlayerfilter.h> #include "testaspect.h" class tst_LayerFiltering : public QObject @@ -45,18 +46,19 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::FilterLayerEntityJob filterJob; + Qt3DRender::QLayer frontendLayer; // THEN QCOMPARE(filterJob.hasLayerFilter(), false); QCOMPARE(filterJob.filteredEntities().size(), 0); - QCOMPARE(filterJob.layers().size(), 0); + QCOMPARE(filterJob.layerFilters().size(), 0); + QCOMPARE(frontendLayer.recursive(), false); } void filterEntities_data() { QTest::addColumn<Qt3DCore::QEntity *>("entitySubtree"); - QTest::addColumn<Qt3DCore::QNodeIdVector>("layerIds"); - QTest::addColumn<bool>("hasLayerFilter"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("layerFilterIds"); QTest::addColumn<Qt3DCore::QNodeIdVector>("expectedSelectedEntities"); @@ -70,15 +72,14 @@ private Q_SLOTS: Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); - QTest::newRow("EntitiesNoLayerNoLayerFilter-ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() - << false - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id() - ); + QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity + << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); } { @@ -87,14 +88,14 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); Q_UNUSED(childEntity1); Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); QTest::newRow("EntityNoLayerWithLayerFilterWithNoFilter-ShouldSelectNone") << rootEntity - << Qt3DCore::QNodeIdVector() - << true + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) << Qt3DCore::QNodeIdVector(); } @@ -109,12 +110,13 @@ private Q_SLOTS: Q_UNUSED(childEntity3); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); - QTest::newRow("NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DCore::QNodeIdVector(); + QTest::newRow("AcceptAny-NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -129,10 +131,12 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); } { @@ -148,10 +152,13 @@ private Q_SLOTS: childEntity2->addComponent(layer2); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id() << layer2->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); } { @@ -167,10 +174,12 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer2->id()) - << true - << Qt3DCore::QNodeIdVector(); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer2); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -186,22 +195,436 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-RecursiveLayerOnRoot-ShouldSelectAll") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-RecursiveLayerLayerFilterDiscardOnRoot-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer); + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersNonRecursive-ShouldSelectChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); } + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursive-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursiveAndDirectReferenceToRecursiveLayer-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2Layers-ShouldSelectRootAndChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursive-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursiveAndDirectReference-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer5); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter2->addLayer(layer4); + layerFilter2->addLayer(layer5); + + QTest::newRow("NestedFiltering-SelectAllOfLayer123AndNoneOf45-ShouldChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity4 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity5 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer6 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer5); + + childEntity4->addComponent(layer2); + childEntity4->addComponent(layer); + childEntity4->addComponent(layer3); + childEntity4->addComponent(layer6); + + childEntity5->addComponent(layer3); + childEntity5->addComponent(layer4); + childEntity5->addComponent(layer6); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer5); + layerFilter->addLayer(layer4); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers); + layerFilter2->addLayer(layer2); + layerFilter2->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter3 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter3->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter3->addLayer(layer); + layerFilter3->addLayer(layer6); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity4->id() + ); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step2") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity4->id()); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id() << layerFilter3->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity4->id()); + } } void filterEntities() { //QSKIP("Skipping until TestAspect can be registered"); QFETCH(Qt3DCore::QEntity *, entitySubtree); - QFETCH(Qt3DCore::QNodeIdVector, layerIds); - QFETCH(bool, hasLayerFilter); + QFETCH(Qt3DCore::QNodeIdVector, layerFilterIds); QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities); + // GIVEN QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree)); @@ -213,16 +636,15 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::FilterLayerEntityJob filterJob; - filterJob.setHasLayerFilter(hasLayerFilter); - filterJob.setLayers(layerIds); + filterJob.setLayerFilters(layerFilterIds); filterJob.setManager(aspect->nodeManagers()); filterJob.run(); // THEN const QVector<Qt3DRender::Render::Entity *> filterEntities = filterJob.filteredEntities(); - QCOMPARE(expectedSelectedEntities.size(), filterEntities.size()); + QCOMPARE(filterEntities.size(), expectedSelectedEntities.size()); for (auto i = 0, m = expectedSelectedEntities.size(); i < m; ++i) - QCOMPARE(expectedSelectedEntities.at(i), filterEntities.at(i)->peerId()); + QCOMPARE(filterEntities.at(i)->peerId(), expectedSelectedEntities.at(i)); } }; diff --git a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp index 08d1caace..bd9848928 100644 --- a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp +++ b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp @@ -50,8 +50,15 @@ public: m_source = source; } - bool isFileTypeSupported(const QUrl &) const Q_DECL_OVERRIDE + void setData(const QByteArray& data, const QString &basePath) Q_DECL_OVERRIDE { + Q_UNUSED(data); + Q_UNUSED(basePath); + } + + bool areFileTypesSupported(const QStringList &extensions) const Q_DECL_OVERRIDE + { + Q_UNUSED(extensions); return m_supportsFormat; } @@ -99,7 +106,7 @@ private Q_SLOTS: void checkInitialize() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); const Qt3DCore::QNodeId sceneId = Qt3DCore::QNodeId::createId(); Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -120,8 +127,10 @@ private Q_SLOTS: void checkRunValidSourceSupportedFormat() { + QSKIP("Can't test successful loading"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, false); @@ -202,8 +211,11 @@ private Q_SLOTS: void checkRunValidSourceUnsupportedFormat() { + // no data is loaded so... + QSKIP("Can't differentiate between no data and unsupported data"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(false, false); @@ -241,7 +253,7 @@ private Q_SLOTS: void checkRunErrorAtLoading() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -259,7 +271,7 @@ private Q_SLOTS: loadSceneJob.run(); // THEN - QCOMPARE(arbiter.events.count(), 4); + QCOMPARE(arbiter.events.count(), 3); auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); @@ -267,16 +279,11 @@ private Q_SLOTS: change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); - QCOMPARE(change->propertyName(), "status"); - QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Loading); - - change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "scene"); QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr); delete change->value().value<Qt3DCore::QEntity *>(); - change = arbiter.events.at(3).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Error); diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index e2877b24b..fd430c5d8 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -32,6 +32,7 @@ #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/qmesh.h> #include <Qt3DRender/private/qmesh_p.h> +#include <Qt3DCore/qaspectengine.h> class MeshFunctorA : public Qt3DRender::QGeometryFactory { @@ -124,14 +125,27 @@ private Q_SLOTS: void checkMeshFunctorEquality() { // GIVEN - const Qt3DRender::MeshFunctor functorA(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("bar")); - const Qt3DRender::MeshFunctor functorB(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("baz")); - const Qt3DRender::MeshFunctor functorC(QUrl::fromLocalFile(QLatin1String("/baz")), - QLatin1String("bar")); - const Qt3DRender::MeshFunctor functorD(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("bar")); + Qt3DCore::QAspectEngine engine; + auto meshA = new Qt3DRender::QMesh(); + meshA->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshA->setMeshName(QLatin1String("bar")); + + auto meshB = new Qt3DRender::QMesh(); + meshB->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshB->setMeshName(QLatin1String("baz")); + + auto meshC = new Qt3DRender::QMesh(); + meshC->setSource(QUrl::fromLocalFile(QLatin1String("/baz"))); + meshC->setMeshName(QLatin1String("bar")); + + auto meshD = new Qt3DRender::QMesh(); + meshD->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshD->setMeshName(QLatin1String("bar")); + + const Qt3DRender::MeshLoaderFunctor functorA(meshA, &engine); + const Qt3DRender::MeshLoaderFunctor functorB(meshB, &engine); + const Qt3DRender::MeshLoaderFunctor functorC(meshC, &engine); + const Qt3DRender::MeshLoaderFunctor functorD(meshD, &engine); // WHEN const bool selfEquality = (functorA == functorA); @@ -147,6 +161,6 @@ private Q_SLOTS: } }; -QTEST_APPLESS_MAIN(tst_MeshFunctors) +QTEST_MAIN(tst_MeshFunctors) #include "tst_meshfunctors.moc" diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index c60ddda27..d9d90a03d 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qrenderaspect.h> #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/pickboundingvolumejob_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> #include <Qt3DRender/private/updatemeshtrianglelistjob_p.h> #include <Qt3DRender/private/updateworldboundingvolumejob_p.h> #include <Qt3DRender/private/updateworldtransformjob_p.h> diff --git a/tests/auto/render/proximityfilter/proximityfilter.pro b/tests/auto/render/proximityfilter/proximityfilter.pro new file mode 100644 index 000000000..74599e4f0 --- /dev/null +++ b/tests/auto/render/proximityfilter/proximityfilter.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_proximityfilter + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_proximityfilter.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/proximityfilter/tst_proximityfilter.cpp b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp new file mode 100644 index 000000000..774e2dd1f --- /dev/null +++ b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qproximityfilter.h> +#include <Qt3DRender/private/qproximityfilter_p.h> +#include <Qt3DRender/private/proximityfilter_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_ProximityFilter : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), false); + QVERIFY(backendProximityFilter.peerId().isNull()); + QCOMPARE(backendProximityFilter.distanceThreshold(), 0.0f); + QCOMPARE(backendProximityFilter.entityId(), Qt3DCore::QNodeId()); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + Qt3DCore::QEntity entity; + proximityFilter.setDistanceThreshold(1340.0f); + proximityFilter.setEntity(&entity); + + { + // WHEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + simulateInitialization(&proximityFilter, &backendProximityFilter); + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), true); + QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id()); + QCOMPARE(backendProximityFilter.distanceThreshold(), 1340.f); + QCOMPARE(backendProximityFilter.entityId(), entity.id()); + } + { + // WHEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + proximityFilter.setEnabled(false); + simulateInitialization(&proximityFilter, &backendProximityFilter); + + // THEN + QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id()); + QCOMPARE(backendProximityFilter.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + TestRenderer renderer; + backendProximityFilter.setRenderer(&renderer); + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), newValue); + } + { + // WHEN + const float newValue = 383.0f; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("distanceThreshold"); + change->setValue(QVariant::fromValue(newValue)); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.distanceThreshold(), newValue); + } + { + // WHEN + const Qt3DCore::QNodeId newValue = Qt3DCore::QNodeId::createId(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("entity"); + change->setValue(QVariant::fromValue(newValue)); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.entityId(), newValue); + } + } + +}; + +QTEST_MAIN(tst_ProximityFilter) + +#include "tst_proximityfilter.moc" diff --git a/tests/auto/render/proximityfiltering/proximityfiltering.pro b/tests/auto/render/proximityfiltering/proximityfiltering.pro new file mode 100644 index 000000000..68b709ec5 --- /dev/null +++ b/tests/auto/render/proximityfiltering/proximityfiltering.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_proximityfiltering + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_proximityfiltering.cpp + +CONFIG += useCommonTestAspect + +include(../commons/commons.pri) diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp new file mode 100644 index 000000000..7a5648271 --- /dev/null +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qtransform.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DRender/private/filterproximitydistancejob_p.h> +#include <Qt3DRender/private/updatetreeenabledjob_p.h> +#include <Qt3DRender/qproximityfilter.h> + +#include "testaspect.h" + +namespace { + +Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent) +{ + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(parent); + Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(parent); + const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance; + + transform->setTranslation(t); + entity->addComponent(transform); + + return entity; +} + +} // anonymous + +class tst_ProximityFiltering : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::FilterProximityDistanceJob filterJob; + + // THEN + QCOMPARE(filterJob.hasProximityFilter(), false); + QCOMPARE(filterJob.filteredEntities().size(), 0); + QCOMPARE(filterJob.proximityFilterIds().size(), 0); + QVERIFY(filterJob.manager() == nullptr); + } + + void filterEntities_data() + { + QTest::addColumn<Qt3DCore::QEntity *>("entitySubtree"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("proximityFilterIds"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("expectedSelectedEntities"); + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + QTest::newRow("ShouldSelectAll") << rootEntity + << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + + QTest::newRow("ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(75.0f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(30.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(75.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity3); + + QTest::newRow("ShouldSelectChild2") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity2->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(49.9f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(50.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + QTest::newRow("ShouldSelectRootChild123") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << targetEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(51.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(75.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(883.0f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(883.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + QTest::newRow("ShouldSelectNoneButTarget") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() << targetEntity->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(150.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(25.0f, rootEntity); + + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + Qt3DRender::QProximityFilter *proximityFilter2 = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter2->setDistanceThreshold(30.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(150.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + proximityFilter2->setEntity(targetEntity); + + Q_UNUSED(childEntity2); + + QTest::newRow("Nested-Step1") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity1->id() + << childEntity3->id() + ); + QTest::newRow("Nested-Step2") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id() << proximityFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity3->id() + ); + } + } + + void filterEntities() + { + QFETCH(Qt3DCore::QEntity *, entitySubtree); + QFETCH(Qt3DCore::QNodeIdVector, proximityFilterIds); + QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities); + + // GIVEN + QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree)); + + // WHEN + Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id()); + Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob; + updateTreeEnabledJob.setRoot(backendRoot); + updateTreeEnabledJob.run(); + + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; + updateWorldTransform.setRoot(backendRoot); + updateWorldTransform.run(); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; + calcBVolume.setManagers(aspect->nodeManagers()); + calcBVolume.setRoot(backendRoot); + calcBVolume.run(); + + Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; + updateWorldBVolume.setManager(aspect->nodeManagers()->renderNodesManager()); + updateWorldBVolume.run(); + + Qt3DRender::Render::ExpandBoundingVolumeJob expandBVolume; + expandBVolume.setRoot(backendRoot); + expandBVolume.run(); + + // WHEN + Qt3DRender::Render::FilterProximityDistanceJob filterJob; + filterJob.setProximityFilterIds(proximityFilterIds); + filterJob.setManager(aspect->nodeManagers()); + filterJob.run(); + + // THEN + const QVector<Qt3DRender::Render::Entity *> filterEntities = filterJob.filteredEntities(); + QCOMPARE(filterEntities.size(), expectedSelectedEntities.size()); + + for (auto i = 0, m = expectedSelectedEntities.size(); i < m; ++i) + QCOMPARE(filterEntities.at(i)->peerId(), expectedSelectedEntities.at(i)); + } +}; + +QTEST_MAIN(tst_ProximityFiltering) + +#include "tst_proximityfiltering.moc" diff --git a/tests/auto/render/qattribute/tst_qattribute.cpp b/tests/auto/render/qattribute/tst_qattribute.cpp index 66854acdd..23532c435 100644 --- a/tests/auto/render/qattribute/tst_qattribute.cpp +++ b/tests/auto/render/qattribute/tst_qattribute.cpp @@ -58,6 +58,8 @@ private Q_SLOTS: QCOMPARE(Qt3DRender::QAttribute::defaultColorAttributeName(), QStringLiteral("vertexColor")); QCOMPARE(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), QStringLiteral("vertexTexCoord")); QCOMPARE(Qt3DRender::QAttribute::defaultTangentAttributeName(), QStringLiteral("vertexTangent")); + QCOMPARE(Qt3DRender::QAttribute::defaultJointIndicesAttributeName(), QStringLiteral("vertexJointIndices")); + QCOMPARE(Qt3DRender::QAttribute::defaultJointWeightsAttributeName(), QStringLiteral("vertexJointWeights")); QCOMPARE(attribute.property("defaultPositionAttributeName").toString(), Qt3DRender::QAttribute::defaultPositionAttributeName()); @@ -69,6 +71,10 @@ private Q_SLOTS: Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); QCOMPARE(attribute.property("defaultTangentAttributeName").toString(), Qt3DRender::QAttribute::defaultTangentAttributeName()); + QCOMPARE(attribute.property("defaultJointIndicesAttributeName").toString(), + Qt3DRender::QAttribute::defaultJointIndicesAttributeName()); + QCOMPARE(attribute.property("defaultJointWeightsAttributeName").toString(), + Qt3DRender::QAttribute::defaultJointWeightsAttributeName()); } void checkCloning_data() diff --git a/tests/auto/render/qblitframebuffer/qblitframebuffer.pro b/tests/auto/render/qblitframebuffer/qblitframebuffer.pro new file mode 100644 index 000000000..219bad3d2 --- /dev/null +++ b/tests/auto/render/qblitframebuffer/qblitframebuffer.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_qblitframebuffer + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qblitframebuffer.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp new file mode 100644 index 000000000..26ef936f6 --- /dev/null +++ b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp @@ -0,0 +1,338 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> + +#include <Qt3DRender/QBlitFramebuffer> +#include <Qt3DRender/private/qblitframebuffer_p.h> + +#include "testpostmanarbiter.h" + +class tst_QBlitFrameBuffer: public QObject +{ + Q_OBJECT + +public: + tst_QBlitFrameBuffer() : QObject() + { + qRegisterMetaType<Qt3DRender::QRenderTarget*>(); + } + +private Q_SLOTS: + + void checkCreationData_data() + { + QTest::addColumn<Qt3DRender::QBlitFramebuffer *>("blitFramebuffer"); + + Qt3DRender::QBlitFramebuffer *defaultConstructed = new Qt3DRender::QBlitFramebuffer(); + Qt3DRender::QRenderTarget *sourceRenderTarget = new Qt3DRender::QRenderTarget(); + Qt3DRender::QRenderTarget *destinationRenderTarget = new Qt3DRender::QRenderTarget(); + defaultConstructed->setSource(sourceRenderTarget); + defaultConstructed->setDestination(destinationRenderTarget); + QTest::newRow("defaultConstructed") << defaultConstructed; + } + + void checkInitialState() + { + // GIVEN + Qt3DRender::QBlitFramebuffer blitFramebuffer; + + // THEN + QCOMPARE(blitFramebuffer.source(), nullptr); + QCOMPARE(blitFramebuffer.destination(), nullptr); + QCOMPARE(blitFramebuffer.sourceRect(), QRect()); + QCOMPARE(blitFramebuffer.destinationRect(), QRect()); + QCOMPARE(blitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0); + QCOMPARE(blitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0); + QCOMPARE(blitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Linear); + } + + void checkCreationData() + { + // GIVEN + QFETCH(Qt3DRender::QBlitFramebuffer *, blitFramebuffer); + + // WHEN + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(blitFramebuffer); + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); + + // THEN + QCOMPARE(creationChanges.size(), 1); + + const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QBlitFramebufferData> creationChangeData = + qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QBlitFramebufferData>>(creationChanges.first()); + const Qt3DRender::QBlitFramebufferData &cloneData = creationChangeData->data; + + // THEN + QCOMPARE(blitFramebuffer->id(), creationChangeData->subjectId()); + QCOMPARE(blitFramebuffer->isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(blitFramebuffer->metaObject(), creationChangeData->metaObject()); + QCOMPARE(blitFramebuffer->source()->id(), cloneData.m_sourceRenderTargetId); + QCOMPARE(blitFramebuffer->destination()->id(), cloneData.m_destinationRenderTargetId); + QCOMPARE(blitFramebuffer->sourceRect(), cloneData.m_sourceRect); + QCOMPARE(blitFramebuffer->destinationRect(), cloneData.m_destinationRect); + QCOMPARE(blitFramebuffer->sourceAttachmentPoint(), cloneData.m_sourceAttachmentPoint); + QCOMPARE(blitFramebuffer->destinationAttachmentPoint(), cloneData.m_destinationAttachmentPoint); + + + delete blitFramebuffer; + } + + void checkPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + QScopedPointer<Qt3DRender::QBlitFramebuffer> blitFramebuffer(new Qt3DRender::QBlitFramebuffer()); + arbiter.setArbiterOnNode(blitFramebuffer.data()); + + Qt3DRender::QRenderTarget *sourceRenderTarget = new Qt3DRender::QRenderTarget; + Qt3DRender::QRenderTarget *destinationRenderTarget = new Qt3DRender::QRenderTarget; + + // sourceRenderTarget + // WHEN + blitFramebuffer->setSource(sourceRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "source"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), sourceRenderTarget->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSource(sourceRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSource(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "source"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationRenderTarget + // WHEN + blitFramebuffer->setDestination(destinationRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destination"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), destinationRenderTarget->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestination(destinationRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestination(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destination"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // sourceRect + // WHEN + blitFramebuffer->setSourceRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ; + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSourceRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSourceRect(QRect()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationRect + blitFramebuffer->setDestinationRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ; + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestinationRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestinationRect(QRect()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // sourceAttachmentPoint + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationAttachmentPoint + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } +}; + +QTEST_MAIN(tst_QBlitFrameBuffer) + +#include "tst_qblitframebuffer.moc" diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp index fdc25cbca..719c6229f 100644 --- a/tests/auto/render/qbuffer/tst_qbuffer.cpp +++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp @@ -112,7 +112,6 @@ private Q_SLOTS: QCOMPARE(buffer->metaObject(), creationChangeData->metaObject()); QCOMPARE(buffer->data(), cloneData.data); QCOMPARE(buffer->usage(), cloneData.usage); - QCOMPARE(buffer->type(), cloneData.type); QCOMPARE(buffer->dataGenerator(), cloneData.functor); QCOMPARE(buffer->isSyncData(), cloneData.syncData); if (buffer->dataGenerator()) { diff --git a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp index 94f720097..edd767ad9 100644 --- a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp +++ b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp @@ -88,6 +88,7 @@ private Q_SLOTS: geometry1->setInstanceCount(1); geometry1->setIndexOffset(0); geometry1->setFirstInstance(55); + geometry1->setIndexBufferByteOffset(48); geometry1->setRestartIndexValue(-1); geometry1->setPrimitiveRestartEnabled(false); geometry1->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); @@ -101,6 +102,7 @@ private Q_SLOTS: geometry2->setInstanceCount(200); geometry2->setIndexOffset(58); geometry2->setFirstInstance(10); + geometry2->setIndexBufferByteOffset(96); geometry2->setRestartIndexValue(65535); geometry2->setVertexCount(2056); geometry2->setPrimitiveRestartEnabled(true); @@ -134,6 +136,7 @@ private Q_SLOTS: QCOMPARE(cloneData.vertexCount, geometryRenderer->vertexCount()); QCOMPARE(cloneData.indexOffset, geometryRenderer->indexOffset()); QCOMPARE(cloneData.firstInstance, geometryRenderer->firstInstance()); + QCOMPARE(cloneData.indexBufferByteOffset, geometryRenderer->indexBufferByteOffset()); QCOMPARE(cloneData.restartIndexValue, geometryRenderer->restartIndexValue()); QCOMPARE(cloneData.primitiveRestart, geometryRenderer->primitiveRestartEnabled()); QCOMPARE(cloneData.primitiveType, geometryRenderer->primitiveType()); @@ -207,6 +210,19 @@ private Q_SLOTS: arbiter.events.clear(); // WHEN + geometryRenderer->setIndexBufferByteOffset(91); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "indexBufferByteOffset"); + QCOMPARE(change->value().value<int>(), 91); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN geometryRenderer->setRestartIndexValue(65535); QCoreApplication::processEvents(); diff --git a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp index ac6f79b3f..9e0cb8e57 100644 --- a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp +++ b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp @@ -36,6 +36,13 @@ class tst_QGraphicsApiFilter : public QObject { Q_OBJECT +public: + tst_QGraphicsApiFilter() : QObject() + { + qRegisterMetaType<Qt3DRender::QGraphicsApiFilter::Api>(); + qRegisterMetaType<Qt3DRender::QGraphicsApiFilter::OpenGLProfile>(); + } + private Q_SLOTS: void defaultConstruction() { diff --git a/tests/auto/render/qmesh/tst_qmesh.cpp b/tests/auto/render/qmesh/tst_qmesh.cpp index 2122d7eb5..127371750 100644 --- a/tests/auto/render/qmesh/tst_qmesh.cpp +++ b/tests/auto/render/qmesh/tst_qmesh.cpp @@ -34,6 +34,7 @@ #include <QSignalSpy> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qnodecreatedchange.h> #include "testpostmanarbiter.h" @@ -121,9 +122,8 @@ private Q_SLOTS: const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QGeometryRendererData>>(creationChanges.first()); const Qt3DRender::QGeometryRendererData cloneData = creationChangeData->data; - Qt3DRender::MeshFunctor meshFunctor(mesh.source(), mesh.meshName()); - - QVERIFY(meshFunctor == *cloneData.geometryFactory); + // Geometry factory is null until the engine becomes available + QVERIFY(cloneData.geometryFactory == nullptr); QCOMPARE(mesh.id(), creationChangeData->subjectId()); QCOMPARE(mesh.isEnabled(), true); QCOMPARE(mesh.isEnabled(), creationChangeData->isNodeEnabled()); @@ -158,6 +158,13 @@ private Q_SLOTS: Qt3DRender::QMesh mesh; arbiter.setArbiterOnNode(&mesh); + Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef); + Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine); + Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(&mesh); + meshd->setScene(scene); + QCoreApplication::processEvents(); + arbiter.events.clear(); + { // WHEN mesh.setSource(QUrl(QStringLiteral("qrc:/toyplane.obj"))); @@ -165,13 +172,15 @@ private Q_SLOTS: // THEN QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(mesh.source()); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); - QVERIFY(meshFunctor == *factory); + QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory); + QVERIFY(meshFunctor != nullptr); + QCOMPARE(meshFunctor->m_mesh, mesh.id()); + QCOMPARE(meshFunctor->m_sourcePath, mesh.source()); arbiter.events.clear(); } @@ -194,6 +203,13 @@ private Q_SLOTS: Qt3DRender::QMesh mesh; arbiter.setArbiterOnNode(&mesh); + Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef); + Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine); + Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(&mesh); + meshd->setScene(scene); + QCoreApplication::processEvents(); + arbiter.events.clear(); + { // WHEN mesh.setMeshName(QStringLiteral("Phil")); @@ -205,9 +221,11 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(QUrl(), mesh.meshName()); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); - QVERIFY(meshFunctor == *factory); + QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory); + QVERIFY(meshFunctor != nullptr); + QCOMPARE(meshFunctor->m_mesh, mesh.id()); + QCOMPARE(meshFunctor->m_meshName, mesh.meshName()); arbiter.events.clear(); } diff --git a/tests/auto/render/qproximityfilter/qproximityfilter.pro b/tests/auto/render/qproximityfilter/qproximityfilter.pro new file mode 100644 index 000000000..4a12e244f --- /dev/null +++ b/tests/auto/render/qproximityfilter/qproximityfilter.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qproximityfilter + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qproximityfilter.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp new file mode 100644 index 000000000..890d6ee3e --- /dev/null +++ b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/qproximityfilter.h> +#include <Qt3DRender/private/qproximityfilter_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/qentity.h> +#include "testpostmanarbiter.h" + +class tst_QProximityFilter : public QObject +{ + Q_OBJECT + +public: + tst_QProximityFilter() : QObject() + { + qRegisterMetaType<Qt3DCore::QEntity*>(); + } + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + + // THEN + QVERIFY(proximityFilter.entity() == nullptr); + QCOMPARE(proximityFilter.distanceThreshold(), 0.0f); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + + { + // WHEN + Qt3DCore::QEntity entity; + + QSignalSpy spy(&proximityFilter, SIGNAL(entityChanged(Qt3DCore::QEntity *))); + Qt3DCore::QEntity *newValue = &entity; + proximityFilter.setEntity(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(proximityFilter.entity(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + proximityFilter.setEntity(newValue); + + // THEN + QCOMPARE(proximityFilter.entity(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&proximityFilter, SIGNAL(distanceThresholdChanged(float))); + const float newValue = 883.0f; + proximityFilter.setDistanceThreshold(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(proximityFilter.distanceThreshold(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + proximityFilter.setDistanceThreshold(newValue); + + // THEN + QCOMPARE(proximityFilter.distanceThreshold(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + Qt3DCore::QEntity entity; + + proximityFilter.setEntity(&entity); + proximityFilter.setDistanceThreshold(1584.0f); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&proximityFilter); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // Entity creation change is the second change + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QProximityFilterData>>(creationChanges.first()); + const Qt3DRender::QProximityFilterData cloneData = creationChangeData->data; + + QCOMPARE(proximityFilter.entity()->id(), cloneData.entityId); + QCOMPARE(proximityFilter.distanceThreshold(), cloneData.distanceThreshold); + QCOMPARE(proximityFilter.id(), creationChangeData->subjectId()); + QCOMPARE(proximityFilter.isEnabled(), true); + QCOMPARE(proximityFilter.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(proximityFilter.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + proximityFilter.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&proximityFilter); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // Entity creation change is the second change + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QProximityFilterData>>(creationChanges.first()); + const Qt3DRender::QProximityFilterData cloneData = creationChangeData->data; + + QCOMPARE(proximityFilter.entity()->id(), cloneData.entityId); + QCOMPARE(proximityFilter.distanceThreshold(), cloneData.distanceThreshold); + QCOMPARE(proximityFilter.id(), creationChangeData->subjectId()); + QCOMPARE(proximityFilter.isEnabled(), false); + QCOMPARE(proximityFilter.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(proximityFilter.metaObject(), creationChangeData->metaObject()); + } + } + + void checkEntityUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QProximityFilter proximityFilter; + arbiter.setArbiterOnNode(&proximityFilter); + Qt3DCore::QEntity entity; + + { + // WHEN + proximityFilter.setEntity(&entity); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "entity"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), proximityFilter.entity()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + proximityFilter.setEntity(&entity); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkDistanceThresholdUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QProximityFilter proximityFilter; + arbiter.setArbiterOnNode(&proximityFilter); + + { + // WHEN + proximityFilter.setDistanceThreshold(454.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "distanceThreshold"); + QCOMPARE(change->value().value<float>(), proximityFilter.distanceThreshold()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + proximityFilter.setDistanceThreshold(454.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkEntityBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DRender::QProximityFilter> proximityFilter(new Qt3DRender::QProximityFilter); + { + // WHEN + Qt3DCore::QEntity entity; + proximityFilter->setEntity(&entity); + + // THEN + QCOMPARE(entity.parent(), proximityFilter.data()); + QCOMPARE(proximityFilter->entity(), &entity); + } + + // THEN (Should not crash and parameter be unset) + QVERIFY(proximityFilter->entity() == nullptr); + + { + // WHEN + Qt3DRender::QProximityFilter someOtherProximityFilter; + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity(&someOtherProximityFilter)); + proximityFilter->setEntity(entity.data()); + + // THEN + QCOMPARE(entity->parent(), &someOtherProximityFilter); + QCOMPARE(proximityFilter->entity(), entity.data()); + + // WHEN + proximityFilter.reset(); + entity.reset(); + + // THEN Should not crash when the camera is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QProximityFilter) + +#include "tst_qproximityfilter.moc" diff --git a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp index d4e603ea4..830615a95 100644 --- a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp +++ b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp @@ -67,7 +67,7 @@ private Q_SLOTS: arbiter.setArbiterOnNode(renderCapture.data()); // WHEN - QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture()); + QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture(QRect(10, 15, 20, 50))); // THEN QCOMPARE(arbiter.events.size(), 1); @@ -75,7 +75,10 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "renderCaptureRequest"); QCOMPARE(change->subjectId(),renderCapture->id()); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - QCOMPARE(change->value().toInt(), 1); + QVERIFY(change->value().canConvert<Qt3DRender::QRenderCaptureRequest>()); + const Qt3DRender::QRenderCaptureRequest request = change->value().value<Qt3DRender::QRenderCaptureRequest>(); + QCOMPARE(request.captureId, 1); + QCOMPARE(request.rect, QRect(10, 15, 20, 50)); arbiter.events.clear(); } diff --git a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp index 1f0a9f066..6f182cbeb 100644 --- a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp +++ b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp @@ -184,6 +184,7 @@ private Q_SLOTS: pickingSettings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); pickingSettings->setPickResultMode(Qt3DRender::QPickingSettings::AllPicks); pickingSettings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontAndBackFace); + pickingSettings->setWorldSpaceTolerance(5.f); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -203,6 +204,7 @@ private Q_SLOTS: QCOMPARE(renderSettings.pickingSettings()->pickMethod(), cloneData.pickMethod); QCOMPARE(renderSettings.pickingSettings()->pickResultMode(), cloneData.pickResultMode); QCOMPARE(renderSettings.pickingSettings()->faceOrientationPickingMode(), cloneData.faceOrientationPickingMode); + QCOMPARE(renderSettings.pickingSettings()->worldSpaceTolerance(), cloneData.pickWorldSpaceTolerance); QCOMPARE(renderSettings.renderPolicy(), cloneData.renderPolicy); QCOMPARE(renderSettings.activeFrameGraph()->id(), cloneData.activeFrameGraphId); QCOMPARE(renderSettings.id(), creationChangeData->subjectId()); @@ -410,6 +412,41 @@ private Q_SLOTS: } + void checkWorldSpaceToleranceUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QRenderSettings renderSettings; + Qt3DRender::QPickingSettings *pickingSettings = renderSettings.pickingSettings(); + + arbiter.setArbiterOnNode(&renderSettings); + + { + // WHEN + pickingSettings->setWorldSpaceTolerance(5.f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "pickWorldSpaceTolerance"); + QCOMPARE(change->value().toFloat(), pickingSettings->worldSpaceTolerance()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + pickingSettings->setWorldSpaceTolerance(5.f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + }; QTEST_MAIN(tst_QRenderSettings) diff --git a/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro b/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro new file mode 100644 index 000000000..32fe88e9f --- /dev/null +++ b/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qshaderprogrambuilder + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qshaderprogrambuilder.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp new file mode 100644 index 000000000..93bee22cc --- /dev/null +++ b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp @@ -0,0 +1,601 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> +#include <Qt3DRender/private/qshaderprogrambuilder_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QShaderProgramBuilder : public QObject +{ + Q_OBJECT +public: + tst_QShaderProgramBuilder() + : QObject() + { + qRegisterMetaType<Qt3DRender::QShaderProgram*>("Qt3DRender::QShaderProgram*"); + } + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + // THEN + QVERIFY(!builder.shaderProgram()); + QVERIFY(builder.enabledLayers().isEmpty()); + QCOMPARE(builder.vertexShaderGraph(), QUrl()); + QCOMPARE(builder.tessellationControlShaderGraph(), QUrl()); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), QUrl()); + QCOMPARE(builder.geometryShaderGraph(), QUrl()); + QCOMPARE(builder.fragmentShaderGraph(), QUrl()); + QCOMPARE(builder.computeShaderGraph(), QUrl()); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(shaderProgramChanged(Qt3DRender::QShaderProgram*))); + auto newValue = new Qt3DRender::QShaderProgram(&builder); + builder.setShaderProgram(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.shaderProgram(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setShaderProgram(newValue); + + // THEN + QCOMPARE(builder.shaderProgram(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(enabledLayersChanged(QStringList))); + const auto newValue = QStringList() << "foo" << "bar"; + builder.setEnabledLayers(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.enabledLayers(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setEnabledLayers(newValue); + + // THEN + QCOMPARE(builder.enabledLayers(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(vertexShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/vertex.json"); + builder.setVertexShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.vertexShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setVertexShaderGraph(newValue); + + // THEN + QCOMPARE(builder.vertexShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(tessellationControlShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/tesscontrol.json"); + builder.setTessellationControlShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.tessellationControlShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setTessellationControlShaderGraph(newValue); + + // THEN + QCOMPARE(builder.tessellationControlShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(tessellationEvaluationShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/tesseval.json"); + builder.setTessellationEvaluationShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setTessellationEvaluationShaderGraph(newValue); + + // THEN + QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(geometryShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/geometry.json"); + builder.setGeometryShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.geometryShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setGeometryShaderGraph(newValue); + + // THEN + QCOMPARE(builder.geometryShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(fragmentShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/fragment.json"); + builder.setFragmentShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.fragmentShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setFragmentShaderGraph(newValue); + + // THEN + QCOMPARE(builder.fragmentShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(computeShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/compute.json"); + builder.setComputeShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.computeShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setComputeShaderGraph(newValue); + + // THEN + QCOMPARE(builder.computeShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkShaderProgramBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DRender::QShaderProgramBuilder> builder(new Qt3DRender::QShaderProgramBuilder); + { + // WHEN + Qt3DRender::QShaderProgram program; + builder->setShaderProgram(&program); + + // THEN + QCOMPARE(program.parent(), builder.data()); + QCOMPARE(builder->shaderProgram(), &program); + } + // THEN (Should not crash and effect be unset) + QVERIFY(!builder->shaderProgram()); + + { + // WHEN + Qt3DRender::QShaderProgramBuilder someOtherBuilder; + QScopedPointer<Qt3DRender::QShaderProgram> program(new Qt3DRender::QShaderProgram(&someOtherBuilder)); + builder->setShaderProgram(program.data()); + + // THEN + QCOMPARE(program->parent(), &someOtherBuilder); + QCOMPARE(builder->shaderProgram(), program.data()); + + // WHEN + builder.reset(); + program.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + builder.setShaderProgram(new Qt3DRender::QShaderProgram(&builder)); + builder.setEnabledLayers({"foo", "bar"}); + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data; + + QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId); + QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers); + QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph); + QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph); + QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph); + QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph); + QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph); + QCOMPARE(builder.id(), creationChangeData->subjectId()); + QCOMPARE(builder.isEnabled(), true); + QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(builder.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + builder.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data; + + QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId); + QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers); + QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph); + QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph); + QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph); + QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph); + QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph); + QCOMPARE(builder.id(), creationChangeData->subjectId()); + QCOMPARE(builder.isEnabled(), false); + QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(builder.metaObject(), creationChangeData->metaObject()); + } + } + + void checkShaderProgramUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + auto program = new Qt3DRender::QShaderProgram(&builder); + + { + // WHEN + builder.setShaderProgram(program); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "shaderProgram"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), builder.shaderProgram()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setShaderProgram(program); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkEnabledLayersUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + const auto layers = QStringList() << "foo" << "bar"; + + { + // WHEN + builder.setEnabledLayers(layers); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "enabledLayers"); + QCOMPARE(change->value().toStringList(), layers); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setEnabledLayers(layers); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkVertexShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "vertexShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.vertexShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationControlShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationControlShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.tessellationControlShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationEvaluationShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationEvaluationShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.tessellationEvaluationShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkGeometryShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "geometryShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.geometryShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkFragmentShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "fragmentShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.fragmentShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkComputeShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "computeShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.computeShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } +}; + +QTEST_MAIN(tst_QShaderProgramBuilder) + +#include "tst_qshaderprogrambuilder.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 5a82ee835..32a7b35fc 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -7,13 +7,13 @@ qtConfig(private_tests) { renderpass \ qgraphicsutils \ shader \ + shaderbuilder \ texture \ renderviewutils \ renderviews \ material \ vsyncframeadvanceservice \ meshfunctors \ - qmaterial \ qattribute \ qbuffer \ qgeometry \ @@ -23,7 +23,6 @@ qtConfig(private_tests) { buffer \ attribute \ geometry \ - geometryloaders \ geometryrenderer \ raycasting \ qcameraselector \ @@ -44,11 +43,8 @@ qtConfig(private_tests) { framegraphnode \ qobjectpicker \ objectpicker \ - picking \ # qboundingvolumedebug \ # boundingvolumedebug \ - boundingsphere \ - qdefaultmeshes \ trianglesextractor \ triangleboundingvolume \ ddstextures \ @@ -70,8 +66,6 @@ qtConfig(private_tests) { graphicshelpergl3_3 \ graphicshelpergl3_2 \ graphicshelpergl2 \ - gltfplugins \ - pickboundingvolumejob \ sendrendercapturejob \ textures \ qparameter \ @@ -81,8 +75,6 @@ qtConfig(private_tests) { qabstracttexture \ qabstracttextureimage \ qrendersettings \ - updatemeshtrianglelistjob \ - updateshaderdatatransformjob \ texturedatamanager \ rendertarget \ transform \ @@ -101,14 +93,43 @@ qtConfig(private_tests) { renderviewbuilder \ filtercompatibletechniquejob \ rendercapture \ + segmentvisitor \ trianglevisitor \ qmemorybarrier \ memorybarrier \ qshaderprogram \ - qscene2d \ - scene2d \ + qshaderprogrambuilder \ coordinatereader \ - framegraphvisitor + framegraphvisitor \ + renderer \ + armature \ + skeleton \ + joint \ + qproximityfilter \ + proximityfilter \ + proximityfiltering \ + qblitframebuffer \ + blitframebuffer + + QT_FOR_CONFIG = 3dcore-private + qtConfig(qt3d-extras) { + SUBDIRS += \ + qmaterial \ + geometryloaders \ + picking \ + boundingsphere \ + qdefaultmeshes \ + pickboundingvolumejob \ + gltfplugins \ + updatemeshtrianglelistjob \ + updateshaderdatatransformjob + } + + qtConfig(qt3d-input) { + SUBDIRS += \ + qscene2d \ + scene2d + } !macos: SUBDIRS += graphicshelpergl4 } diff --git a/tests/auto/render/rendercapture/tst_rendercapture.cpp b/tests/auto/render/rendercapture/tst_rendercapture.cpp index 4029ba136..799a7ccff 100644 --- a/tests/auto/render/rendercapture/tst_rendercapture.cpp +++ b/tests/auto/render/rendercapture/tst_rendercapture.cpp @@ -90,7 +90,7 @@ private Q_SLOTS: QCOMPARE(renderCapture.wasCaptureRequested(), true); } - void checkAcknowledgeCaptureRequest() + void checkTakeCaptureRequest() { // GIVEN Qt3DRender::Render::RenderCapture renderCapture; @@ -99,22 +99,26 @@ private Q_SLOTS: renderCapture.setEnabled(true); // WHEN - renderCapture.requestCapture(2); - renderCapture.requestCapture(4); + renderCapture.requestCapture({ 2, QRect(10, 10, 20, 20) }); + renderCapture.requestCapture({ 4, QRect(15, 15, 30, 30) }); // THEN QCOMPARE(renderCapture.wasCaptureRequested(), true); // WHEN - renderCapture.acknowledgeCaptureRequest(); + Qt3DRender::QRenderCaptureRequest r1 = renderCapture.takeCaptureRequest(); // THEN + QCOMPARE(r1.captureId, 2); + QCOMPARE(r1.rect, QRect(10, 10, 20, 20)); QCOMPARE(renderCapture.wasCaptureRequested(), true); // WHEN - renderCapture.acknowledgeCaptureRequest(); + Qt3DRender::QRenderCaptureRequest r2 = renderCapture.takeCaptureRequest(); // THEN + QCOMPARE(r2.captureId, 4); + QCOMPARE(r2.rect, QRect(15, 15, 30, 30)); QCOMPARE(renderCapture.wasCaptureRequested(), false); } }; diff --git a/tests/auto/render/renderer/renderer.pro b/tests/auto/render/renderer/renderer.pro new file mode 100644 index 000000000..cbafc156b --- /dev/null +++ b/tests/auto/render/renderer/renderer.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +TARGET = tst_renderer + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderer.cpp diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp new file mode 100644 index 000000000..85d978926 --- /dev/null +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QMutex> +#include <QWaitCondition> +#include <QThread> +#include <Qt3DRender/private/renderer_p.h> +#include <Qt3DRender/private/viewportnode_p.h> +#include <Qt3DRender/private/renderview_p.h> +#include <Qt3DRender/private/renderviewbuilder_p.h> + +class tst_Renderer : public QObject +{ + Q_OBJECT +public : + tst_Renderer() {} + ~tst_Renderer() {} + +private Q_SLOTS: + void checkRenderBinJobs() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::RenderSettings settings; + // owned by FG manager + Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); + const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); + + nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); + settings.setActiveFrameGraphId(fgRootId); + + renderer.setNodeManagers(&nodeManagers); + renderer.setSettings(&settings); + renderer.initialize(); + + const int singleRenderViewJobCount = 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + // RenderViewBuilder renderViewJob, + // renderableEntityFilterJob, + // lightGatherJob, + // computableEntityFilterJob, + // syncRenderViewInitializationJob, + // syncFrustumCullingJob, + // filterEntityByLayerJob, + // filterProximityJob, + // setClearDrawBufferIndexJob, + // frustumCullingJob, + // syncRenderCommandBuldingJob, + // syncRenderViewCommandBuilderJob) + // n * (RenderViewCommandBuildJobs + MaterialGathererJobs + + // WHEN (nothing dirty, no buffers) + QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + singleRenderViewJobCount); // Only valid for the first call to renderBinJobs(), since subsequent calls won't have the renderqueue reset + + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // EntityEnabledDirty + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // updateSkinningPaletteJob + 1); // ExpandBoundingVolumeJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // updateSkinningPaletteJob + 1); // ExpandBoundingVolumeJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // BufferGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::ShadersDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // ShaderGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // TexturesGathererJob + 1 + // updateSkinningPaletteJob + 1); // SyncTexturesGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // EntityEnabledDirty + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // ExpandBoundingVolumeJob + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // BufferGathererJob + 1 + // ShaderGathererJob + 1 + // TexturesGathererJob + 1 + // updateSkinningPaletteJob + 1); // SyncTexturesGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + + } +}; + +QTEST_MAIN(tst_Renderer) + +#include "tst_renderer.moc" diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index 1ab687b34..23861f3a9 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -179,27 +179,60 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + + // THEN + QCOMPARE(renderViewBuilder.renderViewIndex(), 0); + QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), false); + QVERIFY(!renderViewBuilder.renderViewJob().isNull()); + QVERIFY(!renderViewBuilder.lightGathererJob().isNull()); + QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull()); + QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull()); + QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); + + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); + + // WHEN + renderViewBuilder.prepareJobs(); + + // THEN + QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull()); + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } - // THEN - QCOMPARE(renderViewBuilder.renderViewIndex(), 0); - QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); - QVERIFY(!renderViewBuilder.renderViewJob().isNull()); - QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(!renderViewBuilder.lightGathererJob().isNull()); - QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull()); - QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull()); - QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull()); - QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); - QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); - QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + + // THEN + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), true); + QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + // mark jobs dirty and recheck + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 13 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } } void checkCheckJobDependencies() @@ -213,66 +246,145 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.buildJobHierachy(); - - // THEN - // Step 1 - QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 0); - QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); - QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); - QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); - - // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); - - // Step 3 - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); - - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); - - QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); - - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QCOMPARE(materialGatherer->dependencies().size(), 2); - QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); - } - - // Step 4 - QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); + QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); + QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); + + // Step 3 + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QCOMPARE(materialGatherer->dependencies().size(), 2); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); + } + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + } + + // Step 5 + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + } } - - // Step 5 - for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); - } - - // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); - for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); + QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); + QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); + + // Step 3 + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); + + QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QCOMPARE(materialGatherer->dependencies().size(), 2); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); + } + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + } + + // Step 5 + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + } } } @@ -289,6 +401,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderViewJob()->run(); @@ -309,6 +422,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderableEntityFilterJob()->run(); @@ -329,6 +443,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.computableEntityFilterJob()->run(); @@ -354,30 +469,58 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFilter->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.buildJobHierachy(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 0); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() == nullptr); - QVERIFY(materialGatherer->renderPassFilter() == nullptr); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } } - - // WHEN - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewInitializationJob()->run(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 1); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() != nullptr); - QVERIFY(materialGatherer->renderPassFilter() != nullptr); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } } } @@ -399,6 +542,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); // THEN @@ -428,6 +572,8 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderViewJob()->run(); diff --git a/tests/auto/render/sceneloader/tst_sceneloader.cpp b/tests/auto/render/sceneloader/tst_sceneloader.cpp index 18cfe0aeb..9aac50c73 100644 --- a/tests/auto/render/sceneloader/tst_sceneloader.cpp +++ b/tests/auto/render/sceneloader/tst_sceneloader.cpp @@ -79,7 +79,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::QSceneLoader frontendSceneLoader; - frontendSceneLoader.setSource(QUrl(QStringLiteral("CorvetteMuseum"))); + frontendSceneLoader.setSource(QUrl(QStringLiteral("file:///CorvetteMuseum"))); Qt3DRender::Render::Scene sceneLoader; Qt3DRender::Render::SceneManager sceneManager; @@ -109,7 +109,7 @@ private Q_SLOTS: // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - const QUrl newUrl(QStringLiteral("Bownling_Green_KY")); + const QUrl newUrl(QStringLiteral("file:///Bownling_Green_KY")); updateChange->setValue(newUrl); updateChange->setPropertyName("source"); sceneLoader.sceneChangeEvent(updateChange); diff --git a/tests/auto/render/segmentvisitor/segmentvisitor.pro b/tests/auto/render/segmentvisitor/segmentvisitor.pro new file mode 100644 index 000000000..2f650aa0b --- /dev/null +++ b/tests/auto/render/segmentvisitor/segmentvisitor.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = segmentvisitor + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_segmentvisitor.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp new file mode 100644 index 000000000..d56daf159 --- /dev/null +++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp @@ -0,0 +1,814 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DRender/qbuffer.h> +#include <private/segmentsvisitor_p.h> +#include <private/nodemanagers_p.h> +#include <private/managers_p.h> +#include <private/geometryrenderer_p.h> +#include <private/geometryrenderermanager_p.h> +#include <private/buffermanager_p.h> +#include "testrenderer.h" + +using namespace Qt3DRender::Render; + +class TestVisitor : public SegmentsVisitor +{ +public: + TestVisitor(NodeManagers *manager) + : SegmentsVisitor(manager) + { + + } + + virtual void visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + { + m_segments.push_back(TestSegment(andx, a, bndx, b)); + } + + NodeManagers *nodeManagers() const + { + return m_manager; + } + + Qt3DCore::QNodeId nodeId() const + { + return m_nodeId; + } + + uint segmentCount() const + { + return m_segments.size(); + } + + bool verifySegment(uint segment, uint andx, uint bndx, QVector3D a, QVector3D b) const + { + if (segment >= uint(m_segments.size())) + return false; + if (andx != m_segments[segment].abcndx[0] + || bndx != m_segments[segment].abcndx[1]) + return false; + + if (!qFuzzyCompare(a, m_segments[segment].abc[0]) + || !qFuzzyCompare(b, m_segments[segment].abc[1])) + return false; + + return true; + } +private: + struct TestSegment + { + uint abcndx[2]; + QVector3D abc[2]; + TestSegment() + { + abcndx[0] = abcndx[1] = uint(-1); + } + + TestSegment(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + { + abcndx[0] = andx; + abcndx[1] = bndx; + abc[0] = a; + abc[1] = b; + } + }; + QVector<TestSegment> m_segments; +}; + +class tst_SegmentVisitor : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialize() + { + // WHEN + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + TestVisitor visitor(nodeManagers.data()); + + // THEN + QCOMPARE(visitor.nodeManagers(), nodeManagers.data()); + } + + void checkApplyEntity() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity()); + TestVisitor visitor(nodeManagers.data()); + + // WHEN + visitor.apply(entity.data()); + + // THEN + QCOMPARE(visitor.nodeId(), entity->id()); + QCOMPARE(visitor.segmentCount(), uint(0)); + } + + void checkApplyGeometryRenderer() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + QScopedPointer<GeometryRenderer> geometryRenderer(new GeometryRenderer()); + TestVisitor visitor(nodeManagers.data()); + + // WHEN + visitor.apply(geometryRenderer.data(), Qt3DCore::QNodeId()); + + // THEN + // tadaa, nothing should happen + } + + void testVisitSegments() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 3); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 0; + dataPtr[11] = 1.0f; + + dataPtr[12] = 1.0f; + dataPtr[13] = 0; + dataPtr[14] = 0; + dataPtr[15] = 0; + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(6); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,1), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 2,3, QVector3D(0,1,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifySegment(2, 4,5, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitSegmentsIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 5); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 1; + iDataPtr[3] = 2; + iDataPtr[4] = 2; + iDataPtr[5] = 3; + iDataPtr[6] = 0; + iDataPtr[7] = 2; + iDataPtr[8] = 1; + iDataPtr[9] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(2*5); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(5)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 0,2, QVector3D(0,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(4, 1,3, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitLineStrip() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0f; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + } + + void testVisitListStripIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 4); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + } + + void testVisitLineLoop() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0f; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(4)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + } + + void testVisitLineLoopIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 4); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(4)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + } + + void testVisitLineAdjacency() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 1.0f; + dataPtr[10] = 0; + dataPtr[12] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(1)); + QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitLinesAdjacencyIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 1.0f; + dataPtr[10] = 0; + dataPtr[12] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(1)); + QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + } +}; + +QTEST_MAIN(tst_SegmentVisitor) + +#include "tst_segmentvisitor.moc" diff --git a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp index 3310941ed..c6bd65324 100644 --- a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp +++ b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp @@ -55,9 +55,9 @@ private Q_SLOTS: renderer.setNodeManagers(&nodeManagers); job.setManagers(&nodeManagers); - renderCapture->requestCapture(42); - renderCapture->acknowledgeCaptureRequest(); - renderCapture->addRenderCapture(image); + renderCapture->requestCapture({ 42, QRect() }); + auto request = renderCapture->takeCaptureRequest(); + renderCapture->addRenderCapture(request.captureId, image); renderer.addRenderCaptureSendRequest(renderCapture->peerId()); //WHEN diff --git a/tests/auto/render/shader/shader.pro b/tests/auto/render/shader/shader.pro index 7c908e0f6..6e8a8ec2e 100644 --- a/tests/auto/render/shader/shader.pro +++ b/tests/auto/render/shader/shader.pro @@ -9,3 +9,4 @@ CONFIG += testcase SOURCES += tst_shader.cpp include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp index f6ed41a8b..067db55e7 100644 --- a/tests/auto/render/shader/tst_shader.cpp +++ b/tests/auto/render/shader/tst_shader.cpp @@ -30,6 +30,7 @@ #include <qbackendnodetester.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DRender/qshaderprogram.h> +#include "testrenderer.h" class tst_RenderShader : public Qt3DCore::QBackendNodeTester { @@ -39,6 +40,11 @@ private slots: void hasCoherentInitialState(); void matchesFrontendPeer(); void cleanupLeavesACoherentState(); + void dealWithPropertyChanges_data(); + void dealWithPropertyChanges(); + void checkSetRendererDirtyOnInitialization(); + void allowToChangeShaderCode_data(); + void allowToChangeShaderCode(); }; @@ -86,36 +92,180 @@ void tst_RenderShader::hasCoherentInitialState() void tst_RenderShader::matchesFrontendPeer() { - Qt3DRender::QShaderProgram *frontend = createFrontendShader(); - Qt3DRender::Render::Shader *backend = new Qt3DRender::Render::Shader(); + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + TestRenderer renderer; + Qt3DRender::Render::Shader backend; - simulateInitialization(frontend, backend); - QCOMPARE(backend->isLoaded(), false); - QVERIFY(backend->dna() != 0U); + backend.setRenderer(&renderer); + simulateInitialization(frontend.data(), &backend); + QCOMPARE(backend.isLoaded(), false); + QVERIFY(backend.dna() != 0U); for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i) - QCOMPARE(backend->shaderCode()[i], + QCOMPARE(backend.shaderCode()[i], frontend->shaderCode( static_cast<const Qt3DRender::QShaderProgram::ShaderType>(i))); } void tst_RenderShader::cleanupLeavesACoherentState() { - Qt3DRender::QShaderProgram *frontend = createFrontendShader(); - Qt3DRender::Render::Shader *shader = new Qt3DRender::Render::Shader(); + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + TestRenderer renderer; + Qt3DRender::Render::Shader shader; - simulateInitialization(frontend, shader); + shader.setRenderer(&renderer); + simulateInitialization(frontend.data(), &shader); - shader->cleanup(); + shader.cleanup(); - QCOMPARE(shader->isLoaded(), false); - QCOMPARE(shader->dna(), 0U); - QVERIFY(shader->uniformsNames().isEmpty()); - QVERIFY(shader->attributesNames().isEmpty()); - QVERIFY(shader->uniformBlockNames().isEmpty()); - QVERIFY(shader->uniforms().isEmpty()); - QVERIFY(shader->attributes().isEmpty()); - QVERIFY(shader->uniformBlocks().isEmpty()); - QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); + QCOMPARE(shader.isLoaded(), false); + QCOMPARE(shader.dna(), 0U); + QVERIFY(shader.uniformsNames().isEmpty()); + QVERIFY(shader.attributesNames().isEmpty()); + QVERIFY(shader.uniformBlockNames().isEmpty()); + QVERIFY(shader.uniforms().isEmpty()); + QVERIFY(shader.attributes().isEmpty()); + QVERIFY(shader.uniformBlocks().isEmpty()); + QCOMPARE(shader.status(), Qt3DRender::QShaderProgram::NotReady); +} + +void tst_RenderShader::dealWithPropertyChanges_data() +{ + QTest::addColumn<QByteArray>("property"); + QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type"); + + QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderCode") + << Qt3DRender::QShaderProgram::Vertex; + + QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderCode") + << Qt3DRender::QShaderProgram::TessellationControl; + + QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderCode") + << Qt3DRender::QShaderProgram::TessellationEvaluation; + + QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderCode") + << Qt3DRender::QShaderProgram::Geometry; + + QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderCode") + << Qt3DRender::QShaderProgram::Fragment; + + QTest::newRow("compute") << QByteArrayLiteral("computeShaderCode") + << Qt3DRender::QShaderProgram::Compute; +} + +void tst_RenderShader::dealWithPropertyChanges() +{ + // GIVEN + QFETCH(QByteArray, property); + QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); + + Qt3DRender::Render::Shader backend; + backend.setLoaded(true); + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("foo")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("foo")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), 0); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("bar")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); +} + +void tst_RenderShader::checkSetRendererDirtyOnInitialization() +{ + // GIVEN + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + Qt3DRender::Render::Shader shader; + TestRenderer renderer; + + shader.setRenderer(&renderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(frontend.data(), &shader); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); +} + +void tst_RenderShader::allowToChangeShaderCode_data() +{ + dealWithPropertyChanges_data(); +} + +void tst_RenderShader::allowToChangeShaderCode() +{ + // GIVEN + QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); + + Qt3DRender::Render::Shader backend; + backend.setLoaded(true); + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("foo")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("foo")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), 0); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("bar")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); } QTEST_APPLESS_MAIN(tst_RenderShader) diff --git a/tests/auto/render/shaderbuilder/input.json b/tests/auto/render/shaderbuilder/input.json new file mode 100644 index 000000000..5437bd5b5 --- /dev/null +++ b/tests/auto/render/shaderbuilder/input.json @@ -0,0 +1,90 @@ +{ + "nodes": [ + { + "uuid": "{00000000-0000-0000-0000-000000000001}", + "type": "worldPosition" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000002}", + "type": "texture" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000003}", + "type": "texCoord" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000004}", + "type": "lightIntensity" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000005}", + "type": "exposure" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000006}", + "type": "fragColor" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000007}", + "type": "sampleTexture" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000008}", + "type": "lightModel" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000009}", + "type": "exposureFunction" + } + ], + "edges": [ + { + "sourceUuid": "{00000000-0000-0000-0000-000000000002}", + "sourcePort": "texture", + "targetUuid": "{00000000-0000-0000-0000-000000000007}", + "targetPort": "sampler" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000003}", + "sourcePort": "texCoord", + "targetUuid": "{00000000-0000-0000-0000-000000000007}", + "targetPort": "coord" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000001}", + "sourcePort": "worldPosition", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "position" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000007}", + "sourcePort": "color", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "baseColor" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000004}", + "sourcePort": "lightIntensity", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "lightIntensity" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000008}", + "sourcePort": "outputColor", + "targetUuid": "{00000000-0000-0000-0000-000000000009}", + "targetPort": "inputColor" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000005}", + "sourcePort": "exposure", + "targetUuid": "{00000000-0000-0000-0000-000000000009}", + "targetPort": "exposure" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000009}", + "sourcePort": "outputColor", + "targetUuid": "{00000000-0000-0000-0000-000000000006}", + "targetPort": "fragColor" + } + ] +} diff --git a/tests/auto/render/shaderbuilder/lightmodel.es2.inc b/tests/auto/render/shaderbuilder/lightmodel.es2.inc new file mode 100644 index 000000000..8e603d9a8 --- /dev/null +++ b/tests/auto/render/shaderbuilder/lightmodel.es2.inc @@ -0,0 +1,6 @@ +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} diff --git a/tests/auto/render/shaderbuilder/lightmodel.gl3.inc b/tests/auto/render/shaderbuilder/lightmodel.gl3.inc new file mode 100644 index 000000000..31615dfcd --- /dev/null +++ b/tests/auto/render/shaderbuilder/lightmodel.gl3.inc @@ -0,0 +1,6 @@ +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} diff --git a/tests/auto/render/shaderbuilder/output.es2 b/tests/auto/render/shaderbuilder/output.es2 new file mode 100644 index 000000000..b543bc5ee --- /dev/null +++ b/tests/auto/render/shaderbuilder/output.es2 @@ -0,0 +1,36 @@ +#version 100 + +varying highp vec3 worldPosition; +uniform sampler2D texture; +varying highp vec2 texCoord; +uniform highp float lightIntensity; +uniform highp float exposure; +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} + +#line 9 +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} + +#line 11 + +void main() +{ + highp vec2 v2 = texCoord; + sampler2D v1 = texture; + highp float v3 = lightIntensity; + highp vec4 v5 = texture2D(v1, v2); + highp vec3 v0 = worldPosition; + highp float v4 = exposure; + highp vec4 v6 = lightModel(v5, v0, v3); + highp vec4 v7 = v6 * pow(2.0, v4); + gl_fragColor = v7; +} diff --git a/tests/auto/render/shaderbuilder/output.gl3 b/tests/auto/render/shaderbuilder/output.gl3 new file mode 100644 index 000000000..95a9c53fd --- /dev/null +++ b/tests/auto/render/shaderbuilder/output.gl3 @@ -0,0 +1,37 @@ +#version 150 core + +in vec3 worldPosition; +uniform sampler2D texture; +in vec2 texCoord; +uniform float lightIntensity; +uniform float exposure; +out vec4 fragColor; +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} + +#line 10 +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} + +#line 12 + +void main() +{ + vec2 v2 = texCoord; + sampler2D v1 = texture; + float v3 = lightIntensity; + vec4 v5 = texture2D(v1, v2); + vec3 v0 = worldPosition; + float v4 = exposure; + vec4 v6 = lightModel(v5, v0, v3); + vec4 v7 = v6 * pow(2.0, v4); + fragColor = v7; +} diff --git a/tests/auto/render/shaderbuilder/prototypes.json b/tests/auto/render/shaderbuilder/prototypes.json new file mode 100644 index 000000000..e9bf2e802 --- /dev/null +++ b/tests/auto/render/shaderbuilder/prototypes.json @@ -0,0 +1,237 @@ +{ + "worldPosition": { + "outputs": [ + "worldPosition" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec3 $worldPosition = worldPosition;", + "headerSnippets": [ "varying highp vec3 worldPosition;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec3 $worldPosition = worldPosition;", + "headerSnippets": [ "in vec3 worldPosition;" ] + } + ] + }, + "texture": { + "outputs": [ + "texture" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "sampler2D $texture = texture;", + "headerSnippets": [ "uniform sampler2D texture;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "sampler2D $texture = texture;", + "headerSnippets": [ "uniform sampler2D texture;" ] + } + ] + }, + "texCoord": { + "outputs": [ + "texCoord" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec2 $texCoord = texCoord;", + "headerSnippets": [ "varying highp vec2 texCoord;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec2 $texCoord = texCoord;", + "headerSnippets": [ "in vec2 texCoord;" ] + } + ] + }, + "lightIntensity": { + "outputs": [ + "lightIntensity" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp float $lightIntensity = lightIntensity;", + "headerSnippets": [ "uniform highp float lightIntensity;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "float $lightIntensity = lightIntensity;", + "headerSnippets": [ "uniform float lightIntensity;" ] + } + ] + }, + "exposure": { + "outputs": [ + "exposure" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp float $exposure = exposure;", + "headerSnippets": [ "uniform highp float exposure;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "float $exposure = exposure;", + "headerSnippets": [ "uniform float exposure;" ] + } + ] + }, + "fragColor": { + "inputs": [ + "fragColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "gl_fragColor = $fragColor;" + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "fragColor = $fragColor;", + "headerSnippets": [ "out vec4 fragColor;" ] + } + ] + }, + "sampleTexture": { + "inputs": [ + "sampler", + "coord" + ], + "outputs": [ + "color" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $color = texture2D($sampler, $coord);" + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $color = texture2D($sampler, $coord);" + } + ] + }, + "lightModel": { + "inputs": [ + "baseColor", + "position", + "lightIntensity" + ], + "outputs": [ + "outputColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", + "headerSnippets": [ "#pragma include lightmodel.es2.inc" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", + "headerSnippets": [ "#pragma include lightmodel.gl3.inc" ] + } + ] + }, + "exposureFunction": { + "inputs": [ + "inputColor", + "exposure" + ], + "outputs": [ + "outputColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);", + "headerSnippets": [ "#pragma include :/lightmodel.es2.inc" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $outputColor = $inputColor * pow(2.0, $exposure);", + "headerSnippets": [ "#pragma include :/lightmodel.gl3.inc" ] + } + ] + } +} diff --git a/tests/auto/render/shaderbuilder/shaderbuilder.pro b/tests/auto/render/shaderbuilder/shaderbuilder.pro new file mode 100644 index 000000000..bd5f7dfe2 --- /dev/null +++ b/tests/auto/render/shaderbuilder/shaderbuilder.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_shaderbuilder + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_shaderbuilder.cpp +RESOURCES += shaderbuilder.qrc + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/shaderbuilder/shaderbuilder.qrc b/tests/auto/render/shaderbuilder/shaderbuilder.qrc new file mode 100644 index 000000000..92ab0405c --- /dev/null +++ b/tests/auto/render/shaderbuilder/shaderbuilder.qrc @@ -0,0 +1,10 @@ +<RCC> + <qresource prefix="/"> + <file>prototypes.json</file> + <file>input.json</file> + <file>output.gl3</file> + <file>output.es2</file> + <file>lightmodel.gl3.inc</file> + <file>lightmodel.es2.inc</file> + </qresource> +</RCC> diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp new file mode 100644 index 000000000..6557acb6c --- /dev/null +++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp @@ -0,0 +1,548 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/private/shaderbuilder_p.h> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> +#include "testrenderer.h" + +Q_DECLARE_METATYPE(Qt3DRender::Render::ShaderBuilder::ShaderType) + +class tst_ShaderBuilder : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +private slots: + void shouldHaveGlobalDefaultPrototypes() + { + // GIVEN + + // THEN + QCOMPARE(Qt3DRender::Render::ShaderBuilder::getPrototypesFile(), QStringLiteral(":/prototypes/default.json")); + QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); + + // WHEN + Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); + + // THEN + QCOMPARE(Qt3DRender::Render::ShaderBuilder::getPrototypesFile(), QStringLiteral(":/prototypes.json")); + auto prototypeNames = Qt3DRender::Render::ShaderBuilder::getPrototypeNames(); + prototypeNames.sort(); + const auto expectedPrototypeNames = QStringList() << "exposure" + << "exposureFunction" + << "fragColor" + << "lightIntensity" + << "lightModel" + << "sampleTexture" + << "texCoord" + << "texture" + << "worldPosition"; + QCOMPARE(prototypeNames, expectedPrototypeNames); + } + + void shouldHaveInitialState() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder shaderBuilder; + + // THEN + QVERIFY(!shaderBuilder.isEnabled()); + QVERIFY(shaderBuilder.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QCOMPARE(shaderBuilder.shaderGraph(type), QUrl()); + QCOMPARE(shaderBuilder.shaderCode(type), QByteArray()); + QVERIFY(!shaderBuilder.isShaderCodeDirty(type)); + } + } + + void shouldHavePropertiesMirroringFromItsPeer_data() + { + QTest::addColumn<Qt3DRender::QShaderProgramBuilder*>("frontend"); + + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + QTest::newRow("empty") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + auto program = new Qt3DRender::QShaderProgram(frontend); + frontend->setShaderProgram(program); + QTest::newRow("shaderProgram") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setEnabledLayers({"foo", "bar"}); + QTest::newRow("enabledLayers") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QTest::newRow("vertex") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QTest::newRow("tessellationControl") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QTest::newRow("tessellationEvaluation") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QTest::newRow("geometry") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QTest::newRow("fragment") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QTest::newRow("compute") << frontend; + } + } + + void shouldHavePropertiesMirroringFromItsPeer() + { + // GIVEN + QFETCH(Qt3DRender::QShaderProgramBuilder*, frontend); + Qt3DRender::Render::ShaderBuilder backend; + + // WHEN + simulateInitialization(frontend, &backend); + + // THEN + QVERIFY(backend.isEnabled() == frontend->isEnabled()); + + if (frontend->shaderProgram()) + QCOMPARE(backend.shaderProgramId(), frontend->shaderProgram()->id()); + else + QVERIFY(backend.shaderProgramId().isNull()); + + QCOMPARE(backend.enabledLayers(), frontend->enabledLayers()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Vertex), frontend->vertexShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Vertex), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Vertex), !frontend->vertexShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationControl), frontend->tessellationControlShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationControl), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Geometry), frontend->geometryShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Geometry), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Geometry), !frontend->geometryShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Fragment), frontend->fragmentShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Fragment), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Fragment), !frontend->fragmentShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Compute), frontend->computeShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Compute), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Compute), !frontend->computeShaderGraph().isEmpty()); + + // WHEN + backend.cleanup(); + + // THEN + QVERIFY(!backend.isEnabled()); + QVERIFY(backend.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QCOMPARE(backend.shaderGraph(type), QUrl()); + QCOMPARE(backend.shaderCode(type), QByteArray()); + QVERIFY(!backend.isShaderCodeDirty(type)); + } + + delete frontend; + } + + void shouldHandleEnablePropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(true); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(false); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(!backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(true); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(!backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderProgramPropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + const auto programId = Qt3DCore::QNodeId::createId(); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(programId)); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderProgramId(), programId); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(Qt3DCore::QNodeId())); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(programId)); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleEnabledLayersPropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + const auto layers = QStringList() << "foo" << "bar"; + + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + const auto graphUrl = QUrl::fromEncoded("qrc:/input.json"); + backend.setShaderGraph(type, graphUrl); + } + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.enabledLayers(), layers); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.enabledLayers(), layers); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(!backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringList()); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(backend.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(!backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderGraphPropertiesChanges_data() + { + QTest::addColumn<QByteArray>("property"); + QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type"); + QTest::addColumn<QUrl>("graphUrl"); + + QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Vertex + << QUrl::fromEncoded("qrc:/vertex.json"); + + QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderGraph") + << Qt3DRender::Render::ShaderBuilder::TessellationControl + << QUrl::fromEncoded("qrc:/tesscontrol.json"); + + QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderGraph") + << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation + << QUrl::fromEncoded("qrc:/tesseval.json"); + + QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Geometry + << QUrl::fromEncoded("qrc:/geometry.json"); + + QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Fragment + << QUrl::fromEncoded("qrc:/fragment.json"); + + QTest::newRow("compute") << QByteArrayLiteral("computeShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Compute + << QUrl::fromEncoded("qrc:/compute.json"); + } + + void shouldHandleShaderGraphPropertiesChanges() + { + // GIVEN + QFETCH(QByteArray, property); + QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type); + QFETCH(QUrl, graphUrl); + + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QUrl()); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(!backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(graphUrl); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QUrl()); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(graphUrl); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(!backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderCodeGeneration_data() + { + QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type"); + + QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex; + QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl; + QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation; + QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry; + QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment; + QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute; + } + + void shouldHandleShaderCodeGeneration() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); + QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); + + QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type); + + const auto gl3Api = []{ + auto api = Qt3DRender::GraphicsApiFilterData(); + api.m_api = Qt3DRender::QGraphicsApiFilter::OpenGL; + api.m_profile = Qt3DRender::QGraphicsApiFilter::CoreProfile; + api.m_major = 3; + api.m_minor = 2; + return api; + }(); + + const auto es2Api = []{ + auto api = Qt3DRender::GraphicsApiFilterData(); + api.m_api = Qt3DRender::QGraphicsApiFilter::OpenGLES; + api.m_major = 2; + api.m_minor = 0; + return api; + }(); + + const auto readCode = [](const QString &suffix) -> QString { + const auto filePath = QStringLiteral(":/output.") + suffix; + QFile file(filePath); + if (!file.open(QFile::ReadOnly | QFile::Text)) + qFatal("File open failed: %s", qPrintable(filePath)); + return file.readAll(); + }; + + const auto gl3Code = readCode("gl3"); + const auto es2Code = readCode("es2"); + + Qt3DRender::Render::ShaderBuilder backend; + + // WHEN + const auto graphUrl = QUrl::fromEncoded("qrc:/input.json"); + backend.setShaderGraph(type, graphUrl); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + + // WHEN + backend.setGraphicsApi(gl3Api); + backend.generateCode(type); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(!backend.isShaderCodeDirty(type)); + QCOMPARE(backend.shaderCode(type), gl3Code); + + // WHEN + backend.setGraphicsApi(es2Api); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QCOMPARE(backend.shaderCode(type), gl3Code); + + // WHEN + backend.generateCode(type); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(!backend.isShaderCodeDirty(type)); +// QCOMPARE(backend.shaderCode(type), es2Code); + } +}; + +QTEST_MAIN(tst_ShaderBuilder) + +#include "tst_shaderbuilder.moc" diff --git a/tests/auto/render/skeleton/skeleton.pro b/tests/auto/render/skeleton/skeleton.pro new file mode 100644 index 000000000..8dbd1b3df --- /dev/null +++ b/tests/auto/render/skeleton/skeleton.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_skeleton + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_skeleton.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp new file mode 100644 index 000000000..499bb7cc7 --- /dev/null +++ b/tests/auto/render/skeleton/tst_skeleton.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/skeleton_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> +#include <testrenderer.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo) +Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData) +Q_DECLARE_METATYPE(Qt3DCore::Sqt) + +namespace { + +void linearizeTreeHelper(QJoint *joint, QVector<QJoint *> &joints) +{ + joints.push_back(joint); + for (const auto child : joint->childJoints()) + linearizeTreeHelper(child, joints); +} + +QVector<QJoint *> linearizeTree(QJoint *rootJoint) +{ + QVector<QJoint *> joints; + linearizeTreeHelper(rootJoint, joints); + return joints; +} + +} + +class tst_Skeleton : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + QSkeletonLoader skeleton; + + skeleton.setSource(QUrl::fromLocalFile("funnybones.json")); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + + // THEN + QCOMPARE(backendSkeleton.peerId(), skeleton.id()); + QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled()); + QCOMPARE(backendSkeleton.source(), skeleton.source()); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + + // GIVEN + Skeleton backendSkeleton2; + backendSkeleton2.setRenderer(&renderer); + backendSkeleton2.setSkeletonManager(nodeManagers.skeletonManager()); + QSkeleton skeleton2; + + QJoint *joint = new QJoint(); + skeleton2.setRootJoint(joint); + + // WHEN + simulateInitialization(&skeleton2, &backendSkeleton2); + + // THEN + QCOMPARE(backendSkeleton2.peerId(), skeleton2.id()); + QCOMPARE(backendSkeleton2.isEnabled(), skeleton2.isEnabled()); + QCOMPARE(backendSkeleton2.source(), QUrl()); + QCOMPARE(backendSkeleton2.rootJointId(), joint->id()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + + // THEN + QVERIFY(backendSkeleton.peerId().isNull()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.source(), QUrl()); + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + + // GIVEN + QSkeletonLoader skeleton; + skeleton.setSource(QUrl::fromLocalFile("skeleton1.json")); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + backendSkeleton.cleanup(); + + // THEN + QCOMPARE(backendSkeleton.source(), QUrl()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + } + + void checkPropertyChanges() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + backendSkeleton.setDataType(Skeleton::File); + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // Initialize to ensure skeleton manager is set + QSkeletonLoader skeleton; + skeleton.setSource(QUrl::fromLocalFile("skeleton1.json")); + simulateInitialization(&skeleton, &backendSkeleton); + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), true); + + // WHEN + const QUrl newSource = QUrl::fromLocalFile("terminator.json"); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("source"); + updateChange->setValue(newSource); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.source(), newSource); + + // WHEN + const QNodeId newRootJointId = QNodeId::createId(); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("rootJoint"); + updateChange->setValue(QVariant::fromValue(newRootJointId)); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.rootJointId(), newRootJointId); + } + + void checkStatusPropertyBackendNotification() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + TestArbiter arbiter; + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + backendSkeleton.setEnabled(true); + Qt3DCore::QBackendNodePrivate::get(&backendSkeleton)->setArbiter(&arbiter); + + // WHEN + backendSkeleton.setStatus(QSkeletonLoader::Error); + + // THEN + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error); + QCOMPARE(arbiter.events.count(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "status"); + QCOMPARE(change->value().value<QSkeletonLoader::Status>(), backendSkeleton.status()); + QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate, + false); + + arbiter.events.clear(); + + // WHEN + backendSkeleton.setStatus(QSkeletonLoader::Error); + + // THEN + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error); + QCOMPARE(arbiter.events.count(), 0); + + arbiter.events.clear(); + } + + void checkCreateFrontendJoint_data() + { + QTest::addColumn<QMatrix4x4>("inverseBindMatrix"); + QTest::addColumn<Qt3DCore::Sqt>("localPose"); + QTest::addColumn<QString>("jointName"); + QTest::addColumn<QJoint *>("expectedJoint"); + + QMatrix4x4 m; + Qt3DCore::Sqt localPose; + QTest::newRow("default") << m << localPose << QString() << new QJoint(); + + const QVector3D t(1.0f, 2.0f, 3.0f); + const QQuaternion r = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f); + const QVector3D s(1.5f, 2.5f, 3.5f); + localPose.scale = s; + localPose.rotation = r; + localPose.translation = t; + + + QString name = QLatin1String("Foo"); + QJoint *joint = new QJoint(); + joint->setTranslation(t); + joint->setRotation(r); + joint->setScale(s); + joint->setName(name); + joint->setInverseBindMatrix(m); + QTest::newRow("localPose") << m << localPose << name << joint; + + m.rotate(r); + m.scale(QVector3D(1.0f, 1.0f, 1.0f) / s); + m.translate(-t); + name = QLatin1String("Bar"); + + joint = new QJoint(); + joint->setTranslation(t); + joint->setRotation(r); + joint->setScale(s); + joint->setInverseBindMatrix(m); + joint->setName(name); + QTest::newRow("inverseBind") << m << localPose << name << joint; + } + + void checkCreateFrontendJoint() + { + // GIVEN + Skeleton backendSkeleton; + QFETCH(QMatrix4x4, inverseBindMatrix); + QFETCH(Qt3DCore::Sqt, localPose); + QFETCH(QString, jointName); + QFETCH(QJoint *, expectedJoint); + + // WHEN + const QJoint *actualJoint = backendSkeleton.createFrontendJoint(jointName, localPose, inverseBindMatrix); + + // THEN + QCOMPARE(actualJoint->scale(), expectedJoint->scale()); + QCOMPARE(actualJoint->rotation(), expectedJoint->rotation()); + QCOMPARE(actualJoint->translation(), expectedJoint->translation()); + QCOMPARE(actualJoint->inverseBindMatrix(), expectedJoint->inverseBindMatrix()); + QCOMPARE(actualJoint->name(), expectedJoint->name()); + + // Cleanup + delete actualJoint; + delete expectedJoint; + } + + void checkCreateFrontendJoints_data() + { + QTest::addColumn<SkeletonData>("skeletonData"); + QTest::addColumn<QJoint *>("expectedRootJoint"); + + QTest::newRow("empty") << SkeletonData() << (QJoint*)nullptr; + + SkeletonData skeletonData; + JointInfo rootJointInfo; + skeletonData.joints.push_back(rootJointInfo); + skeletonData.jointNames.push_back(QLatin1String("rootJoint")); + skeletonData.localPoses.push_back(Qt3DCore::Sqt()); + const int childCount = 10; + for (int i = 0; i < childCount; ++i) { + JointInfo childJointInfo; + childJointInfo.parentIndex = 0; + skeletonData.joints.push_back(childJointInfo); + + const float x = static_cast<float>(i); + Qt3DCore::Sqt localPose; + localPose.translation = QVector3D(x, x, x); + skeletonData.localPoses.push_back(localPose); + + skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); + } + + QJoint *rootJoint = new QJoint(); + for (int i = 0; i < childCount; ++i) { + QJoint *childJoint = new QJoint(); + const float x = static_cast<float>(i); + childJoint->setTranslation(QVector3D(x, x, x)); + rootJoint->addChildJoint(childJoint); + } + + QTest::newRow("wide") << skeletonData << rootJoint; + + skeletonData.joints.clear(); + skeletonData.joints.push_back(rootJointInfo); + for (int i = 0; i < childCount; ++i) { + JointInfo childJointInfo; + childJointInfo.parentIndex = i; + skeletonData.joints.push_back(childJointInfo); + + const float x = static_cast<float>(i); + Qt3DCore::Sqt localPose; + localPose.translation = QVector3D(x, x, x); + skeletonData.localPoses.push_back(localPose); + + skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); + } + + rootJoint = new QJoint(); + QJoint *previousJoint = rootJoint; + for (int i = 0; i < childCount; ++i) { + QJoint *childJoint = new QJoint(); + const float x = static_cast<float>(i); + childJoint->setTranslation(QVector3D(x, x, x)); + previousJoint->addChildJoint(childJoint); + previousJoint = childJoint; + } + + QTest::newRow("deep") << skeletonData << rootJoint; + } + + void checkCreateFrontendJoints() + { + // GIVEN + Skeleton backendSkeleton; + QFETCH(SkeletonData, skeletonData); + QFETCH(QJoint *, expectedRootJoint); + + // WHEN + QJoint *actualRootJoint = backendSkeleton.createFrontendJoints(skeletonData); + + // THEN + if (skeletonData.joints.isEmpty()) { + QVERIFY(actualRootJoint == expectedRootJoint); // nullptr + return; + } + + // Linearise the tree of joints and check them against the skeletonData + QVector<QJoint *> joints = linearizeTree(actualRootJoint); + QCOMPARE(joints.size(), skeletonData.joints.size()); + for (int i = 0; i < joints.size(); ++i) { + // Check the translations match + QCOMPARE(joints[i]->translation(), skeletonData.localPoses[i].translation); + } + + // Now we know the order of Joints match. Check the parents match too + for (int i = 0; i < joints.size(); ++i) { + // Get parent index from joint info + const int parentIndex = skeletonData.joints[i].parentIndex; + if (parentIndex == -1) { + QVERIFY(joints[i]->parent() == nullptr); + } else { + QCOMPARE(joints[i]->parent(), joints[parentIndex]); + } + } + + // Cleanup + delete actualRootJoint; + delete expectedRootJoint; + } +}; + +QTEST_APPLESS_MAIN(tst_Skeleton) + +#include "tst_skeleton.moc" diff --git a/tests/auto/render/texture/tst_texture.cpp b/tests/auto/render/texture/tst_texture.cpp index 9a84714a6..784186690 100644 --- a/tests/auto/render/texture/tst_texture.cpp +++ b/tests/auto/render/texture/tst_texture.cpp @@ -223,6 +223,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().width, 256); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -232,6 +234,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().height, 128); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -241,6 +245,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().depth, 16); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -250,6 +256,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().layers, 32); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -259,6 +267,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().samples, 64); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } QTEST_APPLESS_MAIN(tst_RenderTexture) diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp index 26916b2ab..ebb27953d 100644 --- a/tests/auto/render/transform/tst_transform.cpp +++ b/tests/auto/render/transform/tst_transform.cpp @@ -127,6 +127,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.isEnabled(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -138,6 +140,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.rotation(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -149,6 +153,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.scale(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -160,6 +166,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.translation(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } } diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp index 1e76751cc..9b6481423 100644 --- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp +++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp @@ -191,8 +191,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -291,15 +291,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*5); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -378,8 +378,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -477,15 +477,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*4); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -567,8 +567,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -660,15 +660,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*2); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -746,8 +746,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -843,15 +843,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*4); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -940,8 +940,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(8); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -1034,15 +1034,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(8); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp index 47e64eafe..b8578b294 100644 --- a/tests/auto/render/uniform/tst_uniform.cpp +++ b/tests/auto/render/uniform/tst_uniform.cpp @@ -123,6 +123,26 @@ private Q_SLOTS: QCOMPARE(v.constData<float>()[2], 1340.0f); QCOMPARE(v.constData<float>()[3], 1603.0f); } + { + // GIVEN + const QMatrix4x4 m1; + QMatrix4x4 m2; + m2.rotate(90.0f, 1.0f, 0.0f, 0.0f); + QMatrix4x4 m3; + m3.scale(2.5f); + QMatrix4x4 m4; + m4.translate(1.0f, 2.0f, 3.0f); + + const QVector<QMatrix4x4> matrices = (QVector<QMatrix4x4>() << m1 << m2 << m3 << m4); + UniformValue v(matrices); + + // THEN + for (int j = 0; j < matrices.size(); ++j) { + for (int i = 0; i < 16; ++i) { + QCOMPARE(v.constData<float>()[16 * j + i], matrices[j].constData()[i]); + } + } + } } void checkFromVariant() @@ -345,6 +365,51 @@ private Q_SLOTS: QVERIFY(!(v1 == v2)); QVERIFY(v1 != v2); } + + void checkSetData() + { + // GIVEN + const QMatrix4x4 m1; + QMatrix4x4 m2; + m2.rotate(90.0f, 1.0f, 0.0f, 0.0f); + QMatrix4x4 m3; + m3.scale(2.5f); + QMatrix4x4 m4; + m4.translate(1.0f, 2.0f, 3.0f); + + const QVector<QMatrix4x4> matrices1 = (QVector<QMatrix4x4>() << m1 << m2 << m3 << m4); + UniformValue v(matrices1); + + // WHEN + const QVector<QMatrix4x4> matrices2 = (QVector<QMatrix4x4>() << m4 << m3 << m2 << m1 << m4); + v.setData(matrices2); + + // THEN + for (int j = 0; j < matrices2.size(); ++j) { + for (int i = 0; i < 16; ++i) { + QCOMPARE(v.constData<float>()[16 * j + i], matrices2[j].constData()[i]); + } + } + + // GIVEN + const int positionCount = 10; + QVector<QVector3D> positions(positionCount); + for (int i = 0; i < positionCount; ++i) { + const QVector3D p(float(i), 10.0f * i, 100.0f * i); + positions[i] = p; + } + + UniformValue positionsUniform; + + // WHEN + positionsUniform.setData(positions); + + // THEN + const QVector3D *data = positionsUniform.constData<QVector3D>(); + for (int i = 0; i < positionCount; ++i) { + QCOMPARE(*(data + i), positions[i]); + } + } }; |