summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/animation/animation.pro7
-rw-r--r--tests/auto/animation/animationutils/animationutils.qrc1
-rw-r--r--tests/auto/animation/animationutils/clip5.json1401
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp864
-rw-r--r--tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp7
-rw-r--r--tests/auto/animation/channelmapping/tst_channelmapping.cpp34
-rw-r--r--tests/auto/animation/clipanimator/tst_clipanimator.cpp19
-rw-r--r--tests/auto/animation/clock/clock.pro12
-rw-r--r--tests/auto/animation/clock/tst_clock.cpp111
-rw-r--r--tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp1
-rw-r--r--tests/auto/animation/qcallbackmapping/qcallbackmapping.pro12
-rw-r--r--tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp223
-rw-r--r--tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp7
-rw-r--r--tests/auto/animation/qclipanimator/tst_qclipanimator.cpp57
-rw-r--r--tests/auto/animation/qclock/qclock.pro12
-rw-r--r--tests/auto/animation/qclock/tst_qclock.cpp165
-rw-r--r--tests/auto/animation/qskeletonmapping/qskeletonmapping.pro12
-rw-r--r--tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp175
-rw-r--r--tests/auto/animation/skeleton/skeleton.pro12
-rw-r--r--tests/auto/animation/skeleton/tst_skeleton.cpp146
-rw-r--r--tests/auto/auto.pro14
-rw-r--r--tests/auto/core/aspectcommanddebugger/tst_aspectcommanddebugger.cpp4
-rw-r--r--tests/auto/core/core.pro27
-rw-r--r--tests/auto/core/qarmature/qarmature.pro11
-rw-r--r--tests/auto/core/qarmature/tst_qarmature.cpp167
-rw-r--r--tests/auto/core/qjoint/qjoint.pro12
-rw-r--r--tests/auto/core/qjoint/tst_qjoint.cpp413
-rw-r--r--tests/auto/core/qskeleton/qskeleton.pro11
-rw-r--r--tests/auto/core/qskeleton/tst_qskeleton.cpp210
-rw-r--r--tests/auto/core/qskeletonloader/qskeletonloader.pro12
-rw-r--r--tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp276
-rw-r--r--tests/auto/core/vector3d_base/tst_vector3d_base.cpp705
-rw-r--r--tests/auto/core/vector3d_base/vector3d_base.pro7
-rw-r--r--tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp816
-rw-r--r--tests/auto/core/vector3d_sse/vector3d_sse.pro8
-rw-r--r--tests/auto/core/vector4d_base/tst_vector4d_base.cpp785
-rw-r--r--tests/auto/core/vector4d_base/vector4d_base.pro7
-rw-r--r--tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp830
-rw-r--r--tests/auto/core/vector4d_sse/vector4d_sse.pro9
-rw-r--r--tests/auto/quick3d/3dcore/3dcore.qml5
-rw-r--r--tests/auto/quick3d/3drender/3drender.qml2
-rw-r--r--tests/auto/render/armature/armature.pro12
-rw-r--r--tests/auto/render/armature/tst_armature.cpp120
-rw-r--r--tests/auto/render/blitframebuffer/blitframebuffer.pro12
-rw-r--r--tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp196
-rw-r--r--tests/auto/render/buffer/tst_buffer.cpp65
-rw-r--r--tests/auto/render/commons/testrenderer.h1
-rw-r--r--tests/auto/render/ddstextures/data/16x16-etc1.pkmbin0 -> 144 bytes
-rw-r--r--tests/auto/render/ddstextures/data/16x16-etc2.pkmbin0 -> 144 bytes
-rw-r--r--tests/auto/render/ddstextures/ddstextures.pro4
-rw-r--r--tests/auto/render/ddstextures/tst_ddstextures.cpp2
-rw-r--r--tests/auto/render/entity/tst_entity.cpp20
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/BLACKLIST7
-rw-r--r--tests/auto/render/geometry/tst_geometry.cpp29
-rw-r--r--tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp88
-rw-r--r--tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp86
-rw-r--r--tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp125
-rw-r--r--tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp125
-rw-r--r--tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp138
-rw-r--r--tests/auto/render/joint/joint.pro13
-rw-r--r--tests/auto/render/joint/tst_joint.cpp242
-rw-r--r--tests/auto/render/layerfiltering/tst_layerfiltering.cpp502
-rw-r--r--tests/auto/render/loadscenejob/tst_loadscenejob.cpp31
-rw-r--r--tests/auto/render/meshfunctors/tst_meshfunctors.cpp32
-rw-r--r--tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp1
-rw-r--r--tests/auto/render/proximityfilter/proximityfilter.pro12
-rw-r--r--tests/auto/render/proximityfilter/tst_proximityfilter.cpp133
-rw-r--r--tests/auto/render/proximityfiltering/proximityfiltering.pro13
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp287
-rw-r--r--tests/auto/render/qattribute/tst_qattribute.cpp6
-rw-r--r--tests/auto/render/qblitframebuffer/qblitframebuffer.pro11
-rw-r--r--tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp338
-rw-r--r--tests/auto/render/qbuffer/tst_qbuffer.cpp1
-rw-r--r--tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp16
-rw-r--r--tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp7
-rw-r--r--tests/auto/render/qmesh/tst_qmesh.cpp34
-rw-r--r--tests/auto/render/qproximityfilter/qproximityfilter.pro12
-rw-r--r--tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp270
-rw-r--r--tests/auto/render/qrendercapture/tst_qrendercapture.cpp7
-rw-r--r--tests/auto/render/qrendersettings/tst_qrendersettings.cpp37
-rw-r--r--tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro12
-rw-r--r--tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp601
-rw-r--r--tests/auto/render/render.pro45
-rw-r--r--tests/auto/render/rendercapture/tst_rendercapture.cpp14
-rw-r--r--tests/auto/render/renderer/renderer.pro9
-rw-r--r--tests/auto/render/renderer/tst_renderer.cpp234
-rw-r--r--tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp350
-rw-r--r--tests/auto/render/sceneloader/tst_sceneloader.cpp4
-rw-r--r--tests/auto/render/segmentvisitor/segmentvisitor.pro12
-rw-r--r--tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp814
-rw-r--r--tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp6
-rw-r--r--tests/auto/render/shader/shader.pro1
-rw-r--r--tests/auto/render/shader/tst_shader.cpp188
-rw-r--r--tests/auto/render/shaderbuilder/input.json90
-rw-r--r--tests/auto/render/shaderbuilder/lightmodel.es2.inc6
-rw-r--r--tests/auto/render/shaderbuilder/lightmodel.gl3.inc6
-rw-r--r--tests/auto/render/shaderbuilder/output.es236
-rw-r--r--tests/auto/render/shaderbuilder/output.gl337
-rw-r--r--tests/auto/render/shaderbuilder/prototypes.json237
-rw-r--r--tests/auto/render/shaderbuilder/shaderbuilder.pro13
-rw-r--r--tests/auto/render/shaderbuilder/shaderbuilder.qrc10
-rw-r--r--tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp548
-rw-r--r--tests/auto/render/skeleton/skeleton.pro13
-rw-r--r--tests/auto/render/skeleton/tst_skeleton.cpp405
-rw-r--r--tests/auto/render/texture/tst_texture.cpp10
-rw-r--r--tests/auto/render/transform/tst_transform.cpp8
-rw-r--r--tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp50
-rw-r--r--tests/auto/render/uniform/tst_uniform.cpp65
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
new file mode 100644
index 000000000..62ae2a11f
--- /dev/null
+++ b/tests/auto/render/ddstextures/data/16x16-etc1.pkm
Binary files differ
diff --git a/tests/auto/render/ddstextures/data/16x16-etc2.pkm b/tests/auto/render/ddstextures/data/16x16-etc2.pkm
new file mode 100644
index 000000000..be391113e
--- /dev/null
+++ b/tests/auto/render/ddstextures/data/16x16-etc2.pkm
Binary files differ
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]);
+ }
+ }
};