http://www.vbarchiv.net/forum/id10_i61389t61389.html ... Von Teil 1 ...
[u]5. Via XAMLReader in seinem Code die Objekte laden.
Und nun kommt der wichtigste Part. XAML Dateien kann man mit der Klasse XamlReader importieren. Nur ist es damit leider nicht getan da man den so importierten ViewPort3D ja eigentlich nicht braucht sondern nur die darin enthaltenen Objekte. Und nun kommt der nächste Nachteil - das Flux Studio erzeugt zwar eine recht schönen XAML Datei, kapselt aber das Objekt in unzähligen einzelnen Model3DGroups so daß man erst recht lange suchen muss um seine Geometrie und das Material aus der XAML Datei zu extrahieren. Folgender Code tut genau das:
Public Function extractModelFromXAML(ByVal Path As String) As Model3DGroup
Dim fS As FileStream = Nothing
Dim xmlR As XmlReader = Nothing
Dim group As Model3DGroup = New Model3DGroup()
Dim counter As Integer = 0
Try
fS = New FileStream(Path, FileMode.Open)
xmlR = XmlReader.Create(fS)
Dim tempVP As Viewport3D = Nothing
Try
tempVP = CType(XamlReader.Load(xmlR), Viewport3D)
Catch ex As XamlParseException
'Diese Exception kommt, wenn man doch versucht eine Textur zu
' laden
End Try
If tempVP IsNot Nothing Then
Dim tempM3DG As Model3DGroup = CType(CType(tempVP.Children(0), _
ModelVisual3D).Content, Model3DGroup)
group.Children.Add(findGeometryModel3D(tempM3DG))
End If
Catch ex As Exception
MessageBox.Show("extractModelFromXAML : " & ex.ToString())
Finally
If fS IsNot Nothing Then
fS.Close()
End If
If xmlR IsNot Nothing Then
xmlR.Close()
End If
End Try
Return group
End Function
Private Function findGeometryModel3D(ByVal group As Model3DGroup) As _
Model3DGroup
Static Dim retVal As Model3DGroup = New Model3DGroup()
Try
If group.Children.Count > 0 Then
For i As Integer = 0 To group.Children.Count - 1
If TypeOf group.Children(i) Is Model3DGroup Then
findGeometryModel3D(CType(group.Children(i), _
Model3DGroup))
ElseIf TypeOf group.Children(i) Is GeometryModel3D Then
Dim geoM3D As GeometryModel3D = New GeometryModel3D()
geoM3D.Geometry = CType(group.Children(i), _
GeometryModel3D).Geometry
geoM3D.Material = CType(group.Children(i), _
GeometryModel3D).Material
geoM3D.BackMaterial = CType(group.Children(i), _
GeometryModel3D).BackMaterial
retVal.Children.Add(geoM3D)
End If
Next
End If
Return retVal
Catch ex As Exception
MessageBox.Show("findGeometryModel3D : " & ex.ToString())
End Try
Return retVal
End Function Was genau macht dieser Code und wie verwendet man ihn? Die Funktion extractModelFromXAML lädt das erzeugte XAML File welches durch die path Variable angegeben wird. Der Rückgabewert ist vom Typ Model3DGroup. Die zweite Funktion findGeometryModel3D sucht innerhalb der XAML Nodes rekursiv nach den GeometryModels (also den eigentlich Objekten) und gibt diese als Liste vom Typ Model3DGroup zurück.
Um diese Funktionen in einem eigenen Projekt zu verwenden erstellt man einfach ein neues WPF Window Projekt und bindet dort über die ToolBox einen neuen ViewPort3D ein. Im folgenden Beispiel heist mein ViewPort3D einfach _viewPort:
Dim _modelVisual as ModelVisual3D = new ModelVisual3D
Public Sub showObject()
if _modelVisual IsNot nothing
'Erzeuge Modelle
Dim mGroup as Model3DGroup = new Model3DGroup()
try
mGroup.Children.Add(extractModelFromXAML("C:\IrgendeinModel.xaml")
catch
'Falls die Rückgabe nothing ist sollte man hier noch was tun
end try
'Erzeuge Licht
Dim sLight as AmbientLight = new AmbientLight(Color.FromRGB(255,255,255)) '
' Einfach weisses Licht
mGroup.Children.Add(sLight)
'Erzeuge Kamera - die Kamera zeigt auf den Koordinaten Mittelpunkt
Dim c as PerspectiveCamera(new Point3D(0,0,10), new Vector3D(0,0,-15), new _
Vector3D(0,1,0), 45)
'Fasse alles zusammen
_modelVisual.Content = mGroup
_viewPort.Camera = c
end if
end Sub Und das wars. So kann man mit relativ einfachen Mitteln Objekte aus Google Sketchup dynamisch in seine WPF Projekte einbinden.
PS: Die Funktionen sind noch nicht perfekt und wenn jemand einen Weg weiss, wie man auch Texturen einbinden kann ohne über eine XAMLParseException zu stolpern bin ich für Hinweise dankbar. |