To podejście jest bardziej skomplikowane od poprzedniego, dlatego trudno przygotować funkcję, która jak to miało miejsce w poprzednim przypadku wykonywała wszystkie czynności.
Pierwszym krokiem jest stworzenie dwóch nakładających się warstw:
- Viewport3D jako warstwy spodniej
- Canvas jako przeźroczystej warstwy nałożonej
<Grid ClipToBounds="True">
<Viewport3D Name="mainViewport" ClipToBounds="True" Grid.Column="0" Grid.Row="0">
<Viewport3D.Camera>
<PerspectiveCamera
FarPlaneDistance="100"
LookDirection="-11,-10,-9"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="11,10,9"
FieldOfView="70" />
Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight
Color="White"
Direction="-2,-3,-1" />
</ModelVisual3D.Content></ModelVisual3D>
</Viewport3D><Canvas Name="mainViewportCanvas" ClipToBounds="True" Grid.Column="0" Grid.Row="0"></Canvas>
</Grid>Kolejnym zadaniem jest lokalizacja punktu ze sceny 3D na nałożonej warstwie typu Canvas. Do transformacji lokalizacji można użyć funkcję podobną do poniższej:
public static Point Get2DPoint(Point3D p3d, Viewport3D vp)
{
bool TransformationResultOK;
Viewport3DVisual vp3Dv = VisualTreeHelper.GetParent(
vp.Children[0]) as Viewport3DVisual;
Matrix3D m = MathUtils.TryWorldToViewportTransform(vp3Dv, out TransformationResultOK);
if (!TransformationResultOK) return new Point(0, 0);
Point3D pb = m.Transform(p3d);
Point p2d = new Point(pb.X, pb.Y);
return p2d;
}
Zauważmy, że ta funkcja używa funkcji TryWorldToViewportTransform
z pakietu 3D Tools (dostępnego tutaj): _3DTools.MathUtils.TryWorldToViewportTransform
.
Kolejnym krokiem jest utworzenie i lokalizacja obiektu TextBlock
:
UIElement IModelVisual3D.GetUIElement(ModelVisual3DFilter FilterSettings, Viewport3D DestinationViewport3D)
{
if (FilterSettings.Texts2D)
{
TextBlock tb = new TextBlock();
tb.Text = Description;
Point p2d = Panel3DMath.Get2DPoint(this.Point3D, DestinationViewport3D);
Canvas.SetTop(tb, p2d.Y);
Canvas.SetLeft(tb, p2d.X);
return tb;
}
else
return new UIElement();
}
Ostatecznie dodajemy
TextBlock
(utworzonego w poprzednim kroku) do naszego obiektu canvas. this.mainViewportCanvas.Children.Add(element.GetUIElement(filter,mainViewport));
(To tylko jedna z części artykułu, przeczytaj pozostałe: 1, 2, 3, 4, 5, 6, 7)