poniedziałek, 11 października 2010

[WPF 3D] Wizualne drzewo w WPF (visual tree) a elementy w scenie 3D [PL]

Czasem zachodzi potrzeba, by element sceny 3D wiedział o swojej obecności w scenie, np. w celu odpowiedniego obrócenia się, by być przodem do kamery. Oczywiście przy jego dodawaniu do sceny można by było przekazać do niego odpowiednie informacje o scenie, ale okazuje się, że każdy element sceny może sam uzyskać odpowiednie informacje, gdyż wszystkie elementy sceny 3D w WPF (i nie tylko sceny 3D) tworzą drzewo wizualne (visual tree).
Niniejszy wpis poza prezentacją różnych i niezależnych od konkretnego wykorzystania treści stanowi również opis pewnych zagadnień związanych z projektem Mesh Diagram 3D.Informacje dotyczące projektu oznaczone są etykietą MeshDiagram3D.
Wizualne drzewo (visual tree) reprezentuje wszystkie elementy w interfejsie użytkownika, na podstawie którego powstaje obraz aplikacji na urządzeniu wyjściowym (zazwyczaj ekranie). Wizualne drzewo jest używane do wielu rzeczy, takich jak rendering, routing zdarzeń, lokalizacji zasobów (jeśli element nie ma logicznego elementu nadrzędnego) i innych. Możliwe jest poruszanie się po drzewie z wykorzystaniem klasy VisualTreeHelper. Wierzchołkami w drzewie mogą być obiekty typów dziedziczących po klasach Visual lub Visual3D.
Dla przykładu, we wspomnianym wcześniej problemie, w którym element sceny musi poznać swój kontekst (np. Kamerę, która go obserwuje), może przejść po elementach drzewa (wykorzystując VisualTreeHelper.GetParent, która zwraca obiekt typu DependencyObject, będący elementem sceny, więc w tym przypadku Visual3D). By znaleźć obiekt nadrzędny typu Viewport3DVisual, z którego można pozyskać informacje na temat kamery.
Tutaj warto zwrócić jeszcze uwagę na jedną kwestię, wędrując w górę drzewa, po elementach sceny 3D, nie trafiamy na końcu na element typu Viewport3D, ale na element typu Viewport3DVisual. Klasa Viewport3DVisual renderuje należące do niego (jako dzieci = children) obiekty Visual3D na wybrany prostokątny obszar 2D aplikacji. Viewport3DVisual jest więc typową (2D) kontrolką WPF-a typu Visual z elementami 3D (Visual3D) jako dzieci (Właściwość Viewport3DVisual.Children dostarcza kolekcję objektów Visual3D zawartych w Viewport3DVisual).
Ostatecznie funkcja odnajdująca główny element (typu Viewport3DVisual) w drzewie może wyglądać następująco:
public static Viewport3DVisual GetViewport3DVisual( DependencyObject visual )
{
  Viewport3DVisual viewport;
  if ( !( visual is Visual3D ) )
  {
    throw new ArgumentException( "Must be of type Visual3D.", "visual" );
  }
  while ( visual != null )
  {
    if ( !( visual is ModelVisual3D ) )
    {
      break;
    }
    visual = VisualTreeHelper.GetParent( visual );
  }
  viewport = visual as Viewport3DVisual;
  if ( viewport == null && visual != null )
  {
    throw new ApplicationException(
        String.Format( "Unsupported type: '{0}'.  Expected tree of ModelVisual3Ds leading up to a Viewport3DVisual.",
        visual.GetType().FullName ) );
  }
  return viewport;
}
Na koniec chciałbym jeszce polecić artykuł z portalu CodeProject: “Understanding the Visual Tree and Logical Tree in WPF”.
Promuj

1 komentarz:

Posty powiązane / Related posts