C
Qt Quick Ultralite perspective_transforms の例
Qt Quick Ultralite アプリケーションに透視(2.5D)変換を実装する方法を示します。
概要
perspective_transforms の例では、Matrix4x4 QML transform タイプを使って、透視変換と擬似3D効果を実装しています。この例では、音楽アルバムのジャケットフローコンポーネントを使用しています。

この例のUIには、上部にラジオボタンがあり、以下のカバーフローのスタイルを切り替えることができます:
- カルーセル
- 円
- サークル2D(直交変換を使用)
- 遠近法
カバーフローコンポーネントは中央にレンダリングされます。選択したスタイルに従って、アルバム カバーの動きをアニメーション化します。
一番下にはスライダーコントロールがあり、仰角や傾斜角などのカメラパラメータを調整できます。
さらに、この例には「デモ」モードがあり、ユーザーとの対話が5秒以上続くと有効になります。このモードでは、利用可能なカバーとビュー・タイプの切り替えがアニメーションで行われます。ユーザーがアプリケーションとのインタラクションを開始すると、アニメーションは停止します。
対象プラットフォーム
プロジェクト構造
アプリケーション・プロジェクトの構造には、透視変換に関連する特別な機能はありませんが、最小限のものよりも少し複雑です。以下のサブディレクトリがあります:
- controls -CheckBox や Slider など、サンプルで使用しているカスタム UI コントロールの実装が含まれています。RadioButton
- imports - プロジェクトで使用されるQMLモジュールのコンテンツ - 主にプロジェクト全体の定数(シングルトンを使用)。
- resources - グラフィカルアセット - 主にアルバムジャケット
CMakeプロジェクトファイル
この例のCMakeLists.txtでは、perspective_transforms をメイン実行ターゲットとして定義しています。
...
qul_add_target(perspective_transforms
QML_PROJECT
mcu_perspective_transforms.qmlproject
SELECTORS no_controls
GENERATE_ENTRYPOINT
)
elseif(NOT QUL_PLATFORM MATCHES "^stm32f769i" AND NOT QUL_PLATFORM MATCHES "^mimxrt1170-evkb")
qul_add_target(perspective_transforms
QML_PROJECT
mcu_perspective_transforms.qmlproject
SELECTORS small_controls
GENERATE_ENTRYPOINT
)
...Qmlプロジェクトファイル
関連するqmlファイルはすべてQmlProjectファイルで指定します。
...
QmlFiles {
files: [
"CoverFlow.qml",
"CoverFlowState.qml",
"Cover.qml",
"IdleTimer.qml",
"perspective_transforms.qml"
]
}
QmlFiles {
files: [
"controls/CheckBox.qml",
"controls/RadioButton.qml",
"controls/Slider.qml"
]
}
...すべての画像アセットは、ImageFiles.MCU.resourceOptimizeForRotationプロパティを有効にして追加されています。これにより、サポートされているプラットフォームでのトランスフォームのパフォーマンスが向上します。
ImageFiles {
files: [
"resources/cover0.jpg",
"resources/cover1.jpg",
"resources/cover2.jpg",
"resources/cover3.jpg",
"resources/cover4.jpg",
"resources/cover5.jpg",
"resources/cover6.jpg",
"resources/cover7.jpg",
"resources/cover8.jpg",
"resources/cover9.jpg",
]
MCU.base: "resources"
// Optimize all assets for transformations
MCU.resourceOptimizeForRotation: trueさらに、プロジェクト全体の定数を保持するモジュールが、constants.qmlprojectを使用して定義され、メイン・プロジェクト・ファイルに追加されます。
ModuleFiles {
files: [
"imports/constants/constants.qmlproject",
"configuration/configuration.qmlproject"
]
MCU.qulModules: ["Controls"]
}アプリケーション UI
perspective_transforms.qmlファイルは、アプリケーションのユーザーインターフェイスを定義します。
ラジオボタンやスライダーなどの主なUIコンポーネントが配置されています。これらは、controls サブディレクトリで定義されているカスタムコントロールです。
import "controls"
IdleTimer は、ユーザーの非アクティブが検出されたときにUIをアニメーションさせる処理を行います。これはタッチスクリーンのないプラットフォーム向けです。これは2つのシグナルを公開しており、カバー・フロー・タイプと現在のアルバム・セレクションを独立に切り替えるために使用される。
IdleTimer { id: idleTimer property int coverDir: 1 onSwitchCover: { ... } onSwitchFlowType: { ... } }
最も関連性の高い部分は、カバーフローコンポーネントのインスタンス化である。これは、CoverFlow コンポーネントの現在の状態を保持するオブジェクトを作成することから始まる。
CoverFlowState { id: currentState screenWidth: root.width screenHeight: root.height } ...
その後、CoverFlow コンポーネントが実際のレンダリングを行う。
CoverFlow { anchors.fill: parent currentState: currentState }
CoverFlowState
CoverFlowState.qmlファイルは、CoverFlow のレンダリング方法に影響するすべてのパラメータを保持します。以下のパラメータを設定します:
- スクリーン/キャンバスのサイズ
CoverFlowサイズと位置- レンダリングするカバーの数と現在選択されているカバーのインデックス
- FOVやクリッピング距離、仰角、傾きなどのカメラ設定
- 特定のカバーフロータイプの設定
- 現在のビュータイプとタイプ遷移に関連するパラメータに関する情報
モーフ比は、異なるカバーフロータイプ間のアニメーション遷移に使用されるプロパティです。
property real morphRatio: 1 property int currentViewType: CoverFlowType.Carousel property int previousViewType: CoverFlowType.Carousel NumberAnimation on morphRatio { id: morphAnimation from: 0.0 to: 1.0 duration: 200 }
カバーフロータイプの切り替えは、switchViewType を使って行います。
function switchViewType(newType : int){ previousViewType = currentViewType currentViewType = newType morphAnimation.start() }
カバーフロー
CoverFlow.qmlファイルは、カバーフローコンポーネントを実装します。実際のレンダリングロジックが実装されるCover コンポーネントのインスタンスを複数作成します。
このコンポーネントには、現在の状態を保持するプロパティが1つあります。
Item { id: root property CoverFlowState currentState ...
Repeater は、カバーフローの状態で定義された値に基づいて、Covers の数を動的に作成します。
Repeater { model: root.currentState.numberOfCovers delegate: Cover { required property int index texture: "cover" + index + ".jpg" coverIndex: index state: root.currentState postMatrix: root.globalPostMatrix preMatrix: root.globalPreMatrix reflectionTransform: root.reflectionTransform } }
カバー
Cover.qmlは、右変換を使用してカバー(およびその反射)をレンダリングするために必要なすべての行列計算を実装します。Cover contorlはRectangle 、その子としてImage アイテム(適切なトランスフォームが適用されている)を持つ。1つの画像は実際のカバー画像を表し、2つ目の画像は1つ目の画像の反射をレンダリングするために使用されます。どちらの画像アイテムも、Matrix4x4 トランスフォームを使用しています。matrix プロパティは、matrix4x4 QML 基本型(Matrix4x4 トランスフォームオブジェクトとは異なる)を返す適切な関数にバインドされています。
Rectangle { id: cover property string texture property int coverIndex property CoverFlowState state property matrix4x4 coverTransform: calcCoverTransform() property matrix4x4 postMatrix property matrix4x4 preMatrix property matrix4x4 reflectionTransform z: calcFinalZ() Image { id: coverImageBase source: cover.texture transform: Matrix4x4 { matrix: coverTransform } opacity: 1.0 } Image { id: mirrorImageBase visible: cover.state.showReflection source: cover.texture transform: [ Matrix4x4 { matrix: reflectionTransform }, Matrix4x4 { matrix: coverTransform } ] opacity: 0.1 } ...
新しいmatrix4x4 は、Qt::matrix4x4() ファクトリーメソッドを用いて、すべての行列成分を与えて作成することができます。変換行列を例にとって考えてみましょう:
function mtxTranslate(x : real, y : real, z : real) : matrix4x4 { return Qt.matrix4x4(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1) }
matrix4x4 型では以下の算術演算が可能です:
- 行列の乗算による行列matrix4x4::times
- スカラー倍による行列matrix4x4::times
- 行列の加算matrix4x4::plus
これらはすべてcalcCoverTransform() 関数で使用される:
function calcCoverTransform() : matrix4x4 { var previousViewType = state.previousViewType var currentViewType = state.currentViewType if (state.morphRatio == 0) { currentViewType = previousViewType } else if (state.morphRatio == 1) {
matrix4x4 型は 16 個の値を持ち、それぞれm11 からm44 のプロパティ(行/列の順)でアクセスできる。これは、カバー全体のz 位置を計算するときに使用されます。
function calcFinalZ() : real { var coverTransform = cover.coverTransform var x = state.coverSize/2 var y = state.coverSize/2 var inv_d = 1.0 / (coverTransform.m41 * x + coverTransform.m42 * y + coverTransform.m44) var fX = (coverTransform.m11 * x + coverTransform.m12 * y + coverTransform.m14) * inv_d var fZ = (coverTransform.m31 * x + coverTransform.m32 * y + coverTransform.m34) * inv_d var littleX = Math.abs(fX - state.coverFlowX - state.coverFlowW * 0.5) return -fZ * 100000 - littleX }
Cover.qmlは、行列を操作する複数の関数を実装しています。これらの関数は、以下のカテゴリに分類することができます:
- 初歩的な行列生成関数(平行移動、拡大縮小、回転、遠近法)
- 変換前後の行列の計算(カメラ行列と初期カバー変換)
- 個々のカバーフロータイプに対する最終変換の計算
これらの基本的な構成要素はすべて、複雑な2.5Dエフェクトを実装するのに十分です。
ファイル
- perspective_transforms/CMakeLists.txt
- perspective_transforms/Cover.qml
- perspective_transforms/CoverFlow.qml
- perspective_transforms/CoverFlowState.qml
- perspective_transforms/IdleTimer.qml
- perspective_transforms/configuration/+no_controls/Configuration.qml
- perspective_transforms/configuration/Configuration.qml
- perspective_transforms/configuration/configuration.qmlproject
- perspective_transforms/controls/CheckBox.qml
- perspective_transforms/controls/RadioButton.qml
- perspective_transforms/controls/Slider.qml
- perspective_transforms/imports/constants/+small_controls/Constants.qml
- perspective_transforms/imports/constants/Constants.qml
- perspective_transforms/imports/constants/CoverFlowType.qml
- perspective_transforms/imports/constants/constants.qmlproject
- perspective_transforms/imports/constants/qmldir
- perspective_transforms/mcu_perspective_transforms.qmlproject
- perspective_transforms/perspective_transforms.qml
画像
- perspective_transforms/resources/cover0.jpg
- perspective_transforms/resources/cover1.jpg
- perspective_transforms/resources/cover2.jpg
- perspective_transforms/resources/cover3.jpg
- perspective_transforms/resources/cover4.jpg
- perspective_transforms/resources/cover5.jpg
- perspective_transforms/resources/cover6.jpg
- perspective_transforms/resources/cover7.jpg
- perspective_transforms/resources/cover8.jpg
- perspective_transforms/resources/cover9.jpg
Matrix4x4,matrix4x4,Qt::matrix4x4()も参照 。
特定の Qt ライセンスの下で利用可能です。
詳細を見る。