Qt Quick 3D Physics - Cannon Example
// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick import QtQuick3D import QtQuick3D.Physics import QtQuick3D.Helpers import QtQuick.Controls import QtQuick.Layouts Window { id: appWindow width: 800 height: 600 visible: true title: qsTr("Qt Quick 3D Physics - Cannon") DynamicsWorld {} View3D { width: parent.width height: parent.height focus: true environment: SceneEnvironment { antialiasingMode: SceneEnvironment.MSAA backgroundMode: SceneEnvironment.Color clearColor: "#f0f0f0" } PerspectiveCamera { id: camera position: Qt.vector3d(-4000, 5000, 10000) eulerRotation : Qt.vector3d(-20, -20, 0) clipFar: 500000 clipNear: 100 } DirectionalLight { eulerRotation: Qt.vector3d(-45, 45, 0) castsShadow: true brightness: 1 shadowMapQuality: Light.ShadowMapQualityVeryHigh shadowFactor: 100 } StaticRigidBody { eulerRotation: Qt.vector3d(-90, 0, 0) collisionShapes: PlaneShape {} Model { source: "#Rectangle" scale: Qt.vector3d(2000, 2000, 0) materials: PrincipledMaterial { baseColor: "green" } castsShadows: false receivesShadows: true } } Node { id: shapeSpawner property var instancesBoxes: [] property var instancesSpheres: [] property int stackCount: 0 function createStack(stackZ) { var size = 10; var extents = 400; for (var i = 0; i < size; i++) { for (var j = 0; j < size-i; j++) { var component = Qt.createComponent("box.qml"); let x = j*2 - size + i; let y = i*2 + 1; let z = -5*stackZ; let center = Qt.vector3d(x, y, z).times(0.5*extents); let box = component.createObject(shapeSpawner, {position: center, xyzExtents: extents}); instancesBoxes.push(box); if (box === null) { console.log("Error creating object"); } } } } function createBall(position, forward) { var diameter = 600; var speed = 20000; var component = Qt.createComponent("sphere.qml"); let sphere = component.createObject(shapeSpawner, {position: position, linearVelocity: forward.times(speed), sphereDiameter: diameter}); instancesSpheres.push(sphere); if (sphere === null) { console.log("Error creating object"); } } function reset() { instancesSpheres.forEach(sphere => { sphere.destroy(); }); instancesBoxes.forEach(boxes => { boxes.destroy(); }); instancesSpheres = []; instancesBoxes = []; for (var stackI = 0; stackI < stackSlider.value; stackI++) { shapeSpawner.createStack(stackI); } } } Crosshair { id: crossHair anchors.centerIn: parent } } Component.onCompleted: { shapeSpawner.reset() } WasdController { speed: 100 controlledObject: camera Keys.onPressed: (event)=> { handleKeyPress(event); if (event.key === Qt.Key_Space) { shapeSpawner.createBall(camera.position, camera.forward); } } Keys.onReleased: (event)=> { handleKeyRelease(event) } } Frame { background: Rectangle { color: "#c0c0c0" border.color: "#202020" } anchors.top: parent.top anchors.left: parent.left anchors.margins: 10 ColumnLayout { Label { text: "No. Stacks: " + stackSlider.value.toFixed(0) } Slider { id: stackSlider focusPolicy: Qt.NoFocus from: 1 to: 9 value: 4 stepSize: 1 snapMode: Slider.SnapOnRelease } Button { id: resetButton Layout.alignment: Qt.AlignHCenter text: "Reset scene" onClicked: shapeSpawner.reset() } Button { id: fireButton Layout.alignment: Qt.AlignHCenter text: "Fire!" onClicked: shapeSpawner.createBall(camera.position, camera.forward) } } } }