Qt Quick 3D物理学 - 複合形状の例
複雑な衝突形状の使用例を示します。

この例では、複数の衝突形状を使用して、衝突検出用の複雑なオブジェクトを作成する方法を示します。シーンは、緑色の静的な平面と、互いに連結された一連のリンクで構成されています。最初はシミュレーションが無効になっています。しばらく経つか、ユーザーがスペースキーを押すと、シミュレーションが開始されます。 アニメーションが開始され、最左端と最右端のリンクが水平方向に前後に動き出します。
セットアップ
いつものように、PhysicsWorld を追加する必要があります:
PhysicsWorld {
id: physicsWorld
enableCCD: true
maximumTimestep: 20
scene: viewport.scene
}環境、カメラ、ライトを設定する通常の手順を行います:
environment: SceneEnvironment {
antialiasingMode: SceneEnvironment.MSAA
backgroundMode: SceneEnvironment.Color
clearColor: "lightblue"
}
focus: true
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 900, 1500)
eulerRotation: Qt.vector3d(-10, 0, 0)
clipFar: 15500
clipNear: 1
}
DirectionalLight {
eulerRotation.x: -45
eulerRotation.y: 45
castsShadow: true
brightness: 1.5
shadowMapQuality: Light.ShadowMapQualityHigh
}物理オブジェクト
通常の静的な平面を用意します:
StaticRigidBody {
position: Qt.vector3d(0, -100, 0)
eulerRotation: Qt.vector3d(-90, 0, 0)
collisionShapes: PlaneShape {}
Model {
source: "#Rectangle"
scale: Qt.vector3d(500, 500, 1)
materials: PrincipledMaterial {
baseColor: "green"
}
castsShadows: false
receivesShadows: true
}
}次に、リンクのインスタンスを作成します。
MeshLink {
id: leftLink
isKinematic: true
property vector3d startPos: Qt.vector3d(-6 * viewport.ringDistance,
viewport.ringY,
0)
property vector3d startRot: Qt.vector3d(90, 0, 0)
kinematicPosition: startPos
position: startPos
kinematicEulerRotation: startRot
eulerRotation: startRot
color: "red"
}
CapsuleLink {
position: Qt.vector3d(-5 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
MeshLink {
position: Qt.vector3d(-4 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
MeshLink {
position: Qt.vector3d(-3 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(0, 90, 0)
}
MeshLink {
position: Qt.vector3d(-2 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
MeshLink {
position: Qt.vector3d(-1 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(0, 90, 0)
}
CapsuleLink {
position: Qt.vector3d(0, viewport.ringY, 0)
}
MeshLink {
position: Qt.vector3d(1 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(0, 90, 0)
}
MeshLink {
position: Qt.vector3d(2 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
MeshLink {
position: Qt.vector3d(3 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(0, 90, 0)
}
MeshLink {
position: Qt.vector3d(4 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
CapsuleLink {
position: Qt.vector3d(5 * viewport.ringDistance, viewport.ringY, 0)
eulerRotation: Qt.vector3d(90, 0, 0)
}
MeshLink {
id: rightLink
isKinematic: true
property vector3d startPos: Qt.vector3d(6 * viewport.ringDistance,
viewport.ringY,
0)
property vector3d startRot: Qt.vector3d(90, 0, 0)
kinematicPosition: startPos
position: startPos
kinematicEulerRotation: startRot
eulerRotation: startRot
color: "red"
}左側にある最初のリンクの「isKinematic 」プロパティは「true 」に設定されており、これによりアニメーションを通じて制御できるようになっています。これはキネマティックオブジェクトであるため、「kinematicPosition 」および「kinematicRotation 」プロパティを設定する必要があります。このリンクのアニメーションは、「kinematicPosition 」プロパティをアニメーション化することで行います。他のリンクは、互いに間隔を空けてインスタンス化されています。
物理シミュレーションに正確に追従する滑らかなアニメーションを実現するために、`PhysicsWorld`の`onFrameDone `信号に接続した`AnimationController `を使用します。これにより、フレーム落ちによってシミュレーションの速度が低下した場合でも、アニメーションもそれに応じて遅くなります。また、4つの`NumberAnimation `を持つ`SequentialAnimation `を使用して、左端と右端のリングを前後に動かします。以下は、このアニメーションのQMLコードです:
Connections {
target: physicsWorld
property real totalAnimationTime: 12000
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 {
NumberAnimation {
target: leftLink
property: "kinematicPosition.x"
to: 3 * viewport.ringDistance
from: -6 * viewport.ringDistance
easing.type: Easing.InOutCubic
duration: 1000
}
NumberAnimation {
target: leftLink
property: "kinematicPosition.x"
from: 3 * viewport.ringDistance
to: -6 * viewport.ringDistance
easing.type: Easing.InOutCubic
duration: 1000
}
NumberAnimation {
target: rightLink
property: "kinematicPosition.x"
to: -3 * viewport.ringDistance
from: 6 * viewport.ringDistance
easing.type: Easing.InOutCubic
duration: 1000
}
NumberAnimation {
target: rightLink
property: "kinematicPosition.x"
from: -3 * viewport.ringDistance
to: 6 * viewport.ringDistance
easing.type: Easing.InOutCubic
duration: 1000
}
}
}興味深いのは、MeshリンクファイルとCapsuleリンクファイルの内部で何が起きているかです。それぞれについて見ていきましょう。
Mesh Link
DynamicRigidBody {
id: root
scale: Qt.vector3d(100, 100, 100)
property color color: "white"
PrincipledMaterial {
id: _material
baseColor: root.color
metalness: 1.0
roughness: 0.5
}
Model {
source: "meshes/ring.mesh"
materials: [_material]
}
collisionShapes: [
ConvexMeshShape {
source: "meshes/segmentedRing_001.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_002.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_003.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_004.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_005.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_006.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_007.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_008.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_009.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_010.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_011.mesh"
},
ConvexMeshShape {
source: "meshes/segmentedRing_012.mesh"
}
]
}Mesh Linkは、モデルとマテリアルを持つ動的剛体です。モデルはメッシュファイルからメッシュを読み込みます。 また、衝突検出用の複合形状を形成するために組み合わされる、一連の衝突形状のリストもあります。各形状は、ソースファイルからメッシュを読み込む「Convex Mesh」形状です。凸形状とは、基本的に、形状内の任意の2点間の直線が常に形状の内側にある形状のことです。
デバッグモードを有効にして詳しく見てみると、衝突形状がどのようにして複合衝突形状を形成しているかがわかります:

カプセルリンク
DynamicRigidBody {
id: root
property real len: 170
property real w: 17
PrincipledMaterial {
id: material3
baseColor: "yellow"
metalness: 1.0
roughness: 0.5
}
Node {
opacity: 1
Model {
materials: material3
source: "#Cylinder"
scale: Qt.vector3d(root.w / 100, root.len / 100, root.w / 100)
eulerRotation.z: 90
y: -root.len / 2
}
Model {
materials: material3
source: "#Cylinder"
scale: Qt.vector3d(root.w / 100, root.len / 100, root.w / 100)
eulerRotation.z: 90
y: root.len / 2
}
Model {
materials: material3
source: "#Cylinder"
scale: Qt.vector3d(root.w / 100, root.len / 100, root.w / 100)
x: root.len / 2
}
Model {
materials: material3
source: "#Cylinder"
scale: Qt.vector3d(root.w / 100, root.len / 100, root.w / 100)
x: -root.len / 2
}
Model {
materials: material3
source: "#Sphere"
scale: Qt.vector3d(root.w / 100, root.w / 100, root.w / 100)
x: -root.len / 2
y: -root.len / 2
}
Model {
materials: material3
source: "#Sphere"
scale: Qt.vector3d(root.w / 100, root.w / 100, root.w / 100)
x: -root.len / 2
y: root.len / 2
}
Model {
materials: material3
source: "#Sphere"
scale: Qt.vector3d(root.w / 100, root.w / 100, root.w / 100)
x: root.len / 2
y: -root.len / 2
}
Model {
materials: material3
source: "#Sphere"
scale: Qt.vector3d(root.w / 100, root.w / 100, root.w / 100)
x: root.len / 2
y: root.len / 2
}
}
collisionShapes: [
CapsuleShape {
y: -root.len / 2
height: root.len
diameter: root.w
},
CapsuleShape {
y: root.len / 2
height: root.len
diameter: root.w
},
CapsuleShape {
x: -root.len / 2
eulerRotation.z: 90
height: root.len
diameter: root.w
},
CapsuleShape {
x: root.len / 2
eulerRotation.z: 90
height: root.len
diameter: root.w
}
]
}「カプセルリンク」は、同じマテリアルを共有するいくつかのモデルから構成されるダイナミック剛体です。このリンクは、複数の円柱と球体から形成されています。「メッシュリンク」と同様に、衝突形状のリストがあります。今回は、各形状が「カプセル形状」となっています。
デバッグモードを有効にして詳しく見てみると、衝突形状がどのように複合衝突形状を形成しているかがわかります。

ファイル:
© 2026 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.