Qt Quick 3D物理-质量示例

Qt Quick 3D Physics - Mass Example

Qt Quick 3D物理-质量示例

Demonstrates different ways of setting mass and inertia of a body.

演示设置物体质量和惯性的不同方法。

This example demonstrates three different ways of setting up the mass and inertia of a body. The scene consists of three bodies that consist of three spheres stacked vertically. These bodies all have the same mass but differing centers of mass and inertia tensors giving them different behavior when colliding.

这个例子演示了设置物体质量和惯性的三种不同方法。场景由三个实体组成,这三个实体由三个垂直叠放的球体组成。这些物体都具有相同的质量,但不同的质心和惯性张量,使得它们在碰撞时具有不同的行为。

Setup

设置

We first add our DynamicsWorld:

​我们首先添加DynamicsWorld:

DynamicsWorld {
    running: true
    gravity: Qt.vector3d(0, -9.81, 0)
    typicalLength: 1
    typicalSpeed: 10
}

We do the usual setup where we have an environment, camera and lights:

我们通常设置环境、摄像机和灯光:

environment: SceneEnvironment {
    clearColor: "lightblue"
    backgroundMode: SceneEnvironment.Color
}

PerspectiveCamera {
    id: camera
    position: Qt.vector3d(0, 2, 5)
    eulerRotation: Qt.vector3d(-10, 0, 0)
    clipFar: 100
    clipNear: 0.01
}

DirectionalLight {
    eulerRotation.x: -45
    eulerRotation.y: 45
    castsShadow: true
    brightness: 1
    shadowFactor: 100
}

Physical objects

物体

We have our regular static plane:

我们有常规的静态平面:

StaticRigidBody {
    position: Qt.vector3d(0, 0, 0)
    eulerRotation: Qt.vector3d(-90, 0, 0)
    collisionShapes: PlaneShape {}
    Model {
        source: "#Rectangle"
        materials: DefaultMaterial {
            diffuseColor: "green"
        }
        castsShadows: false
        receivesShadows: true
    }
}

We define a custom QML class for our body which we call RolyPoly since they behave like so called roly-poly toys. The RolyPoly is a DynamicRigidBody with three spherical collision shapes:

​我们为我们的身体定义了一个定制的QML类,我们称之为RolyPoly,因为它们的行为类似于所谓的roly-poly玩具。RolyPoly是具有三种球形碰撞形状的DynamicRigidBody:

DynamicRigidBody {
    property string color: "blue"

    collisionShapes: [
        SphereShape {
            id: sphere0
            diameter:  1
        },
        SphereShape {
            id: sphere1
            diameter:  0.8
            position: Qt.vector3d(0, 0.6, 0)
        },
        SphereShape {
            id: sphere2
            diameter:  0.6
            position: Qt.vector3d(0, 1.1, 0)
        }
    ]

    Model {
        source: "#Sphere"
        position: sphere0.position
        scale: Qt.vector3d(1,1,1).times(sphere0.diameter*0.01)
        materials: PrincipledMaterial {
            baseColor: color
        }
    }

    Model {
        source: "#Sphere"
        position: sphere1.position
        scale: Qt.vector3d(1,1,1).times(sphere1.diameter*0.01)
        materials: PrincipledMaterial {
            baseColor: color
        }
    }

    Model {
        source: "#Sphere"
        position: sphere2.position
        scale: Qt.vector3d(1,1,1).times(sphere2.diameter*0.01)
        materials: PrincipledMaterial {
            baseColor: color
        }
    }
}

We then add three roly-polys to our scene:

然后,我们将三个角色多边形添加到场景中:

RolyPoly {
    position: Qt.vector3d(-2, 0.5, 0)
    color: "blue"

    mass: 0.9
    centerOfMassPosition: Qt.vector3d(0, -0.5, 0)
    inertiaTensor: Qt.vector3d(0.217011, 0.0735887, 0.217011)
    massMode: DynamicRigidBody.MassAndInertiaTensor
}

RolyPoly {
    position: Qt.vector3d(0, 0.5, 0)
    color: "purple"

    mass: 0.9
    centerOfMassPosition: Qt.vector3d(0, -0.5, 0)
    inertiaTensor: Qt.vector3d(0.05, 100, 100)
    massMode: DynamicRigidBody.MassAndInertiaTensor
}

RolyPoly {
    position: Qt.vector3d(2, 0.5, 0)
    color: "red"

    mass: 0.9
    massMode: DynamicRigidBody.Mass
}

The purple and blue roly-poly has a custom center of mass and inertia tensor. Since bodies use uniform density by default and will calculate mass and inertia automatically we set massMode to DynamicRigidBody.MassAndInertiaTensor in our purple and blue bodies to use our provided mass and inertia tensors instead. The lower center of mass will make it so the bodies will always stand up after being pushed over. The inertia tensor of the purple body makes it so it will wobble easily in one direction but hardly in the other. The red body has an automatically calculated center of mass and will therefore keep lying down after being knocked over.

​紫色和蓝色的roly多边形有一个自定义的质量中心和惯性张量。由于默认情况下实体使用均匀密度,并将自动计算质量和惯性,因此我们将massMode设置为DynamicRigidBody.MassAndInertiaTensor后,紫色和蓝色物体中的质量和惯性张量使用我们提供的质量和惯量张量。较低的重心将使物体在被推倒后始终站起来。紫色物体的惯性张量使它很容易在一个方向上摆动,但在另一个方向几乎不会摆动。红色的身体有一个自动计算的重心,因此在被撞倒后会一直躺着。

Shooting balls

射击的球

To test out the behavior of the different bodies we add a Node for shooting balls:

为了测试不同实体的行为,我们添加了一个用于投球的节点:

Node {
    id: shapeSpawner
    property var spheres: []

    function createBall(position, forward) {
        let diameter = 0.2;
        let speed = 20;
        let settings = {
            position: position,
            linearVelocity: forward.times(speed),
            sphereDiameter: diameter
        };
        var component = Qt.createComponent("sphere.qml");
        let sphere = component.createObject(shapeSpawner, settings);

        var pair = {
            "sphere" : sphere,
            "date" : Date.now()
        };

        spheres.push(pair);

        if (sphere === null) {
            console.log("Error creating object");
        }
    }

    function clean() {
        spheres = spheres.filter(sphere => {
            let diff = Date.now() - sphere['date'];
            if (diff > 5000) {
                sphere['sphere'].destroy();
                return false;
            }
            return true;
        });
    }

    Timer {
        interval: 200
        running: true
        repeat: true
        onTriggered: shapeSpawner.clean()
    }
}

We then add a WasdController to be able to move the camera and aim and shoot balls at the bodies:

​然后,我们添加了WasdController,以便能够移动相机,瞄准并向目标投掷球:

WasdController {
    speed: 0.01
    controlledObject: camera
    Keys.onPressed: (event)=> {
        handleKeyPress(event);
        if (event.key === Qt.Key_Space) {
            shapeSpawner.createBall(camera.position, camera.forward);
        }
    }
    Keys.onReleased: (event)=> { handleKeyRelease(event) }
}

Files:

© 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值