Qt Quick 3D Physics - カスタムシェイプの例
さまざまなシェイプの使用例
この例では、複数のリジッドボディメッシュのロードとスポーン、そしてそれらのアニメーションをデモします。シーンは、サイコロタワー、テーブルクロス、カップ、一握りのサイコロで構成されています。カップは、スポーンしたサイコロを集めて、サイコロタワーに入れるようにアニメーションします。サイコロはテーブルクロスの上に転がり落ちます。
環境
いつものように、PhysicsWorld とView3D があります。View3D には、ライトプローブをセットアップする環境があります:
environment: SceneEnvironment { clearColor: "white" backgroundMode: SceneEnvironment.SkyBox antialiasingMode: SceneEnvironment.MSAA antialiasingQuality: SceneEnvironment.High lightProbe: proceduralSky }
テクスチャ
スカイボックス、テーブルクロス、サイコロの数字に使う4つのテクスチャを定義します:
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 }
シーン
カメラと指向性ライトを含むシーンを含むノードがあります:
id: scene scale: Qt.vector3d(2, 2, 2) PerspectiveCamera { id: camera position: Qt.vector3d(-45, 25, 60) eulerRotation: Qt.vector3d(-6, -33, 0) clipFar: 1000 clipNear: 0.1 } DirectionalLight { eulerRotation: Qt.vector3d(-45, 25, 0) castsShadow: true brightness: 1 shadowMapQuality: Light.ShadowMapQualityHigh pcfFactor: 0.1 shadowBias: 1 }
テーブルクロス
テーブルクロスを追加します。テーブルクロスは、織物テクスチャを持つモデルと、衝突用のHeightFieldShape から構成されるStaticRigidBody 。
StaticRigidBody { position: Qt.vector3d(-15, -8, 0) id: tablecloth Model { geometry: HeightFieldGeometry { id: tableclothGeometry extents: Qt.vector3d(150, 20, 150) source: "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 source: "maps/cloth-heightmap.png" } }
カップ
コップは、コリジョンシェイプとして、モデルとTriangleMeshShape を持つDynamicRigidBody として定義します。eulerRotation
とposition
プロパティはアニメーションの一部なので、ビヘイビアを持ちます。
DynamicRigidBody { id: diceCup isKinematic: true mass: 0 property vector3d bottomPos: Qt.vector3d(11, 6, 0) property vector3d topPos: Qt.vector3d(11, 45, 0) property vector3d unloadPos: Qt.vector3d(0, 45, 0) position: bottomPos kinematicPivot: Qt.vector3d(0, 6, 0) kinematicPosition: bottomPos collisionShapes: TriangleMeshShape { id: cupShape source: "meshes/simpleCup.mesh" } Model { source: "meshes/cup.mesh" materials: PrincipledMaterial { baseColor: "#cc9988" roughness: 0.3 metalness: 1 } } }
タワー
TowerはStaticRigidBody 、ModelとTriangleMeshShape 。
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 source: "meshes/tower.mesh" } }
サイコロ
サイコロを生成するには、ComponentとRepeater3D 。 ComponentにはDynamicRigidBody 、ConvexMeshShape 、Modelが含まれます。位置、色、スケール、メッシュソースは、ダイスごとにランダムに生成されます。
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)), diceCup.bottomPos.y + 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 source: 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.source receivesShadows: false 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 (var i = 0; i < count; i++) { objectAt(i).restore() } } }
アニメーション
サイコロをカップからサイコロタワーに移動させるために、カップをアニメーションさせて上に移動させ、ひっくり返します。アニメーションが物理シミュレーションと同期していることを確認するために、PhysicsWorld のonFrameDone
シグナルに接続したAnimationController を使用します。シミュレーションの各フレームの後、経過したタイムステップでアニメーションを進行させます。
Connections { target: physicsWorld property real totalAnimationTime: 7500 function onFrameDone(timeStep) { let progressStep = timeStep / totalAnimationTime animationController.progress += progressStep if (animationController.progress >= 1) { animationController.completeToEnd() animationController.reload() animationController.progress = 0 } } } AnimationController { id: animationController animation: SequentialAnimation { PauseAnimation { duration: 2500 } PropertyAnimation { target: diceCup property: "kinematicPosition" to: diceCup.topPos duration: 2500 } ParallelAnimation { PropertyAnimation { target: diceCup property: "kinematicEulerRotation.z" to: 130 duration: 1500 } PropertyAnimation { target: diceCup property: "kinematicPosition" to: diceCup.unloadPos duration: 1500 } } PauseAnimation { duration: 1000 } ParallelAnimation { PropertyAnimation { target: diceCup property: "kinematicEulerRotation.z" to: 0 duration: 1500 } PropertyAnimation { target: diceCup property: "kinematicPosition" to: diceCup.topPos duration: 1500 } } PropertyAnimation { target: diceCup; property: "kinematicPosition"; to: diceCup.bottomPos; duration: 1500 } PauseAnimation { duration: 2000 } ScriptAction { script: dicePool.restore() } } }
コントローラ
最後に、キーボードを使ってカメラをコントロールできるように、WasdController :
WasdController { keysEnabled: true controlledObject: camera speed: 0.2 }
ファイル
- customshapes/CMakeLists.txt
- customshapes/customshapes.pro
- customshapes/main.cpp
- customshapes/main.qml
- customshapes/qml.qrc
- customshapes/resources.qrc
画像
ここに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。