Bagikan melalui


Gambaran Umum Transformasi 3D

Topik ini menjelaskan cara menerapkan transformasi ke model 3D dalam sistem grafis Windows Presentation Foundation (WPF). Transformasi memungkinkan pengembang untuk memposisikan ulang, mengubah ukuran, dan mengatur ulang model tanpa mengubah nilai dasar yang menentukannya.

Ruang Koordinat 3D

Konten grafis 3D di Windows Presentation Foundation (WPF) dienkapsulasi dalam elemen, Viewport3D, yang dapat berpartisipasi dalam struktur elemen dua dimensi. Sistem grafis memperlakukan Viewport3D sebagai elemen visual dua dimensi seperti yang lain di Windows Presentation Foundation (WPF). Viewport3D berfungsi sebagai jendela—viewport—ke dalam pemandangan tiga dimensi. Lebih akurat, itu adalah permukaan di mana adegan 3D diproyeksikan. Meskipun Anda dapat menggunakan Viewport3D dengan objek gambar 2D lainnya dalam grafik adegan yang sama, Anda tidak dapat menginterpenetrasi objek 2D dan 3D dalam Viewport3D. Dalam diskusi berikut, ruang koordinat yang dijelaskan dimuat oleh elemen Viewport3D.

Sistem koordinat Windows Presentation Foundation (WPF) untuk grafik 2D menemukan asal di kiri atas permukaan penyajian (biasanya layar). Dalam sistem 2D, nilai sumbu x positif bergerak ke kanan dan nilai sumbu y positif bergerak ke bawah. Namun, dalam sistem koordinat 3D, asal terletak di tengah layar, dengan nilai sumbu x positif berlanjut ke kanan tetapi nilai sumbu y positif melanjutkan ke atas sebagai gantinya, dan nilai sumbu z positif melanjutkan ke luar dari asal, menuju penampil.

Sistem koordinat CoordSystem-1
Perbandingan Sistem Koordinat

Ruang yang ditentukan oleh sumbu ini adalah bingkai referensi stasioner untuk objek 3D di Windows Presentation Foundation (WPF). Saat Anda membangun model di ruang ini dan membuat lampu dan kamera untuk melihatnya, sangat membantu untuk membedakan bingkai referensi stasioner ini, atau "ruang dunia," dari bingkai referensi lokal yang Anda buat untuk setiap model saat Anda menerapkan transformasi ke sana. Ingat juga bahwa objek di ruang dunia mungkin terlihat sama sekali berbeda, atau tidak terlihat sama sekali, tergantung pada pengaturan cahaya dan kamera, tetapi posisi kamera tidak mengubah lokasi objek di ruang dunia.

Mengubah Model

Saat Anda membuat model, model tersebut memiliki lokasi tertentu di adegan. Untuk memindahkan model tersebut di sekitar adegan, untuk memutarnya, atau mengubah ukurannya, tidak praktis untuk mengubah simpul yang menentukan model itu sendiri. Sebagai gantinya, sama seperti dalam 2D, Anda menerapkan transformasi ke model.

Setiap objek model memiliki properti Transform yang dapat Anda pindahkan, orientasi ulang, atau mengubah ukuran model. Ketika Anda menerapkan transformasi, Anda secara efektif menggeser semua titik model dengan vektor atau nilai yang ditentukan oleh transformasi. Dengan kata lain, Anda telah mengubah ruang koordinat tempat model ditentukan ("ruang model"), tetapi Anda belum mengubah nilai yang membentuk geometri model dalam sistem koordinat seluruh adegan ("ruang dunia").

Transformasi Terjemahan

Transformasi 3D mewarisi dari kelas dasar abstrak Transform3D; ini termasuk kelas transformasi affine TranslateTransform3D, ScaleTransform3D, dan RotateTransform3D. Sistem 3D Windows Presentation Foundation (WPF) juga menyediakan kelas MatrixTransform3D yang memungkinkan Anda menentukan transformasi yang sama dalam operasi matriks yang lebih ringkas.

TranslateTransform3D memindahkan semua titik dalam Model3D ke arah vektor offset yang Anda tentukan dengan properti OffsetX, OffsetY, dan OffsetZ. Misalnya, dengan satu puncak kubus pada (2,2,2), vektor offset (0,1,6,1) akan memindahkan puncak tersebut (2,2,2) ke (2,3,6,3). Puncak kubus masih (2,2,2) di ruang model, tetapi sekarang ruang model telah mengubah hubungannya ke ruang dunia sehingga (2,2,2) dalam ruang model adalah (2,3,6,3) di ruang dunia.

gambar Terjemahan
Terjemahan dengan Offset

Contoh kode berikut menunjukkan cara menerapkan terjemahan.

<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>

Transformasi Skala

ScaleTransform3D mengubah skala model oleh vektor skala tertentu dengan referensi ke titik tengah. Tentukan skala seragam, yang menskalakan model dengan nilai yang sama dalam sumbu X, Y, dan Z, untuk mengubah ukuran model secara proporsional. Misalnya, mengatur properti ScaleX, ScaleY, dan ScaleZ transformasi ke 0,5 membagi dua ukuran model; mengatur properti yang sama ke 2 menggandakan skalanya di ketiga sumbu.

Uniform ScaleTransform3D Threecubes_uniformscale_1
Contoh ScaleVector

Dengan menentukan transformasi skala non-seragam—transformasi skala yang nilai X, Y, dan Z-nya tidak semuanya sama—Anda dapat menyebabkan model meregangkan atau berkontraksi dalam satu atau dua dimensi tanpa memengaruhi yang lain. Misalnya, mengatur ScaleX ke 1, ScaleY ke 2, dan ScaleZ ke 1 akan menyebabkan model yang diubah menjadi dua kali lipat tingginya, tetapi tetap sama di sumbu X dan Z.

Secara bawaan, ScaleTransform3D menyebabkan titik-titik memperbesar atau memperkecil sekitar asal (0,0,0). Namun, jika model yang ingin Anda ubah tidak diambil dari asalnya, penskalakan model dari asal tidak akan menskalakan model "di tempat." Sebaliknya, ketika simpul model dikalikan dengan vektor skala, operasi skala akan memiliki efek menerjemahkan model serta menskalakannya.

Tiga kubus diskalakan dengan titik tengah yang ditentukan
Contoh Pusat Skala

Untuk menskalakan model "di tempat", tentukan pusat model dengan mengatur properti CenterX, CenterY, dan CenterZ ScaleTransform3D. Ini memastikan bahwa sistem grafis menskalakan ruang model dan kemudian menerjemahkannya ke pusat pada Point3Dyang ditentukan . Sebaliknya, jika Anda telah membangun model berdasarkan titik asal dan menentukan titik pusat yang berbeda, harapkan untuk melihat model yang digeser jauh dari titik asal.

Transformasi Rotasi

Anda dapat memutar model dalam 3D dengan beberapa cara berbeda. Transformasi rotasi khas menentukan sumbu dan sudut rotasi di sekitar sumbu tersebut. Kelas RotateTransform3D memungkinkan Anda menentukan Rotation3D dengan properti Rotation. Anda kemudian menentukan properti Axis dan Angle pada Rotation3D, dalam hal ini AxisAngleRotation3D, untuk menentukan transformasi. Contoh berikut memutar model sebesar 60 derajat di sekitar sumbu Y.

<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>

Catatan: Windows Presentation Foundation (WPF) 3D adalah sistem tangan kanan, yang berarti nilai sudut positif untuk rotasi menghasilkan rotasi berlawanan arah jarum jam terhadap sumbu.

Rotasi sudut sumbu mengasumsikan rotasi terhadap titik asal jika nilai tidak ditentukan untuk properti CenterX, CenterY, dan CenterZ pada RotateTransform3D. Seperti halnya penskalaan, sangat membantu untuk mengingat bahwa rotasi mengubah seluruh ruang koordinat model. Jika model tidak dibuat terhadap titik awal, atau telah diterjemahkan sebelumnya, rotasi mungkin "berporos" terhadap titik awal alih-alih berputar di tempat.

Rotasi dengan titik tengah baru
Rotasi dengan pusat baru yang ditentukan

Untuk memutar model "di tempat", tentukan pusat aktual model sebagai pusat rotasi. Karena geometri biasanya dimodelkan tentang asal, Anda paling sering mendapatkan hasil yang diharapkan dari serangkaian transformasi dengan terlebih dahulu mengukur model (menskalakannya), lalu mengatur orientasinya (memutarnya), dan akhirnya memindahkannya ke lokasi yang diinginkan (menerjemahkannya).

Rotasi sebesar 60 derajat pada sumbu x dan y
Contoh Rotasi

Rotasi sudut sumbu bekerja dengan baik untuk transformasi statis dan beberapa animasi. Namun, pertimbangkan untuk memutar model kubus 60 derajat di sekitar sumbu X, lalu 45 derajat di sekitar sumbu Z. Anda dapat menggambarkan transformasi ini sebagai dua transformasi affine diskrit, atau sebagai matriks. Namun, mungkin sulit untuk menganimasikan rotasi yang ditentukan dengan lancar dengan cara ini. Meskipun posisi awal dan akhir model yang dihitung oleh salah satu pendekatan sama, posisi menengah yang diambil oleh model secara komputasi tidak pasti. Kuaternion mewakili cara alternatif untuk menghitung interpolasi antara awal dan akhir rotasi.

Kuaternion mewakili sumbu dalam ruang 3D dan rotasi mengelilingi sumbu tersebut. Sebagai contoh, kuaternion mungkin mewakili sumbu (1,1,2) dan rotasi 50 derajat. Kekuatan Quaternions dalam mendefinisikan rotasi berasal dari dua operasi yang dapat dilakukan terhadapnya: komposisi dan interpolasi. Komposisi dua kuaternion yang diterapkan pada geometri berarti, "putar geometri di sekitar sumbu ke-2 dengan rotasi ke-2, lalu putar di sekitar sumbu ke-1 dengan rotasi ke-1." Dengan menggunakan komposisi, Anda dapat menggabungkan dua rotasi pada geometri untuk mendapatkan satu kuaternion yang mewakili hasilnya. Karena interpolasi kuaternion dapat menghitung jalur yang lancar dan masuk akal dari satu sumbu dan orientasi ke sumbu lainnya, Anda dapat menginterpolasi dari kuaternion asli ke kuaternion gabungan untuk mencapai transisi yang lancar dari satu ke yang lain, memungkinkan Anda untuk menganimasikan transformasi. Untuk model yang ingin Anda animasikan, Anda dapat menentukan Quaternion tujuan untuk rotasi dengan menggunakan QuaternionRotation3D untuk properti Rotation.

Menggunakan Koleksi Transformasi

Saat membangun adegan, biasanya menerapkan lebih dari satu transformasi ke model. Tambahkan transformasi ke koleksi Children dari kelas Transform3DGroup untuk mengelompokkan transformasi dengan mudah yang dapat diterapkan pada berbagai model di adegan. Seringkali lebih mudah untuk menggunakan kembali transformasi di beberapa grup yang berbeda, dengan cara yang sama seperti Anda dapat menggunakan kembali model dengan menerapkan serangkaian transformasi yang berbeda ke setiap penerapan. Perhatikan bahwa urutan di mana transformasi ditambahkan ke koleksi signifikan: transformasi dalam koleksi diterapkan dari pertama hingga terakhir.

Menganimasikan Transformasi

Implementasi Windows Presentation Foundation (WPF) 3D menggunakan sistem pengaturan waktu dan animasi yang sama dengan grafik 2D. Dengan kata lain, untuk menganimasikan adegan 3D, animasikan properti modelnya. Dimungkinkan untuk menganimasikan properti primitif secara langsung, tetapi biasanya lebih mudah untuk menganimasikan transformasi yang mengubah posisi atau tampilan model. Karena transformasi dapat diterapkan ke objek Model3DGroup serta model individual, dimungkinkan untuk menerapkan satu set animasi ke anak-anak Model3Dgroup dan sekumpulan animasi lain ke sekelompok objek. Untuk informasi latar belakang tentang waktu dan sistem animasi Windows Presentation Foundation (WPF), lihat Gambaran Umum Animasi dan Gambaran Umum Papan Cerita .

Untuk menganimasikan objek di Windows Presentation Foundation (WPF), buat garis waktu, tentukan animasi (yang benar-benar merupakan perubahan dalam beberapa nilai properti dari waktu ke waktu), dan tentukan properti untuk menerapkan animasi. Properti ini harus merupakan properti dari FrameworkElement. Karena semua objek dalam adegan 3D adalah turunan dari Viewport3D, properti yang ditargetkan oleh animasi apa pun yang ingin Anda terapkan ke adegan adalah properti dari properti Viewport3D. Penting untuk menentukan jalur properti untuk animasi dengan hati-hati, karena sintaksnya bisa bertele-tele atau sulit dipahami.

Misalkan Anda ingin memutar objek di tempat, tetapi juga untuk menerapkan gerakan ayur untuk mengekspos lebih banyak objek untuk dilihat. Anda dapat memilih untuk menerapkan RotateTransform3D ke model, dan menganimasikan sumbu rotasinya dari satu vektor ke vektor lainnya. Contoh kode berikut menunjukkan penerapan Vector3DAnimation ke properti Axis dari transformasi Rotation3D, dengan anggapan RotateTransform3D sebagai salah satu transformasi yang diterapkan ke model dengan TransformGroup.

//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

Gunakan sintaks serupa untuk menargetkan properti transformasi lain untuk memindahkan atau menskalakan objek. Misalnya, Anda dapat menerapkan Point3DAnimation ke properti ScaleCenter pada transformasi skala untuk menyebabkan model mendistorsi bentuknya dengan lancar.

Meskipun contoh sebelumnya mengubah properti GeometryModel3D, dimungkinkan juga untuk mengubah properti model lain dalam adegan. Dengan menganimasikan terjemahan yang diterapkan ke objek Cahaya, misalnya, Anda dapat membuat efek cahaya dan bayangan bergerak yang dapat mengubah tampilan model Anda secara dramatis.

Karena kamera juga merupakan model, dimungkinkan untuk mengubah properti kamera juga. Meskipun Anda tentu saja dapat mengubah tampilan adegan dengan mengubah lokasi kamera atau jarak bidang—yang pada dasarnya mengubah seluruh proyeksi adegan—perhatikan bahwa banyak efek yang Anda capai dengan cara ini mungkin tidak memiliki "makna visual" yang sama bagi pemirsa seperti transformasi yang diterapkan pada lokasi atau posisi model di dalam adegan.

Lihat juga