Dieser Artikel wurde maschinell übersetzt.

DirectX-Faktor

Ein 2D-Portal zu einer 3D-Welt

Charles Petzold

Das Codebeispiel herunterladen

Charles PetzoldWenn Sie sehr versiert in 2D Grafiken sind, könnte man annehmen, dass 3D mit Ausnahme der zusätzlichen Dimension ähnlich ist. Nicht ganz! Wer in der 3D Grafikprogrammierung versuchte sich hat weiß, wie schwierig es ist. 3D Grafikprogrammierung müssen Sie zu master neue und exotische Konzepte über alles in der konventionellen 2D Welt gestoßen. Eine Menge Vorbereitungen sind erforderlich, um nur eine kleine 3D auf dem Bildschirm zu bekommen, und selbst dann eine leichte Fehleinschätzung kann machen es unsichtbar. Folglich ist das visuelle Feedback so wichtig zu lernen Grafikprogrammierung verzögert, bis alle Programmierung Teile und arbeiten in Harmonie sind.

DirectX erkennt den tiefgreifenden Unterschied zwischen 2D und 3D Grafik-Programmierung mit der Aufteilung auf Direct2D und Direct3D. Obwohl Sie 2D und 3D Inhalte auf dem gleichen Ausgabegerät mischen können, dies sind sehr unterschiedliche und verschiedene Programmierschnittstellen und es gibt keinen Mittelweg. DirectX ermöglicht nicht sein ein wenig Land, ein bisschen musikintrument.

Oder gibt es?

Interessanterweise enthält Direct2D einige Konzepte und Einrichtungen, die im 3D Programmierung Universum entstanden. Durch Funktionen wie Geometrie tesselation (die Zerlegung komplexer Geometrien Dreiecke) und 2D Effekte mit Shadern (bestehend aus speziellen Code, der in der Graphics processing Unit oder GPU ausgeführt wird), ist es möglich, einige leistungsfähige 3D Konzepte zu nutzen, während Sie noch im Rahmen des Direct2D.

Darüber hinaus diese 3D Konzepte gefunden und allmählich erforscht werden können, und Sie bekommen die Zufriedenheit wirklich die Ergebnisse auf dem Bildschirm zu sehen. Erhalten Sie Ihre 3D Füße nass in Direct2D, so dass eine spätere Sprung in Direct3D-Programmierung ein bisschen weniger ist schockierend.

Ich denke, es sollte nicht allzu verwunderlich, dass Direct2D einige 3D-Funktionen beinhaltet. Direct2D, architektonisch, baut auf auf Direct3D, dem Direct2D auch die Hardware-Beschleunigung der GPU nutzen zu können. Diese Beziehung zwischen Direct2D und Direct3D wird immer deutlicher, wie Sie die Unterwelt von Direct2D, zu erforschen anzufangen.

Ich werde diese Untersuchung mit einer Überprüfung der 3D-Koordinaten und Koordinatensysteme beginnen.

Den großen Sprung nach außen

Wenn Sie diese Spalte in den letzten Monaten verfolgt haben, wissen Sie, es ist möglich, die GetGlyphRunOutline-Methode eines Objekts aufrufen, die implementiert die IDWriteFontFace-Schnittstelle um eine ID2D1PathGeometry-Instanz abzurufen, die die Umrisse von Textzeichen in Bezug auf geraden Linien und Bézier-Kurven beschreibt. Sie können dann bearbeiten, die Koordinaten dieser Linien und Kurven um die Textzeichen auf verschiedene Weise verzerren.

Es ist auch möglich, die 2D Koordinaten einer Pfad-Geometrie in 3D-Koordinaten und dann Manip umzuwandeln­Ulate diese 3D Koordinaten vor Umwandlung zurück in 2D Pfadgeometrie normalerweise angezeigt. Klingt das nach Spaß?

Koordinaten im zweidimensionalen Raum werden ausgedrückt als die Paare (X, Y), die eine Position auf dem Bildschirm entsprechen; 3D-Koordinaten sind in der Form (X, Y, Z) und vom Konzept her ist die Z-Achse orthogonal auf dem Bildschirm. Es sei denn, Sie mit einem holographischen Display oder einen 3D Drucker zu tun haben, sind diese Z-Koordinaten nicht fast so real wie X- und Y-Koordinaten.

Es gibt andere Unterschiede zwischen 2D und 3D Koordinatensystemen. Konventionell 2D Ursprung – der Punkt (0, 0) — ist die obere linke Ecke des Anzeigegeräts. X Koordinaten nach rechts und Y Koordinaten runter um. In 3D sehr oft der Ursprung liegt in der Mitte des Bildschirms, und es ähnelt mehr einem standard kartesischen Koordinatensystem: Das X-Koordinaten noch Zunahme geht auf das Recht, sondern die Y-Koordinaten-Erhöhung hinauf, und es gibt negative Koordinaten sowie. (Natürlich die Herkunft, Skalierung und Ausrichtung der diese Achsen können mit Matrix-Transformationen geändert werden und sind in der Regel.)

Im Prinzip die positive Z-Achse zeigen aus dem Bildschirm heraus oder in den Bildschirm zeigen. Diese beiden Übereinkommen sind bekannt als "rechten" und "linken" Koordinatensysteme, unter Bezugnahme auf eine Technik, um sie zu unterscheiden: Mit einem rechten Koordinatensystem Wenn Sie den Zeigefinger Ihrer rechten Hand in Richtung der positiven X-Achse und der Mittelfinger in Richtung der positiven Y zeigen zeigt Ihren Daumen auf positiven Z. Auch, wenn Sie die Finger der rechten Hand von der positiven X-Achse auf der positiven y-Achse, Ihre Daumen Punkte zu positiven Z Kurve. Mit einem linken Koordinatensystem ist es das gleiche, außer mit der linken Hand.

Mein Ziel ist es, eine Geometrie 2D Pfad einer kurzen Text-Zeichenfolge abrufen und dann drehen Sie es um den Ursprung in einer 3D Ring also Anfang zum Ende, wie in der Abbildung gezeigt trifft Abbildung 1. Da I'll be Konvertierung von 2D zu 3D Koordinaten Koordinaten und dann zurück zu 2D, habe ich mich entschieden, ein dreidimensionales Koordinatensystem mit Y-Koordinaten, die zunehmende hinunter zu verwenden, wie in 2D. Die positive Z-Achse kommt aus dem Bildschirm heraus, aber es ist wirklich ein linken Koordinatensystem.

The Coordinate System Used for the Programs in This Article
Abbildung 1 das Koordinatensystem für die Programme in diesem Artikel verwendet

Um diese ganze Arbeit so einfach wie möglich zu machen, habe ich eine Schriftartdatei gespeichert als Programm Ressource verwendet und erstellt ein IDWriteFontFile-Objekt für den Erhalt des IDWriteFontFace-Objekts. Alternativ könnten Sie eine IDWriteFontFace durch eine mehr Kreisverkehr Methode aus der System-Schriftart-Auflistung abrufen.

Das ID2D1PathGeometry-Objekt generiert aus der GetGlyphRunOutline-Methode wird dann über die Simplify-Methode mit dem D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES-Argument vereinfachen Sie alle Bézier-Kurven in Sequenzen von kurzen Zeilen übergeben. Dass vereinfachte Geometrie in einer benutzerdefinierten ID2D1GeometrySink-Implementierung übergeben wird mit dem Namen FlattenedGeometrySink zu weiter zerlegen die geraden in viel kürzeren geraden. Das Ergebnis ist eine vollständig Klemmverbinder Geometrie, bestehend nur aus Linien.

Zur Erleichterung der Manipulation von diesen Koordinaten, FlattenedGeometry­Waschbecken generiert eine Sammlung von Polygon-Objekte. Abbildung 2 zeigt die Definition der Polygon-Struktur. Es ist im Grunde nur eine Sammlung von miteinander verbundene 2D Punkte. Jedes Polygon-Objekt entspricht eine geschlossene Figur in der Pfadgeometrie. Nicht alle Figuren in Pfadgeometrien sind geschlossen, aber im Text Glyphen sind immer geschlossen, so dass diese Struktur gut für diesen Zweck ist. Einige Zeichen (z. B. C, E und X) werden durch ein Polygon beschrieben; einige (A, D und O) bestehen aus zwei Polygon-Objekte für innen und außen; einige (B, z. B.) bestehen aus drei; und einige Sonderzeichen möglicherweise viel mehr.

Abbildung 2 die Polygon-Klasse zum Speichern von geschlossenen Pfad Zahlen

struct Polygon
{
  // Constructors
  Polygon()
  {
  }
  Polygon(size_t pointCount)
  {
    Points = std::vector<D2D1_POINT_2F>(pointCount);
  }
  // Move constructor
  Polygon(Polygon && other) : Points(std::move(other.Points))
  {
  }
  std::vector<D2D1_POINT_2F> Points;
  static HRESULT CreateGeometry(ID2D1Factory* factory,
                                const std::vector<Polygon>& polygons,
                                ID2D1PathGeometry** pathGeometry);
};
HRESULT Polygon::CreateGeometry(ID2D1Factory* factory,
                                const std::vector<Polygon>& polygons,
                                ID2D1PathGeometry** pathGeometry)
{
  HRESULT hr;
  if (FAILED(hr = factory->CreatePathGeometry(pathGeometry)))
    return hr;
  Microsoft::WRL::ComPtr<ID2D1GeometrySink> geometrySink;
  if (FAILED(hr = (*pathGeometry)->Open(&geometrySink)))
    return hr;
  for (const Polygon& polygon : polygons)
  {
    if (polygon.Points.size() > 0)
    {
      geometrySink->BeginFigure(polygon.Points[0],
                                D2D1_FIGURE_BEGIN_FILLED);
      if (polygon.Points.size() > 1)
      {
        geometrySink->AddLines(polygon.Points.data() + 1,
                               polygon.Points.size() - 1);
      }
      geometrySink->EndFigure(D2D1_FIGURE_END_CLOSED);
    }
  }
  return geometrySink->Close();
}

Zum herunterladbaren Code für diesen Artikel ist ein Windows-Speicher-Programm CircularText benannt, die erstellt eine Auflistung von Polygon-Objekte basierend auf dem Text "Text in eine unendliche Circle of," wo Ende zurück an den Anfang in einem Kreis verbinden soll. Die Textzeichenfolge wird eigentlich im Programm als "Ext im unendlichen Kreis der T" angegeben um zu vermeiden ein Leerzeichen am Anfang oder am Ende das verschwinden würden, wenn eine Pfadgeometrie aus der Glyphen generiert wird.

Die CircularTextRenderer-Klasse in der CircularText Projekt zwei Std Objekte enthält, geben Sie Polygon namens M_srcPolygons (der ursprüngliche Polygon-Objekte aus der Pfadgeometrie generiert) und M_dstPolygons (die Polygon-Objekte verwendet, um die gerenderten Path-Geometrie zu erzeugen). Abbildung 3 zeigt die Methode CreateWindowSizeDependentResources, die die Quelle-Polygone in die Ziel-Polygone anhand der Größe des Bildschirms konvertiert.

Abbildung 3 von 2D auf 3D nach 2D in das CircularText-Programm

void CircularTextRenderer::CreateWindowSizeDependentResources()
{
  // Get window size and geometry size
  Windows::Foundation::Size logicalSize = m_deviceResources->GetLogicalSize();
  float geometryWidth = m_geometryBounds.right - m_geometryBounds.left;
  float geometryHeight = m_geometryBounds.bottom - m_geometryBounds.top;
  // Calculate a few factors for converting 2D to 3D
  float radius = logicalSize.Width / 2 - 50;
  float circumference = 2 * 3.14159f * radius;
  float scale = circumference / geometryWidth;
  float height = scale * geometryHeight;
  for (size_t polygonIndex = 0; polygonIndex < m_srcPolygons.size(); polygonIndex++)
  {
    const Polygon& srcPolygon = m_srcPolygons.at(polygonIndex);
    Polygon& dstPolygon = m_dstPolygons.at(polygonIndex);
    for (size_t pointIndex = 0; pointIndex < srcPolygon.Points.size(); pointIndex++)
    {
      const D2D1_POINT_2F pt = srcPolygon.Points.at(pointIndex);
      float radians = 2 * 3.14159f * (pt.x - m_geometryBounds.left) / geometryWidth;
      float x = radius * sin(radians);
      float z = radius * cos(radians);
      float y = height * ((pt.y - m_geometryBounds.top) / geometryHeight - 0.5f);
      dstPolygon.Points.at(pointIndex) = Point2F(x, y);
    }
  }
  // Create path geometry from Polygon collection
  DX::ThrowIfFailed(
    Polygon::CreateGeometry(m_deviceResources->GetD2DFactory(),
                            m_dstPolygons,
                            &m_pathGeometry)
    );
}

In der inneren Schleife sehen Sie x, y und Z-Werte berechnet. Dies ist ein 3D Koordinaten, aber es wird auch nicht gespeichert. Es wird stattdessen sofort wieder in 2D reduziert, durch den Z-Wert einfach zu ignorieren. Um Mi­spät die 3D-Koordinaten der Code zuerst konvertiert eine horizontale Position auf der ursprünglichen Pfadgeometrie einen Winkel im Bogenmaß von 0 bis 2π. Die sin und cos Funktionen berechnen Stellung ein Einheitskreis auf die XZ-Ebene. Der y-Wert ist eine direkte Konvertierung von der vertikalen Koordinaten der ursprüngliche Pfadgeometrie.

Die CreateWindowSizeDependentResources-Methode schließt mit der Erlangung eines ID2D1PathGeometry-Objektes vom Ziel Polygon-Sammlung. Die Render-Methode legt dann eine Matrixtransformation den Ursprung in der Mitte des Bildschirms setzen, und beide füllt und zeichnet diese Pfadgeometrie mit das Ergebnis angezeigt, die Abbildung 4.

The CircularText Display
Abbildung 4 die CircularText-Anzeige

Funktioniert das Programm? Es ist schwer zu sagen! Hinsehen, und Sie können sehen einige breiten Zeichen in der Mitte und schmaler Zeichen am linken und rechten. Aber das große Problem ist, dass ich mit einer Pfadgeometrie mit keine sich überschneidenden Linien begann, und die Geometrie erscheint jetzt wieder selbst, mit dem Ergebnis, dass überlappende Bereiche nicht gefüllt sind. Dieser Effekt ist charakteristisch für Geometrien, und es geschieht, ob die Pfadgeometrie erstellt von Polygon-Struktur eine Füllmodus der alternativen oder winding hat.

Dazu einige Perspektive

Dreidimensionale Grafik-Programmierung ist nicht gerade Koordinatenpunkte. Visuelle Hinweise sind erforderlich für den Betrachter ein Bild auf einem 2D Bildschirm als ein Objekt im 3D-Raum darstellt zu interpretieren. In der realen Welt zeigen Sie selten Objekte von einem konstanten Aussichtspunkt. Würde man einen besseren Überblick über den 3D-Text in Abbildung 4 Wenn Sie es etwas kippen könnte so es eher wie der Ring in sieht Abbildung 1.

Um eine Perspektive auf den Text der dreidimensionalen zu erhalten, müssen die Koordinaten im Raum gedreht werden. Wie Sie wissen, unterstützt Direct2D eine Matrix-Transformation-Struktur mit dem Namen D2D1_MATRIX_3x2_F, die Sie verwenden können, 2D Transformationen zu definieren, die vom ersten Aufruf der SetTransform-Methode der ID2D1RenderTarget auf die Ausgabe von 2D-Grafiken angewendet werden können.

In den meisten Fällen wird eine Klasse namens Matrix3x2F aus dem D2D1-Namespace für diesen Zweck verwendet. Diese Klasse leitet sich von D2D1_MATRIX_3x2F_F und stellt Methoden für die Definition der verschiedenen Arten von Normen für die Übersetzung, Skalierung, Drehung und Neigung.

Die Matrix3x2F-Klasse definiert auch eine Methode namens TransformPoint, die die Transformation "manuell" auf einzelne D2D1_POINT_2F-Objekte angewendet werden können. Dies ist nützlich für die Bearbeitung von Punkte, bevor sie wiedergegeben sind.

Sie mögen denken, brauche ich eine 3D-Drehung Matrix, den angezeigten Text zu kippen. Ich werde sicherlich erkunden 3D Matrix-Transformationen in zukünftigen Spalten, aber jetzt kann ich machen, mit 2D Drehung zu tun. Stellen Sie sich befindet sich irgendwo auf der negativen X-Achse des Abbildung 1, schauend in Richtung des Ursprungs. Die positive Z und Y-Achse liegen ebenso wie die X und Y Achsen in einem herkömmlichen 2D Koordinatensystem, so scheint es plausibel, dass durch die Anwendung einer 2D Rotationsmatrix auf Z und Y-Werte, ich die Koordinaten um den Dreimonats - drehen können­dimensionalen X-Achse.

Sie können damit experimentieren, mit dem CircularText-Programm. Erstellen eine 2D Rotationsmatrix in der CreateWindowSizeDependent­Ressourcen-Methode irgendwann, bevor die Polygon-Koordinaten manipuliert werden:

Matrix3x2F tiltMatrix = Matrix3x2F::Rotation(-8);

Das ist eine Drehung um-8 Grad, und die negativen Vorzeichen zeigt eine Rotation entgegen dem Uhrzeigersinn. In der inneren Schleife nach X, y und z wurden berechnet, die Transformation für die z und y-Werte gelten, als wären sie x und y Werte:

 

D2D1_POINT_2F tiltedPoint =
     tiltMatrix.TransformPoint(Point2F(z, y));
z = tiltedPoint.x;
y = tiltedPoint.y;

Abbildung 5 zeigt, was Sie sehen.

The Tilted CircularText Display
Abbildung 5 die schräge CircularText-Anzeige

Das ist viel besser, aber es hat immer noch Probleme. Schlimme Dinge passieren, wenn die Geometrie überlappt, und es nichts deutet darauf hin, welche Teil der Geometrie Nearer to you ist und die weiter entfernt. Es starren, und einige Perspektive UMSCHALT können auftreten.

Dennoch die Möglichkeit 3D Transformationen auf dieses Objekt angewendet deutet darauf hin, dass es auch einfach um das Objekt um die y-Achse drehen könnte – und es ist. Wenn Sie sich vorstellen, den Ursprung von der positiven y-Achse anzeigen, sehen Sie, dass die X- und Z-Achse ausgerichtet genauso wie die X- und y-Achsen in einem 2D Koordinatensystem sind.

Das SpinningCircularText-Projekt implementiert zwei Drehungstransformationen um den Text zu drehen und kippen Sie es. Alle Studiengang computational Logic zuvor in CreateWindowSizeDependentResources ist in die Update-Methode verschoben worden. Die 3D-Punkte werden zweimal gedreht: einmal um die x-Achse auf verstrichene Zeit, und dann um die y-Achse basierten auf dem Benutzer kehren einen Finger auf dem Bildschirm. Diese Update-Methode erscheint Abbildung 6.

Abbildung 6 die Update-Methode des SpinningCircularText

void SpinningCircularTextRenderer::Update(DX::StepTimer const& timer)
{
  // Get window size and geometry size
  Windows::Foundation::Size logicalSize = m_deviceResources->GetLogicalSize();
  float geometryWidth = m_geometryBounds.right - m_geometryBounds.left;
  float geometryHeight = m_geometryBounds.bottom - m_geometryBounds.top;
  // Calculate a few factors for converting 2D to 3D
  float radius = logicalSize.Width / 2 - 50;
  float circumference = 2 * 3.14159f * radius;
  float scale = circumference / geometryWidth;
  float height = scale * geometryHeight;
  // Calculate rotation matrix
  float rotateAngle = -360 * float(fmod(timer.GetTotalSeconds(), 10)) / 10;
  Matrix3x2F rotateMatrix = Matrix3x2F::Rotation(rotateAngle);
  // Calculate tilt matrix
  Matrix3x2F tiltMatrix = Matrix3x2F::Rotation(m_tiltAngle);
  for (size_t polygonIndex = 0; polygonIndex < m_srcPolygons.size(); polygonIndex++)
  {
    const Polygon& srcPolygon = m_srcPolygons.at(polygonIndex);
    Polygon& dstPolygon = m_dstPolygons.at(polygonIndex);
    for (size_t pointIndex = 0; pointIndex < srcPolygon.Points.size(); pointIndex++)
    {
      const D2D1_POINT_2F pt = srcPolygon.Points.at(pointIndex);
      float radians = 2 * 3.14159f * (pt.x - m_geometryBounds.left) / geometryWidth;
      float x = radius * sin(radians);
      float z = radius * cos(radians);
      float y = height * ((pt.y - m_geometryBounds.top) / geometryHeight - 0.5f);
      // Apply rotation to X and Z
      D2D1_POINT_2F rotatedPoint = rotateMatrix.TransformPoint(Point2F(x, z));
      x = rotatedPoint.x;
      z = rotatedPoint.y;
      // Apply tilt to Y and Z
      D2D1_POINT_2F tiltedPoint = tiltMatrix.TransformPoint(Point2F(y, z));
      y = tiltedPoint.x;
      z = tiltedPoint.y;
      dstPolygon.Points.at(pointIndex) = Point2F(x, y);
    }
  }
  // Create path geometry from Polygon collection
  DX::ThrowIfFailed(
    Polygon::CreateGeometry(m_deviceResources->GetD2DFactory(),
    m_dstPolygons,
    &m_pathGeometry)
    );
    // Update FPS display text
    uint32 fps = timer.GetFramesPerSecond();
    m_text = (fps > 0) ?
std::to_wstring(fps) + L" FPS" : L" - FPS";
}

Es ist bekannt, dass zusammengesetzte Matrix-Transformationen gleichbedeutend mit Matrix-Multiplikationen sind und weil Matrix-Multiplikationen nicht kommutativ, auch nicht zusammengesetzte Transformationen. Schalten Sie, um die Anwendung des Neigungssensors und drehen Sie Transformationen für einen anderen Effekt (die Sie eigentlich lieber) zu.

Wenn Sie das SpinningCircularText-Programm zu erstellen, ich angepasst, die SampleFpsTextRenderer-Klasse, die von der Visual Studio -Vorlage erstellen Sie die SpinningCircularTextRenderer-Klasse erstellt, aber ich habe die Anzeige der Rendering-Rate. Dadurch können Sie sehen, wie schlecht die Leistung ist. Ich sehe auf meinem Surface Pro einen Frames per second (FPS) Abbildung 25 im Debug-Modus, das angibt, dass der Code nicht mit die Aktualisierungsrate der Videoanzeige halten.

Wenn Sie diese Leistung nicht mögen, fürchte ich, ich habe schlechte Neuigkeiten: Ich werde es noch schlimmer zu machen.

Vordergrund trennen vom Hintergrund

Das größte Problem mit dem Pfad-Geometrie-Ansatz bei 3D ist die Wirkung der überlappenden Bereiche. Ist es möglich, diejenigen zu vermeiden Überschneidungen? Das Bild, das dieses Programm versucht zu zeichnen ist nicht allzu kompliziert. Zu jeder Zeit gibt es eine Frontansicht des Teil des Textes und eine Rückansicht der Rest des Textes und die Vorderansicht immer oben auf der Rückseite angezeigt werden sollen. Wenn es möglich wäre, die Pfadgeometrie in zwei Pfadgeometrien unterteilen — eine für den Hintergrund und eine für den Vordergrund – Sie könnte diesen Pfadgeometrien mit separaten FillGeometry aufrufen rendern, so im Vordergrund auf dem Hintergrund wäre. Diese zwei Pfadgeometrien konnte sogar mit verschiedenen Pinseln erbracht werden.

Betrachten Sie die ursprüngliche Pfadgeometrie von der GetGlyphRunOutline-Methode erstellte. Das ist nur eine flache 2D Pfadgeometrie, die Besetzung eines rechteckigen Bereichs. Schließlich wird die Hälfte dieser Geometrie im Vordergrund angezeigt, und die andere Hälfte wird im Hintergrund angezeigt. Aber die Zeit, die Polygon-Objekte abgerufen werden, ist es zu spät, um dass Split mit etwas computational Leichtigkeit zu machen.

Stattdessen muss die ursprünglichen Pfadgeometrie in Hälfte abgebrochen werden, bevor die Polygon-Objekte abgerufen werden. Diese Pause ist abhängig von den Drehwinkel, was bedeutet, dass viel mehr Logik in die Update-Methode verschoben werden muss.

Die ursprüngliche Pfadgeometrie kann in der Mitte mit zwei Aufrufe an die CombineWithGeometry-Methode aufgeteilt werden. Diese Methode kombiniert zwei Geometrien auf verschiedene Weise zu einer dritten Geometrie. Der ursprünglichen Pfadgeometrie, die die Textkonturen beschreibt und eine Rechteckgeometrie, die eine Teilmenge der Pfadgeometrie definiert sind die beiden Geometrien, die kombiniert werden. Diese Teilmenge wird angezeigt im Vordergrund oder Hintergrund, je nach den Drehwinkel.

Zum Beispiel wenn der Drehwinkel 0 ist, muss der Rechteckgeometrie die zentrale Hälfte der Pfadgeometrie der Textkonturen abdecken. Dies ist der Teil der ursprünglichen Geometrie, die im Vordergrund angezeigt wird. Aufrufen von CombineWithGeometry mit den D2D1_COMBINE_MODE_INTERSECT-Modus gibt eine Pfadgeometrie, die nur aus diesem zentralen Bereich, während Aufrufen von CombineWithGeometry mit D2D1_COMBINE_MODE_EXCLUDE eine Pfadgeometrie des Restes erhält zurück — die Teile auf Links und rechts. Diese zwei Pfadgeometrien können dann auf Polygon-Objekte separat für die Manipulation der Koordinaten, gefolgt von einer Konvertierung zurück zu separaten Pfadgeometrien für Rendering umrüsten.

Diese Logik ist Bestandteil eines Projekts mit dem Namen OccludedCircularText, die die Render-Methode implementiert, indem die beiden Geometrien mit verschiedenen Pinseln, füllen siehe Abbildung 7.

The OccludedCircularText Display
Abbildung 7 die OccludedCircularText-Anzeige

Jetzt ist es viel mehr auf der Hand, was im Vordergrund ist und was im Hintergrund. Dennoch ist soviel Berechnung der Update-Methode verschoben worden, dass Leistung sehr schlecht ist.

In einer herkömmlichen 2D Programmierumgebung ich würde habe erschöpft die 2D Programmierwerkzeuge zur Verfügung und werden jetzt mit dieser schrecklichen Leistung fest. Direct2D, bietet jedoch eine alternative Methode zum Rendern der Geometrie, die die Logik vereinfacht und verbessert die Leistung enorm. Diese Lösung nutzt die grundlegendsten 2D Polygons — das ist ein Polygon, das spielt auch eine wichtige Rolle in der 3D Programmierung.

Ich spreche natürlich von der bescheidenen Dreieck.

Charles Petzold ist ein langjähriger Beitrag zum MSDN Magazine und Autor von "Programming Windows, 6th Edition" (O' Reilly Media, 2012), ein Buch über das Schreiben von Anwendungen für Windows 8. Seiner Website lautet charlespetzold.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Jim Galasyn (Microsoft)