3D 変換の概要
このトピックでは、Windows Presentation Foundation (WPF) グラフィックス システムの 3D モデルに変換を適用する方法について説明します。 変換を使用すると、開発者はモデルを定義する基本値を変更することなく、モデルの位置の変更、サイズ変更、および方向変更を行うことができます。
3D 座標空間
Windows Presentation Foundation (WPF) の 3D グラフィックス コンテンツは、2 次元要素構造に参加できる要素 (Viewport3D) にカプセル化されます。 グラフィックス システムでは、Viewport3D は、Windows Presentation Foundation (WPF) の他の多くの要素と同様に、2 次元ビジュアル要素として扱われます。 Viewport3D は、3 次元シーンにウィンドウ (ビューポート) として機能します。 より正確には、3D シーンが投影されるサーフェスです。 同じシーン グラフ内の他の 2D 描画オブジェクトと共に Viewport3D を使用できますが、Viewport3D 内で 2D オブジェクトと 3D オブジェクトを相互に接続することはできません。 次の説明では、説明されている座標空間は Viewport3D 要素に含まれています。
2D グラフィックス用の Windows Presentation Foundation (WPF) 座標系は、レンダリング サーフェイスの左上 (通常は画面) に原点を配置します。 2D システムでは、正の x 軸の値が右に進み、正の y 軸の値が下方向に進みます。 ただし、3D 座標系では、原点は画面の中央に配置され、正の x 軸の値は右に進みますが、正の y 軸の値は上方向に進み、正の z 軸の値は原点からビューアーに向かって外側に向かって進みます。
座標系の比較
これらの軸によって定義される空間は、Windows Presentation Foundation (WPF) の 3D オブジェクトの固定参照フレームです。 この空間でモデルを構築し、それらを表示するライトとカメラを作成するときは、この静止した参照フレーム ("ワールド空間" ) を、変換を適用するときに各モデルに対して作成するローカル参照フレームと区別すると便利です。 また、ワールド空間内のオブジェクトは、ライトやカメラの設定によっては、まったく異なって見えたり、まったく表示されない場合もありますが、カメラの位置によってワールド空間内のオブジェクトの位置が変わることはありません。
モデルの変換
モデルを作成すると、シーン内に特定の場所が存在します。 シーン内でこれらのモデルを移動したり、モデルを回転させたり、サイズを変更したりするには、モデル自体を定義する頂点を変更することは現実的ではありません。 代わりに、2D と同様に、モデルに変換を適用します。
各モデル オブジェクトには、モデルの移動、方向変更、またはサイズ変更を行うことができる Transform プロパティがあります。 変換を適用すると、変換によって指定されたベクターまたは値によって、モデルのすべてのポイントを効果的にオフセットします。 つまり、モデルが定義されている座標空間 ("モデル空間") を変換しましたが、シーン全体の座標系 ("ワールド空間") でモデルのジオメトリを構成する値は変更していません。
平行移動変換
3D 変換は抽象基底クラス Transform3Dから継承されます。これには、TranslateTransform3D、ScaleTransform3D、および RotateTransform3Dのアフィン変換クラスが含まれます。 Windows Presentation Foundation (WPF) 3D システムには、より簡潔なマトリックス操作で同じ変換を指定できる MatrixTransform3D クラスも用意されています。
TranslateTransform3D、OffsetX、OffsetY、および OffsetZ プロパティで指定したオフセット ベクトルの方向に Model3D 内のすべてのポイントを移動します。 たとえば、キューブの 1 つの頂点 (2,2,2) を指定すると、オフセット ベクター (0,1.6,1) は、その頂点 (2,2,2) を (2,3.6,3) に移動します。 キューブの頂点はまだモデル空間では (2,2,2) ですが、モデル空間がワールド空間との関係を変更し、モデル空間の (2,2,2) がワールド空間で (2,3.6,3) になるようにしました。
オフセット付きの翻訳
次のコード例は、翻訳を適用する方法を示しています。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="600" Height="201">
<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="600" Height="150"
Canvas.Left="0" Canvas.Top="10">
<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>
<!-- This ModelVisual3D defines the light cast in the scene. Without light, the
3D object cannot be seen. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The OffsetX property is animated
in the Storyboard below. -->
<GeometryModel3D.Transform>
<TranslateTransform3D x:Name="myTranslateTransform3D" OffsetX="0" OffsetY="0" OffsetZ="0" />
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the TranslateTransform3D animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>
<!-- This animation animates the OffsetX property of the TranslateTransform3D. -->
<DoubleAnimation
Storyboard.TargetName="myTranslateTransform3D"
Storyboard.TargetProperty="OffsetX"
To="-0.8"
AutoReverse="True" RepeatBehavior="Forever" />
<!-- If you want to animate OffsetY and/or OffsetZ, create similar DoubleAnimations
respectively. -->
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>
スケール変換
ScaleTransform3D、中心点を参照して、指定したスケール ベクトルによってモデルのスケールを変更します。 モデルのサイズを比例的に変更するために、X 軸、Y 軸、Z 軸で同じ値でモデルをスケーリングする均一スケールを指定します。 たとえば、変換の ScaleX、ScaleY、および ScaleZ プロパティを 0.5 に設定すると、モデルのサイズが半分になります。同じプロパティを 2 に設定すると、3 つの軸すべてでスケールが 2 倍になります。
ScaleVector の例
一様でないスケール変換 (X、Y、Z の値がすべて同じではないスケール変換) を指定すると、モデルが他のディメンションに影響を与えずに 1 つまたは 2 つのディメンションで拡大または縮小される可能性があります。 たとえば、ScaleX を 1、ScaleY を 2、ScaleZ を 1 に設定すると、変換されたモデルの高さが 2 倍になりますが、X 軸と Z 軸に沿って変更されません。
既定では、ScaleTransform3D では頂点が原点 (0,0,0) に関して展開または縮小されます。 ただし、変換するモデルが原点から描画されていない場合、原点からモデルをスケーリングしても、モデルは "インプレース" にスケーリングされません。代わりに、モデルの頂点にスケール ベクターを乗算すると、スケール操作によって、モデルの変換とスケーリングの効果が得られます。
スケールの中心点の例
モデルを "インプレース" でスケーリングするには、ScaleTransform3D の CenterX、CenterY、および CenterZ プロパティを設定して、モデルの中心を指定します。 これにより、グラフィックス システムによってモデル空間がスケーリングされ、指定した Point3Dの中心に変換されます。 逆に、原点に関するモデルを構築し、別の中心点を指定した場合は、モデルが原点から離れて翻訳されていることを期待します。
回転変換
モデルは、さまざまな方法で 3D で回転できます。 一般的な回転変換では、軸とその軸の周りの回転角度を指定します。 RotateTransform3D クラスを使用すると、Rotation プロパティを使用して Rotation3D を定義できます。 次に、Rotation3D の Axis プロパティと Angle プロパティ (この場合は AxisAngleRotation3D) を指定して、変換を定義します。 次の例では、モデルを Y 軸を中心に 60 度回転します。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">
<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">
<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>
<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>
<!-- This animation animates the Angle property of the AxisAngleRotation3D
making the 3D object rotate from -60 degrees to 60 degrees. -->
<DoubleAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Angle"
From="-60" To="60" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>
<!-- This animation animates the Axis property of the AxisAngleRotation3D
making the 3D wobble as it rotates. -->
<Vector3DAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Axis"
From="0,3,0" To="1,0,1" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>
注:Windows Presentation Foundation (WPF) 3D は右利きのシステムです。つまり、回転の正の角度値を指定すると、軸を中心に反時計回りに回転します。
RotateTransform3D の CenterX、CenterY、CenterZ の各プロパティの値が指定されていない場合、軸角度の回転は原点を中心とする回転と見なされます。 スケーリングと同様に、回転によってモデルの座標空間全体が変換されることを覚えておくことをお勧めします。 モデルが原点に関して作成されていない場合、または以前に翻訳されている場合、回転は、所定の位置で回転するのではなく、原点を中心に "ピボット" する可能性があります。
新しい中心が指定された回転
モデルを「その場で」回転するには、モデルの実際の中心を回転の中心として指定します。 通常、ジオメトリは原点に関してモデル化されるため、多くの場合、最初にモデルのサイズを変更 (スケーリング)、その向きを設定 (回転) し、最後に目的の場所に移動 (変換) することで、一連の変換の期待される結果を得ることができます。
回転の例
軸角度回転は、静的な変換や一部のアニメーションに適しています。 ただし、キューブ モデルを X 軸を中心に 60 度回転し、次に Z 軸を 45 度回転することを検討してください。 この変換は、2 つの不連続アフィン変換として、またはマトリックスとして記述できます。 ただし、このように定義された回転をスムーズにアニメーション化するのは困難な場合があります。 どちらのアプローチによって計算されるモデルの開始位置と終了位置も同じですが、モデルによって取得される中間位置は計算上不確かです。 四元数は、回転の開始と終了の間の補間を計算する別の方法を表します。
四元数は、3D 空間内の軸とその軸の周りの回転を表します。 たとえば、四元数は (1,1,2) 軸と 50 度の回転を表します。 回転の定義における四元数の能力は、コンポジションと補間という 2 つの操作から得られます。 2つの四元数をジオメトリに適用する際の組み合わせは、「ジオメトリをrotation2でaxis2の周りに回転させた後、rotation1でaxis1の周りに回転させる」という意味です。構成を使用することで、ジオメトリ上の2つの回転を1つの四元数に統合し、その結果を表現できます。 四元数補間では、ある軸と向きから別の軸へのスムーズで妥当なパスを計算できるため、元の四元数から構成済みの四元数への補間を行って、一方から他方へのスムーズな遷移を実現し、変換をアニメーション化することができます。 アニメーション化するモデルの場合は、Rotation プロパティの QuaternionRotation3D を使用して、回転の宛先 Quaternion を指定できます。
変換コレクションの使用
シーンを構築するときは、モデルに複数の変換を適用するのが一般的です。 Transform3DGroup クラスの Children コレクションに変換を追加して、シーン内のさまざまなモデルに適用するために変換を簡単にグループ化します。 多くの場合、複数の異なるグループで変換を再利用すると便利です。多くの場合、各インスタンスに異なる変換セットを適用することでモデルを再利用できます。 変換がコレクションに追加される順序は重要であることに注意してください。コレクション内の変換は最初から最後まで適用されます。
変換のアニメーション化
Windows Presentation Foundation (WPF) の 3D 実装は、2D グラフィックスと同じタイミングおよびアニメーション システムに参加します。 言い換えると、3D シーンをアニメーション化するには、そのモデルのプロパティをアニメーション化します。 プリミティブのプロパティを直接アニメーション化することもできますが、通常は、モデルの位置や外観を変更する変換をアニメーション化する方が簡単です。 変換は Model3DGroup オブジェクトと個々のモデルに適用できるため、1 つのアニメーション セットを Model3Dgroup の子に適用し、別のアニメーション セットをオブジェクトのグループに適用できます。 Windows Presentation Foundation (WPF) のタイミングとアニメーション システムの背景情報については、「アニメーションの概要 と ストーリーボードの概要」を参照してください。
Windows Presentation Foundation (WPF) でオブジェクトをアニメーション化するには、タイムラインを作成し、アニメーション (実際には時間の経過に伴うプロパティ値の変更) を定義し、アニメーションを適用するプロパティを指定します。 このプロパティは、FrameworkElement のプロパティである必要があります。 3D シーン内のすべてのオブジェクトは Viewport3D の子であるため、シーンに適用するアニメーションの対象となるプロパティは Viewport3D のプロパティです。 構文は詳細な場合があるため、アニメーションのプロパティ パスを慎重に調べてください。
オブジェクトを所定の位置で回転させる一方で、スイング モーションを適用して、表示するオブジェクトの多くを公開するとします。 RotateTransform3D をモデルに適用し、その回転軸をベクトル間でアニメーション化することができます。 次のコード例では、RotateTransform3D が TransformGroupを使用してモデルに適用される複数の変換の 1 つであると仮定して、変換の Rotation3D の Axis プロパティに Vector3DAnimation を適用する方法を示します。
//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 1));
'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))
Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;
Dim myVectorAnimation As New Vector3DAnimation(New Vector3D(-1, -1, -1), New Duration(TimeSpan.FromMilliseconds(5000)))
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever
同様の構文を使用して、他の変換プロパティをターゲットにしてオブジェクトを移動またはスケーリングします。 たとえば、スケール変換の ScaleCenter プロパティに Point3DAnimation を適用すると、モデルの形状が滑らかに歪みます。
前の例では、GeometryModel3Dのプロパティを変換しますが、シーン内の他のモデルのプロパティを変換することもできます。 たとえば、Light オブジェクトに適用された翻訳をアニメーション化することで、動く光や影の効果を作成して、モデルの外観を大幅に変更できます。
カメラもモデルであるため、カメラのプロパティも変換できます。 カメラの位置または平面の距離を変換することでシーンの外観を確実に変更できますが、実際には、シーンプロジェクション全体を変換すると、この方法で実現する効果の多くは、シーン内のモデルの位置や位置に適用される変換ほど"視覚的な感覚"をビューアーに与えない場合があることに注意してください。
関連項目
.NET Desktop feedback