Qt Quick 3D物理-自定义形状示例

Qt Quick 3D Physics - Custom Shapes Example

Qt Quick 3D物理-自定义形状示例

Demonstrates using different shapes.

演示如何使用不同的形状。

This example demonstrates loading and spawning several rigid body meshes as well as animating them. The scene consists of a dice tower, a weave, a cup and a handful of dices. The cup is animated to collect spawning dices and put them in the dice tower. The dices will then roll down and out on the weave.

此示例演示加载和生成多个刚体网格以及设置它们的动画。场景由一个骰子塔、一个编织物、一个杯子和一把骰子组成。这个杯子被设置成动画来收集产卵骰子并将它们放入骰子塔。然后,骰子将在编织物上向下滚动。

QML

This is the full qml code for the example:

这是示例的完整qml代码:

Window {
    width: 1280
    height: 720
    visible: true
    title: qsTr("QtQuick3DPhysics Custom Shapes")

    DynamicsWorld {
        id: physicsWorld
        running: true
        typicalLength: 2
        enableCCD: true
    }

    View3D {
        id: viewport
        anchors.fill: parent

        environment: SceneEnvironment {
            clearColor: "white"
            backgroundMode: SceneEnvironment.SkyBox
            antialiasingMode: SceneEnvironment.MSAA
            antialiasingQuality: SceneEnvironment.High
            lightProbe: proceduralSky
        }

        Texture {
            id: proceduralSky
            textureData: ProceduralSkyTextureData {
                sunLongitude: -115
            }
        }

        Texture {
            id: weaveNormal
            source: "maps/weave.png"
            scaleU: 200
            scaleV: 200
            generateMipmaps: true
            mipFilter: Texture.Linear
        }

        Texture {
            id: numberNormal
            source: "maps/numbers-normal.png"
        }

        Texture {
            id: numberFill
            source: "maps/numbers.png"
            generateMipmaps: true
            mipFilter: Texture.Linear
        }

        Node {
            id: scene
            scale: Qt.vector3d(2, 2, 2)
            PerspectiveCamera {
                id: camera
                position: Qt.vector3d(-45, 20, 60)
                eulerRotation: Qt.vector3d(-6, -13, 0)
                clipFar: 1000
                clipNear: 0.1
            }

            DirectionalLight {
                eulerRotation: Qt.vector3d(-45, 25, 0)
                castsShadow: true
                brightness: 1
                shadowMapQuality: Light.ShadowMapQualityVeryHigh
            }

            StaticRigidBody {
                position: Qt.vector3d(-15, -8, 0)
                id: tablecloth

                Model {
                    geometry: HeightFieldGeometry {
                        id: tableclothGeometry
                        extents: Qt.vector3d(150, 20, 150)
                        heightMap: "maps/cloth-heightmap.png"
                        smoothShading: false
                    }
                    materials: PrincipledMaterial {
                        baseColor: "#447722"
                        roughness: 0.8
                        normalMap: weaveNormal
                        normalStrength: 0.7
                    }
                }

                collisionShapes: HeightFieldShape {
                    id: hfShape
                    extents: tableclothGeometry.extents
                    heightMap: "maps/cloth-heightmap.png"
                }
            }

            DynamicRigidBody {
                id: diceCup
                isKinematic: true
                mass: 0
                property vector3d restPos: Qt.vector3d(11, 6, 0)
                position: restPos
                pivot: Qt.vector3d(0, 6, 0)
                collisionShapes: TriangleMeshShape {
                    id: cupShape
                    meshSource: "meshes/simpleCup.mesh"
                }
                Model {
                    source: "meshes/cup.mesh"
                    materials: PrincipledMaterial {
                        baseColor: "#cc9988"
                        roughness: 0.3
                        metalness: 1
                    }
                }
                Behavior on eulerRotation.z {
                    NumberAnimation { duration: 1500 }
                }
                Behavior on position {
                    PropertyAnimation { duration: 1500 }
                }
            }

            StaticRigidBody {
                id: diceTower
                x: -4
                Model {
                    id: testModel
                    source: "meshes/tower.mesh"
                    materials: [
                        PrincipledMaterial {
                            baseColor: "#ccccce"
                            roughness: 0.3
                        },
                        PrincipledMaterial {
                            id: glassMaterial
                            baseColor: "#aaaacc"
                            transmissionFactor: 0.95
                            thicknessFactor: 1
                            roughness: 0.05
                        }
                    ]
                }
                collisionShapes: TriangleMeshShape {
                    id: triShape
                    meshSource: "meshes/tower.mesh"
                }
            }

            Component {
                id: diceComponent

                DynamicRigidBody {
                    id: thisBody
                    function randomInRange(min, max) {
                        return Math.random() * (max - min) + min;
                    }

                    function restore() {
                        reset(initialPosition, eulerRotation)
                    }

                    scale: Qt.vector3d(scaleFactor, scaleFactor, scaleFactor)
                    eulerRotation: Qt.vector3d(randomInRange(0, 360),
                                               randomInRange(0, 360),
                                               randomInRange(0, 360))

                    property vector3d initialPosition: Qt.vector3d(11 + 1.5*Math.cos(index/(Math.PI/4)),
                                                                   5 + index * 1.5,
                                                                   0)
                    position: initialPosition

                    property real scaleFactor: randomInRange(0.8, 1.4)
                    property color baseCol: Qt.hsla(randomInRange(0, 1),
                                                    randomInRange(0.6, 1.0),
                                                    randomInRange(0.4, 0.7),
                                                    1.0)

                    collisionShapes: ConvexMeshShape {
                        id: diceShape
                        meshSource: Math.random() < 0.25 ? "meshes/icosahedron.mesh"
                                  : Math.random() < 0.5 ? "meshes/dodecahedron.mesh"
                                  : Math.random() < 0.75 ? "meshes/octahedron.mesh"
                                                         : "meshes/tetrahedron.mesh"
                    }

                    Model {
                        id: thisModel
                        source: diceShape.meshSource
                        materials: PrincipledMaterial {
                            metalness: 1.0
                            roughness: randomInRange(0.2, 0.6)
                            baseColor: baseCol
                            emissiveMap: numberFill
                            emissiveFactor: Qt.vector3d(1, 1, 1)
                            normalMap: numberNormal
                            normalStrength: 0.75
                        }
                    }
                }
            }

            Repeater3D {
                id: dicePool
                model: 25
                delegate: diceComponent
                function restore() {
                    for (let i = 0; i < count; i++) {
                        objectAt(i).restore()
                    }
                }
            }

            SequentialAnimation {
                running: physicsWorld.running
                PauseAnimation { duration: 1500 }
                ScriptAction { script: diceCup.position = Qt.vector3d(4, 45, 0) }
                PauseAnimation { duration: 1500 }
                ScriptAction { script: { diceCup.eulerRotation.z = 130; diceCup.position = Qt.vector3d(0, 45, 0) } }
                PauseAnimation { duration: 3000 }
                ScriptAction { script: { diceCup.eulerRotation.z = 0; diceCup.position = Qt.vector3d(4, 45, 0) } }
                PauseAnimation { duration: 1500 }
                ScriptAction { script: diceCup.position = diceCup.restPos }
                PauseAnimation { duration: 2000 }
                ScriptAction { script: dicePool.restore() }
                loops: Animation.Infinite
            }
        } // scene
    } // View3D

    WasdController {
        keysEnabled: true
        controlledObject: camera
        speed: 0.2
    }
}

Enivronment

环境

As usual it contains a DynamicsWorld and a View3D. In the View3D we have our environment which sets up a lightprobe:

​像往常一样,它包含DynamicsWorld和View3D。在View3D中,我们的环境设置了一个光探针:

environment: SceneEnvironment {
    clearColor: "white"
    backgroundMode: SceneEnvironment.SkyBox
    antialiasingMode: SceneEnvironment.MSAA
    antialiasingQuality: SceneEnvironment.High
    lightProbe: proceduralSky
}

Textures

纹理

We define four textures which will be used for the skybox, the weave and the numbers on the dice:

我们定义了四种纹理,分别用于天空盒、编织和骰子上的数字:

Texture {
    id: proceduralSky
    textureData: ProceduralSkyTextureData {
        sunLongitude: -115
    }
}

Texture {
    id: weaveNormal
    source: "maps/weave.png"
    scaleU: 200
    scaleV: 200
    generateMipmaps: true
    mipFilter: Texture.Linear
}

Texture {
    id: numberNormal
    source: "maps/numbers-normal.png"
}

Texture {
    id: numberFill
    source: "maps/numbers.png"
    generateMipmaps: true
    mipFilter: Texture.Linear
}

Scene

场景

We have a Node which contains our scene with the camera and a directional light:

我们有一个节点,其中包含带有摄影机和平行光的场景:

id: scene
scale: Qt.vector3d(2, 2, 2)
PerspectiveCamera {
    id: camera
    position: Qt.vector3d(-45, 20, 60)
    eulerRotation: Qt.vector3d(-6, -13, 0)
    clipFar: 1000
    clipNear: 0.1
}

DirectionalLight {
    eulerRotation: Qt.vector3d(-45, 25, 0)
    castsShadow: true
    brightness: 1
    shadowMapQuality: Light.ShadowMapQualityVeryHigh
}

Weave

编织

We add the weave which is a StaticRigidBody consisting of a model with a weave texture and a HeightFieldShape for collision.

​我们添加了一个weave,它是一个StaticRigidBody,由一个具有weave纹理的模型和一个用于碰撞的HeightFieldShape组成。

StaticRigidBody {
    position: Qt.vector3d(-15, -8, 0)
    id: tablecloth

    Model {
        geometry: HeightFieldGeometry {
            id: tableclothGeometry
            extents: Qt.vector3d(150, 20, 150)
            heightMap: "maps/cloth-heightmap.png"
            smoothShading: false
        }
        materials: PrincipledMaterial {
            baseColor: "#447722"
            roughness: 0.8
            normalMap: weaveNormal
            normalStrength: 0.7
        }
    }

    collisionShapes: HeightFieldShape {
        id: hfShape
        extents: tableclothGeometry.extents
        heightMap: "maps/cloth-heightmap.png"
    }
}

Cup

杯子

We define the cup as a DynamicRigidBody with a Model and a TriangleMeshShape as the collision shape. It has a Behavior on the eulerRotation and position properties as these are part of an animation.

​我们将杯子定义为DynamicRigidBody,并将模型和三角形网格形状定义为碰撞形状。它在eulerRotation和position属性上具有行为,因为它们是动画的一部分。

DynamicRigidBody {
    id: diceCup
    isKinematic: true
    mass: 0
    property vector3d restPos: Qt.vector3d(11, 6, 0)
    position: restPos
    pivot: Qt.vector3d(0, 6, 0)
    collisionShapes: TriangleMeshShape {
        id: cupShape
        meshSource: "meshes/simpleCup.mesh"
    }
    Model {
        source: "meshes/cup.mesh"
        materials: PrincipledMaterial {
            baseColor: "#cc9988"
            roughness: 0.3
            metalness: 1
        }
    }
    Behavior on eulerRotation.z {
        NumberAnimation { duration: 1500 }
    }
    Behavior on position {
        PropertyAnimation { duration: 1500 }
    }
}

Tower

The tower is just a StaticRigidBody with a Model and a TriangleMeshShape for collision.

​该塔只是一个StaticRigidBody,带有一个模型和一个用于碰撞的三角形网格形状。

StaticRigidBody {
    id: diceTower
    x: -4
    Model {
        id: testModel
        source: "meshes/tower.mesh"
        materials: [
            PrincipledMaterial {
                baseColor: "#ccccce"
                roughness: 0.3
            },
            PrincipledMaterial {
                id: glassMaterial
                baseColor: "#aaaacc"
                transmissionFactor: 0.95
                thicknessFactor: 1
                roughness: 0.05
            }
        ]
    }
    collisionShapes: TriangleMeshShape {
        id: triShape
        meshSource: "meshes/tower.mesh"
    }
}

Dices

骰子

To generate the dices we use a Component and a Repeater3D. The Component contains a DynamicRigidBody with a ConvexMeshShape and a Model. The position, color, scale and mesh source are randomly generated for each die.

​为了生成骰子,我们使用组件和Repeater3D。组件包含一个带有凸面网格形状的DynamicRigidBody和一个模型。位置、颜色、比例和网格源是为每个模具随机生成的。

Component {
    id: diceComponent

    DynamicRigidBody {
        id: thisBody
        function randomInRange(min, max) {
            return Math.random() * (max - min) + min;
        }

        function restore() {
            reset(initialPosition, eulerRotation)
        }

        scale: Qt.vector3d(scaleFactor, scaleFactor, scaleFactor)
        eulerRotation: Qt.vector3d(randomInRange(0, 360),
                                   randomInRange(0, 360),
                                   randomInRange(0, 360))

        property vector3d initialPosition: Qt.vector3d(11 + 1.5*Math.cos(index/(Math.PI/4)),
                                                       5 + index * 1.5,
                                                       0)
        position: initialPosition

        property real scaleFactor: randomInRange(0.8, 1.4)
        property color baseCol: Qt.hsla(randomInRange(0, 1),
                                        randomInRange(0.6, 1.0),
                                        randomInRange(0.4, 0.7),
                                        1.0)

        collisionShapes: ConvexMeshShape {
            id: diceShape
            meshSource: Math.random() < 0.25 ? "meshes/icosahedron.mesh"
                      : Math.random() < 0.5 ? "meshes/dodecahedron.mesh"
                      : Math.random() < 0.75 ? "meshes/octahedron.mesh"
                                             : "meshes/tetrahedron.mesh"
        }

        Model {
            id: thisModel
            source: diceShape.meshSource
            materials: PrincipledMaterial {
                metalness: 1.0
                roughness: randomInRange(0.2, 0.6)
                baseColor: baseCol
                emissiveMap: numberFill
                emissiveFactor: Qt.vector3d(1, 1, 1)
                normalMap: numberNormal
                normalStrength: 0.75
            }
        }
    }
}

Repeater3D {
    id: dicePool
    model: 25
    delegate: diceComponent
    function restore() {
        for (let i = 0; i < count; i++) {
            objectAt(i).restore()
        }
    }
}

Animation

动画

To make the dices move from the cup to the dice tower we animate the cup and move it up and then tip it over. This is done using a SequentialAnimation:

​为了使骰子从杯子移动到骰子塔,我们设置了杯子的动画,并将其向上移动,然后将其翻转过来。这是使用SequentialAnimation完成的:

SequentialAnimation {
    running: physicsWorld.running
    PauseAnimation { duration: 1500 }
    ScriptAction { script: diceCup.position = Qt.vector3d(4, 45, 0) }
    PauseAnimation { duration: 1500 }
    ScriptAction { script: { diceCup.eulerRotation.z = 130; diceCup.position = Qt.vector3d(0, 45, 0) } }
    PauseAnimation { duration: 3000 }
    ScriptAction { script: { diceCup.eulerRotation.z = 0; diceCup.position = Qt.vector3d(4, 45, 0) } }
    PauseAnimation { duration: 1500 }
    ScriptAction { script: diceCup.position = diceCup.restPos }
    PauseAnimation { duration: 2000 }
    ScriptAction { script: dicePool.restore() }
    loops: Animation.Infinite
}

Controller

控制器

Finally a WasdController is added to be able to control the camera using a keyboard:

​最后,添加了WasdController,可以使用键盘控制摄像机:

WasdController {
    keysEnabled: true
    controlledObject: camera
    speed: 0.2
}

Files:

Images:

© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This directory contains the Qt3D project for Qt5: * Qt3D QML bindings and * Qt3D C++ APIs Building Qt3D ================== Qt5 is a rapidly changing bleeding edge environment. This branch is our initial support for it and thus is also rapidly changing and bleeding edge. This branch is experimental, and unsupported. This information is provided for advanced use only. No guarantees about API stability or even if this works at all are supplied, use at your own risk. First fetch the Qt5 source tree and Qt3D master branch: cd ~/depot git clone ssh://codereview.qt-project.org:29418/qt/qt5.git cd qt5 ./init-repository --codereview-username \ --module-subset=qtbase,qtsvg,qtdeclarative,qttools,qtxmlpatterns,qtdoc,qlalr,qtrepotools,qtqa,qtlocation,qt3d git submodule foreach "git fetch gerrit && git reset --hard gerrit/master" cd qt3d scp -p -P 29418 codereview.qt-project.org:hooks/commit-msg .git/hooks/ git fetch gerrit git checkout --track -b master gerrit/master If you are reading this file then somehow you probably already got this far anyway. Now build Qt5, which will also build Qt3D as a module: cd ~/build mkdir qt5 cd qt5 ~/depot/qt5/configure -developer-build -opensource -confirm-license -no-webkit -no-phonon -nomake tests \ -nomake examples -declarative -opengl -svg && make -j 4 What's in Qt3D ================== Directory structure: src/threed/ This is the main library of the Qt3D project, containing abstractions for cross-platform GL, shaders, lighting models, and so on. src/plugins/ Scene format loading plugins. src/imports/ QML import plugins. util/ Various utilities that are useful when working with Qt3D. examples/ Some examples of using Qt3D QML bindings and Qt3D C++ API. demos/ Some more complex demos of using Qt3D QML bindings and Qt3D C++ API. tests/auto/qml3d/ Unit tests for the QML bindings. tests/auto/threed/ Unit tests for the C++ API doc/ Documentation. devices/symbian/ Symbian deployment file Documentation ============= The documentation can be generated with "make docs". It will be placed into "doc/html" in the build directory. Packages ======== This section is only for those developing Qt3D. Read on to discover how the building of packages works. This section is also important if you want to change how the structure of the Qt3D pro files work. To build Qt3D, run: qmake && make The .pro files will cause the toolchain to place the libraries, QML files and meshes of Qt3D directly into place, as part of the compile process. The files go into the bin/ directory, and the executables can be run directly from there. If you are doing a developer build, plugins will be installed in such a way that Qt will find them. After building the tree the install step is invoked using the INSTALL_ROOT environment export to cause the installation rules to place all the files into a sandboxed install tree, ready for packaging: INSTALL_ROOT=tmp make install Examples ======== Some examples require assimp library to parse the content. Go to http://assimp.sourceforge.net/ and build and install the assimp library. Then configure Qt3D to include assimp and run qmake && make.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值