Share via


Cenni preliminari sulle trasformazioni tridimensionali

Aggiornamento: novembre 2007

In questo argomento viene descritto come applicare trasformazioni a modelli tridimensionali nel sistema grafico Windows Presentation Foundation (WPF). Le trasformazioni consentono allo sviluppatore di riposizionare, ridimensionare e orientare nuovamente i modelli senza modificare i valori di base che li definiscono.

Nel presente argomento sono contenute le seguenti sezioni.

  • Spazio della Coordinata tridimensionale
  • Trasformazione di modelli
  • Trasformazioni delle traslazioni
  • Trasformazioni a scala
  • Trasformazioni della rotazione
  • Utilizzo di insiemi di trasformazione
  • Animazione delle trasformazioni
  • Argomenti correlati

Spazio della Coordinata tridimensionale

Il contenuto grafico tridimensionale in Windows Presentation Foundation (WPF) è incapsulato in un elemento, Viewport3D, che può far parte della struttura dell'elemento bidimensionale. Il sistema grafico considera Viewport3D come un elemento visivo bidimensionale come molti altri in Windows Presentation Foundation (WPF). Viewport3D funziona come una finestra, un riquadro di visualizzazione, in una scena tridimensionale. Più precisamente, è una superficie sulla quale è proiettata una scena tridimensionale. Anche se è possibile utilizzare Viewport3D con altri oggetti disegno bidimensionali nello stesso grafico della scena, non si possono inserire oggetti bidimensionali e tridimensionali all'interno di un Viewport3D. Nella discussione seguente, lo spazio delle coordinate descritto è contenuto nell'elemento Viewport3D.

Il sistema di coordinate Windows Presentation Foundation (WPF) per la grafica bidimensionale individua l'origine nella parte superiore sinistra della superficie di rendering, in genere lo schermo. Nel sistema bidimensionale i valori positivi dell'asse x proseguono verso destra mentre i valori positivi dell'asse y proseguono in direzione discendente. Nel sistema di coordinate tridimensionale, tuttavia, l'origine viene individuata al centro dell'area di rendering, con i valori positivi dell'asse x che proseguono verso destra, i valori positivi dell'asse y che proseguono verso l'alto e i valori positivi dell'asse z che proseguono verso l'esterno dell'origine, in direzione del visualizzatore.

Confronto tra sistemi di coordinate

Sistemi di coordinate

Lo spazio definito da questi assi è il frame di riferimento stazionario per gli oggetti tridimensionali in Windows Presentation Foundation (WPF). Quando si compilano modelli in questo spazio e si creano luci e fotocamere per visualizzarli, è consigliabile distinguere il frame di riferimento fisso, o "spazio globale", dal frame di riferimento locale creato per ciascun modello quando si applicano delle trasformazioni. Si ricordi inoltre che gli oggetti dello spazio globale possono avere un aspetto completamente diverso, o non essere visibile a tutti, a seconda delle impostazioni di luce e fotocamera, tuttavia la posizione della fotocamera non modifica la posizione degli oggetti nello spazio globale.

Trasformazione di modelli

Quando vengono creati, i modelli hanno una determinata posizione nella scena. Per spostare i modelli nella scena, ruotarli, o modificarne la dimensione, è poco pratico modificare i vertici che li definiscono. Vengono invece applicate trasformazioni ai modelli, come nel sistema bidimensionale.

Ogni modello di oggetto dispone di una proprietà Transform con la quale è possibile spostare, orientare nuovamente o ridimensionare il modello. Quando si applica una trasformazione, si esegue in effetti l'offset di tutti i punti del modello con qualsiasi vettore o valore specificato dalla trasformazione. In altre parole, viene trasformato lo spazio delle coordinate nel quale il modello è definito ("spazio modello"), ma non vengono modificati i valori che costituiscono la geometria del modello nel sistema di coordinate dell'intera scena ("spazio globale").

Trasformazioni delle traslazioni

Le trasformazioni tridimensionali ereditano dalla classe base astratta Transform3D e includono le classi di trasformazione affini TranslateTransform3D, ScaleTransform3D e RotateTransform3D. Il sistema tridimensionale Windows Presentation Foundation (WPF) fornisce inoltre una classe MatrixTransform3D che consente di specificare le stesse trasformazioni in più concise operazioni della matrice.

TranslateTransform3D consente di spostare tutti i punti nel Model3D in direzione del vettore offset che viene specificato con le proprietà OffsetX, OffsetY e OffsetZ. Ad esempio, dato il vertice di un cubo a (2,2,2), il vettore offset di (0,1.6,1) sposta quel vertice da (2,2,2) a (2,3.6,3). Il vertice del cubo è ancora (2,2,2) nello spazio modello, tuttavia, dal momento che è stata modificata la relazione tra quello spazio e lo spazio globale, risulta che (2,2,2) nello spazio modello diventa (2,3.6,3) nello spazio globale.

Traslazione con offset

Traslazione

Nell'esempio di codice riportato di seguito viene illustrato come applicare una traslazione.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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>

Trasformazioni a scala

ScaleTransform3D consente di modificare la scala del modello con un vettore di ridimensionamento specificato con riferimento a un punto centrale. Specificare una scala uniforme, che adatta il modello con lo stesso valore sugli assi X, Y e Z, in modo da modificare proporzionalmente la dimensione del modello. Ad esempio, impostando le proprietà ScaleX, ScaleY e ScaleZ delle trasformazioni su 0,5 si dimezza la dimensione del modello; impostando le stesse proprietà su 2 si raddoppia la scala su tutti e tre gli assi.

Esempio di ScaleVector

ScaleTransform3D uniforme

Specificando una trasformazione di scala non uniforme (in cui i valori X, Y e Z non sono tutti uguali), è possibile generare un modello da estendere o comprimere in una o due dimensioni senza influire sugli altri. Ad esempio, impostando ScaleX su 1, ScaleY su 2 e ScaleZ su 1 viene generato il modello trasformato con l'altezza raddoppiata ma invariato lunglo gli assi X e Z.

Per impostazione predefinita, con ScaleTransform3D vengono generati vertici per espandere o comprimere l'origine (0,0,0). Se, tuttavia, il modello che si desidera trasformare non è stato creato dall'origine, il ridimensionamento del modello dall'origine non si adatterà al modello "sul posto". Quando invece i vertici del modello sono moltiplicati per il vettore di ridimensionamento, l'operazione di ridimensionamento avrà l'effetto di traslazione sul modello nonché di ridimensionamemto.

Esempio di centro di ridimensionamento

Tre cubi ridimensionati con punto centrale specificato

Per ridimensionare un modello "sul posto," specificare il centro del modello impostando le proprietà CenterX, CenterY e CenterZ di ScaleTransform3D. In tal modo il sistema grafico ridimensiona lo spazio modello, quindi ne esegue la traslazione verso il centro sul Point3D specificato. Se, al contrario, il modello è stato creato intorno all'origine e si specifica un punto centrale diverso, ne deriva il modello traslato lontano dall'origine.

Trasformazioni della rotazione

È possibile ruotare un modello in 3D in molti modi. Una trasformazione tipica della rotazione specifica un asse e un angolo di rotazione intorno all'asse. La classe RotateTransform3D consente di definire un oggetto Rotation3D con la relativa proprietà Rotation. Quindi si specificano le proprietà Axis e Angle su Rotation3D, in questo caso AxisAngleRotation3D, per definire la trasformazione. Negli esempi seguenti viene ruotato un modello di 60 gradi intorno all'asse Y.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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>

Nota:Windows Presentation Foundation (WPF) 3-D è un sistema con origine nell'angolo inferiore destro, che implica che un valore positivo dell'angolo di una rotazione genera una rotazione in senso antiorario rispetto all'asse.

Le rotazioni asse-angolo presumono una rotazione rispetto all'origine se non si specifica un valore per le proprietà CenterX, CenterY e CenterZ su RotateTransform3D. Come per il ridimensionamento, è opportuno ricordare che la rotazione trasforma l'intero spazio delle coordinate del modello. Se il modello è stato creato intorno all'origine, oppure è stato traslato in precedenza, la rotazione potrebbe "girare" rispetto all'origine invece di ruotare sul posto.

Rotazione con un nuove centro specificato

Rotazione con nuovo punto centrale

Per ruotare il modello "sul posto", specificare il centro effettivo del modello come centro di rotazione. Poiché in genere la geometria si basa sull'origine, molto spesso è possibile ottenere il risultato previsto di un insieme di trasformazioni innanzitutto adattando il modello (ridimensionandolo), quindi impostando l'orientamento (ruotandolo) e, infine, spostandolo nella posizione desiderata (traslandolo).

Esempi di rotazione

Rotazione di 60 gradi sugli assi X e Y

Le rotazioni asse-angolo sono utili per le trasformazioni statiche e per alcune animazioni. Si consiglia tuttavia di ruotare il modello di un cubo di 60 gradi rispetto all'asse X, quindi di 45 gradi rispetto all'asse Z. È possibile descrivere questa trasformazione come due distinte trasformazioni affini o come una matrice. Potrebbe tuttavia essere difficile animare correttamente una rotazione definita in questo modo. Sebbene le posizioni iniziale e finale del modello calcolate da uno dei due approcci siano le stesse, le posizioni intermedie assunte dal modello non sono definite dal punto di vista del calcolo. I quaternioni rappresentano un modo alternativo di calcolare l'interpolazione tra l'inizio e la fine di una rotazione.

Un quaternione rappresenta un asse nello spazio tridimensionale e una rotazione intorno a questo. Ad esempio, un quaternione può rappresentare un asse (1,1,2) e una rotazione di 50 gradi. La capacità dei quaternioni di definire le rotazioni deriva dalle due operazioni che è possibile eseguire su di essi: composizione e interpolazione. La composizione di due quaternioni applicata alla geometria significa "ruotare la geometria intorno all'asse2 con la rotazione2, quindi ruotarla intorno all'asse1 con la rotazione1". Con l'utilizzo della composizione è possibile combinare le due rotazioni relative alla geometria per ottenere un singolo quaternione che rappresenta il risultato. Dal momento che l'interpolazione dei quaternioni consente di calcolare un percorso corretto e adeguato da un asse e da un orientamento all'altro, è possibile eseguire l'interpolazione dal quaternione originale a quello composto per ottenere una transizione corretta dall'uno all'altro, con la possibilità di animare la trasformazione. Relativamente ai modelli che si desidera animare, è possibile specificare una destinazione Quaternion per la rotazione utilizzando QuaternionRotation3D per la proprietà Rotation.

Utilizzo di insiemi di trasformazione

Durante la compilazione di una scena, è normale applicare più di una trasformazione a un modello. Aggiungere trasformazioni all'insieme Children della classe Transform3DGroup per raggruppare opportunamente le trasformazioni da applicare a vari modelli della scena. È spesso consigliabile riutilizzare una trasformazione in vari gruppi differenti, in modo molto simile a quanto avviene per il riutilizzo di un modello applicando un insieme diverso di trasformazioni a ciascuna istanza. Notare che l'ordine in cui le trasformazioni vengono aggiunte agli insiemi è significativo: le trasformazioni nell'insieme vengono applicate dalla prima all'ultima.

Animazione delle trasformazioni

L'implementazione Windows Presentation Foundation (WPF) 3-D fa parte dello stesso sistema di temporizzazione e animazione della grafica bidimensionale. In altre parole, per animare una scena tridimensionale, è necessario animare le proprietà dei relativi modelli. È possibile animare direttamente proprietà di primitive, ma generalmente è più semplice animare trasformazioni che modificano la posizione o l'aspetto di modelli. Poiché le trasformazioni possono essere applicate agli oggetti Model3DGroup oltre che ai modelli singoli, è possibile applicare uno insieme di animazioni a un elemento figlio di un oggetto Model3DGroup e un altro insieme di animazioni a un gruppo di oggetti. Per informazioni di base sul sistema di temporizzazione e di animazione Windows Presentation Foundation (WPF), vedere Cenni preliminari sull'animazione e Cenni preliminari sugli storyboard.

Per animare un oggetto in Windows Presentation Foundation (WPF), creare una sequenza temporale, definire un'animazione (che rappresenti una vera modifica del valore di alcune proprietà nel tempo) e specificare la proprietà alla quale applicare l'animazione. Questa deve essere una proprietà di un oggetto FrameworkElement. Poiché tutti gli oggetti in una scena tridimensionale sono elementi figlio di Viewport3D, le proprietà interessate da qualsiasi animazione che si desidera applicare alla scena sono proprietà delle proprietà di Viewport3D. È importante elaborare attentamente il percorso di proprietà per l'animazione, in quanto la sintassi può risultare prolissa.

Si supponga di voler ruotare un oggetto sul posto, ma anche di applicare un movimento oscillante per esporre un'area maggiore dell'oggetto da visualizzare. È possibile scegliere di applicare un oggetto RotateTransform3D al modello e animare l'asse di rotazione da uno vettore a un altro. Nell'esempio di codice riportato di seguito viene illustrata l'applicazione di un oggetto Vector3DAnimation alla proprietà Axis dell’oggetto Rotation3D della trasformazione, presupponendo che RotateTransform3D sia una delle numerose trasformazioni applicate al modello con un oggetto TransformGroup.

//Define a rotation
RotateTransform3D myRotateTransform = 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;

Utilizzare una sintassi simile per gestire altre proprietà di trasformazione in modo da spostare o ridimensionare l'oggetto. Ad esempio è possibile applicare un oggetto Point3DAnimation alla proprietà ScaleCenter su una trasformazione di scala in modo da generare un modello per modificare correttamente la forma.

Anche se negli esempi riportati in precedenza vengono trasformate le proprietà di GeometryModel3D, è inoltre possibile trasformare le proprietà di altri modelli nella scena. Animando le traslazioni applicate agli oggetti luce, è possibile ad esempio creare luci mobili ed effetti di ombreggiatura che possono cambiare notevolmente l'aspetto grafico dei modelli.

Poiché anche le fotocamere sono modelli, è possibile trasformare anche le proprietà delle fotocamere. Sebbene sia possibile modificare l'aspetto grafico della scena trasformando la posizione della fotocamera o le distanze del piano, trasformando di fatto l'intera proiezione della scena, notare che molti degli effetti raggiungibili in questo modo non hanno molto "senso visivo" per il visualizzatore rispetto alle trasformazioni applicate al percorso o alla posizione dei modelli nella scena.

Vedere anche

Attività

Esempio di trasformazioni bidimensionali

Concetti

Cenni preliminari sulla grafica tridimensionale

Cenni preliminari sulle trasformazioni