revert to VB and update to new project file format
This commit is contained in:
453
Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb
Normal file
453
Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb
Normal file
@@ -0,0 +1,453 @@
|
||||
Imports System.IO
|
||||
Imports Assimp
|
||||
Imports Assimp.Unmanaged
|
||||
|
||||
Namespace AssimpModule
|
||||
|
||||
Friend Class ConversionContext
|
||||
|
||||
Public Property DaeMdl As Scene
|
||||
Public Property UpAxis As UpAxis
|
||||
Public Property NewMesh As New Mesh
|
||||
Public Property NewObj As New Object3D
|
||||
Public Property ChannelIndicies As New Dictionary(Of Material, Integer)
|
||||
|
||||
Public Sub New(daeMdlP As Scene, upAxis As UpAxis)
|
||||
DaeMdl = daeMdlP
|
||||
Me.UpAxis = upAxis
|
||||
|
||||
NewObj.Meshes.Add(NewMesh)
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
Friend Class ParsingContext
|
||||
|
||||
Public ReadOnly Property ConversionContext As ConversionContext
|
||||
Public Property DicVertices As New Dictionary(Of Vector3D, Vertex)
|
||||
Public Property DicNormals As New Dictionary(Of Vector3D, Normal)
|
||||
Public Property DicUVs As New Dictionary(Of Vector3D, UV)
|
||||
Public Property DicVertexColors As New Dictionary(Of Color4D, VertexColor)
|
||||
|
||||
Public Sub New(ctx As ConversionContext)
|
||||
ConversionContext = ctx
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
Public Class AssimpLoader
|
||||
|
||||
Public Shared Event LoadingAssimpLibs()
|
||||
Public Shared Event LoadedAssimpLibs()
|
||||
|
||||
Public Shared Property PathToAssimpLib32 As String = "Assimp32.dll"
|
||||
Public Shared Property PathToAssimpLib64 As String = "Assimp64.dll"
|
||||
|
||||
Friend Shared Sub LoadAssimpLibs()
|
||||
If Not AssimpLibrary.Instance.IsLibraryLoaded Then
|
||||
RaiseEvent LoadingAssimpLibs()
|
||||
AssimpLibrary.Instance.LoadLibrary(PathToAssimpLib32, PathToAssimpLib64)
|
||||
RaiseEvent LoadedAssimpLibs()
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Shared Sub ComputeNewObj(cc As ConversionContext)
|
||||
Dim identity As Matrix4x4 = Matrix4x4.Identity
|
||||
ComputeNode(cc.DaeMdl.RootNode, identity, New ParsingContext(cc))
|
||||
End Sub
|
||||
|
||||
Private Shared Sub ComputeNode(node As Node, trafo As Matrix4x4, pc As ParsingContext)
|
||||
Dim newObj = pc.ConversionContext.NewObj
|
||||
Dim newMesh = pc.ConversionContext.NewMesh
|
||||
Dim daeMdl = pc.ConversionContext.DaeMdl
|
||||
Dim channelIndicies = pc.ConversionContext.ChannelIndicies
|
||||
Dim UpAxis = pc.ConversionContext.UpAxis
|
||||
Dim dicVertices = pc.DicVertices
|
||||
Dim dicNormals = pc.DicNormals
|
||||
Dim dicUVs = pc.DicUVs
|
||||
Dim dicVertexColors = pc.DicVertexColors
|
||||
|
||||
trafo = trafo * node.Transform
|
||||
|
||||
If node.HasMeshes Then
|
||||
For Each meshIndex In node.MeshIndices
|
||||
Dim m As Assimp.Mesh = daeMdl.Meshes(meshIndex)
|
||||
|
||||
Dim curMat As Material
|
||||
If m.MaterialIndex > -1 AndAlso newObj.Materials.Count > m.MaterialIndex Then
|
||||
curMat = newObj.Materials.ElementAt(m.MaterialIndex).Value
|
||||
Else
|
||||
curMat = Nothing
|
||||
End If
|
||||
|
||||
For Each untransformedN As Vector3D In m.Normals
|
||||
Dim n = trafo * untransformedN
|
||||
If Not dicNormals.ContainsKey(n) Then
|
||||
Dim newNormal As New Normal
|
||||
|
||||
Select Case UpAxis
|
||||
Case UpAxis.Y
|
||||
newNormal.X = n.X
|
||||
newNormal.Y = n.Y
|
||||
newNormal.Z = n.Z
|
||||
Case UpAxis.Z
|
||||
newNormal.X = n.Y
|
||||
newNormal.Y = n.Z
|
||||
newNormal.Z = n.X
|
||||
End Select
|
||||
|
||||
newMesh.Normals.Add(newNormal)
|
||||
dicNormals.Add(n, newNormal)
|
||||
End If
|
||||
Next
|
||||
|
||||
For Each untranformedV As Vector3D In m.Vertices
|
||||
Dim v = trafo * untranformedV
|
||||
If Not dicVertices.ContainsKey(v) Then
|
||||
Dim newVert As New Vertex
|
||||
|
||||
Select Case UpAxis
|
||||
Case UpAxis.Y
|
||||
newVert.X = v.X
|
||||
newVert.Y = v.Y
|
||||
newVert.Z = v.Z
|
||||
Case UpAxis.Z
|
||||
newVert.X = v.Y
|
||||
newVert.Y = v.Z
|
||||
newVert.Z = v.X
|
||||
End Select
|
||||
|
||||
newMesh.Vertices.Add(newVert)
|
||||
dicVertices.Add(v, newVert)
|
||||
End If
|
||||
Next
|
||||
|
||||
For Each uvList As List(Of Vector3D) In m.TextureCoordinateChannels
|
||||
For Each uv As Vector3D In uvList
|
||||
If Not dicUVs.ContainsKey(uv) Then
|
||||
Dim newUV As New UV
|
||||
|
||||
newUV.U = uv.X
|
||||
newUV.V = uv.Y
|
||||
|
||||
newMesh.UVs.Add(newUV)
|
||||
dicUVs.Add(uv, newUV)
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
|
||||
For Each vcList As List(Of Color4D) In m.VertexColorChannels
|
||||
For Each vc As Color4D In vcList
|
||||
If Not dicVertexColors.ContainsKey(vc) Then
|
||||
Dim newVC As New VertexColor
|
||||
|
||||
newVC.R = vc.R
|
||||
newVC.G = vc.G
|
||||
newVC.B = vc.B
|
||||
newVC.A = vc.A
|
||||
|
||||
newMesh.VertexColors.Add(newVC)
|
||||
dicVertexColors.Add(vc, newVC)
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
|
||||
For Each f As Assimp.Face In m.Faces
|
||||
If f.HasIndices Then
|
||||
Dim newFace As New Face With {.Material = curMat}
|
||||
|
||||
For Each index As Integer In f.Indices
|
||||
If index > -1 Then
|
||||
Dim newPoint As New Point
|
||||
|
||||
If m.HasVertices Then
|
||||
Dim v = trafo * m.Vertices(index)
|
||||
newPoint.Vertex = dicVertices(v)
|
||||
End If
|
||||
|
||||
If m.HasNormals Then
|
||||
Dim n = trafo * m.Normals(index)
|
||||
newPoint.Normal = dicNormals(n)
|
||||
End If
|
||||
|
||||
If curMat IsNot Nothing AndAlso channelIndicies.ContainsKey(curMat) Then
|
||||
Dim tkey As Integer = channelIndicies(curMat)
|
||||
|
||||
If m.HasTextureCoords(tkey) Then
|
||||
newPoint.UV = dicUVs(m.TextureCoordinateChannels(tkey)(index))
|
||||
End If
|
||||
|
||||
If m.HasVertexColors(tkey) Then
|
||||
newPoint.VertexColor = dicVertexColors(m.VertexColorChannels(tkey)(index))
|
||||
End If
|
||||
End If
|
||||
|
||||
newFace.Points.Add(newPoint)
|
||||
End If
|
||||
Next
|
||||
|
||||
If newFace.Points.Count = 3 Then
|
||||
newMesh.Faces.Add(newFace)
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
End If
|
||||
|
||||
For Each n In node.Children
|
||||
ComputeNode(n, trafo, pc)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Public Shared Function FromFile(fileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D
|
||||
Dim LoadedImages As New Dictionary(Of String, Image)
|
||||
Dim ac As New AssimpContext
|
||||
|
||||
Dim cc As New ConversionContext(ac.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality Or PostProcessSteps.Triangulate), UpAxis)
|
||||
|
||||
Dim newObj = cc.NewObj
|
||||
Dim daeMdl = cc.DaeMdl
|
||||
Dim channelIndicies = cc.ChannelIndicies
|
||||
|
||||
For Each et As EmbeddedTexture In daeMdl.Textures
|
||||
If et.HasCompressedData Then
|
||||
Dim newMat As New Material
|
||||
|
||||
Dim ms As New MemoryStream(et.CompressedData)
|
||||
newMat.Image = Image.FromStream(ms)
|
||||
ms.Close()
|
||||
|
||||
newObj.Materials.Add("tex_" & daeMdl.Textures.IndexOf(et), newMat)
|
||||
End If
|
||||
Next
|
||||
|
||||
For Each mat As Assimp.Material In daeMdl.Materials
|
||||
Dim newMat As New Material
|
||||
Dim texSlot As TextureSlot? = Nothing
|
||||
Dim col4d As Color4D? = Nothing
|
||||
|
||||
newMat.Opacity = mat.Opacity
|
||||
|
||||
Select Case True
|
||||
Case mat.HasTextureNormal
|
||||
texSlot = mat.TextureNormal
|
||||
Case mat.HasTextureDiffuse
|
||||
texSlot = mat.TextureDiffuse
|
||||
Case mat.HasTextureAmbient
|
||||
texSlot = mat.TextureAmbient
|
||||
Case mat.HasTextureSpecular
|
||||
texSlot = mat.TextureSpecular
|
||||
End Select
|
||||
|
||||
Select Case True
|
||||
Case mat.HasColorDiffuse
|
||||
col4d = mat.ColorDiffuse
|
||||
Case mat.HasColorAmbient
|
||||
col4d = mat.ColorAmbient
|
||||
Case mat.HasColorSpecular
|
||||
col4d = mat.ColorSpecular
|
||||
End Select
|
||||
|
||||
If texSlot IsNot Nothing Then
|
||||
Dim filePath As String = texSlot.Value.FilePath
|
||||
|
||||
If LoadMaterials Then
|
||||
If filePath <> "" Then
|
||||
Dim combiPath As String = Path.Combine(Path.GetDirectoryName(fileName), filePath)
|
||||
If File.Exists(combiPath) Then
|
||||
newMat.Image = LoadImage(combiPath, LoadedImages)
|
||||
ElseIf File.Exists(filePath) Then
|
||||
newMat.Image = LoadImage(filePath, LoadedImages)
|
||||
End If
|
||||
ElseIf texSlot.Value.TextureIndex > -1 AndAlso daeMdl.Textures.Count > texSlot.Value.TextureIndex Then
|
||||
Dim et As EmbeddedTexture = daeMdl.Textures(texSlot.Value.TextureIndex)
|
||||
If et.HasCompressedData Then
|
||||
Dim ms As New MemoryStream(et.CompressedData)
|
||||
newMat.Image = Image.FromStream(ms)
|
||||
ms.Close()
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
channelIndicies.Add(newMat, texSlot.Value.UVIndex)
|
||||
End If
|
||||
|
||||
If col4d IsNot Nothing Then
|
||||
newMat.Color = Color.FromArgb(col4d.Value.R * 255, col4d.Value.G * 255, col4d.Value.B * 255)
|
||||
End If
|
||||
|
||||
newObj.Materials.Add(mat.Name, newMat)
|
||||
Next
|
||||
|
||||
ComputeNewObj(cc)
|
||||
|
||||
Return newObj
|
||||
End Function
|
||||
|
||||
Public Shared Sub ToFile(fileName As String, obj As Object3D)
|
||||
Dim mdl As New Scene
|
||||
Dim dicMatIndex As New Dictionary(Of Material, Integer)
|
||||
|
||||
Dim texDir As String = ""
|
||||
If obj.Materials.Count > 0 Then
|
||||
texDir = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName))
|
||||
If Not Directory.Exists(texDir) Then
|
||||
Directory.CreateDirectory(texDir)
|
||||
End If
|
||||
End If
|
||||
|
||||
For Each kvp As KeyValuePair(Of String, Material) In obj.Materials
|
||||
Dim mat As New Assimp.Material
|
||||
|
||||
mat.Name = If(kvp.Key <> "", kvp.Key, "_" & mdl.Materials.Count)
|
||||
mat.Opacity = mat.Opacity
|
||||
|
||||
Dim texslot As New TextureSlot
|
||||
texslot.TextureIndex = mdl.Textures.Count
|
||||
texslot.TextureType = TextureType.Diffuse
|
||||
texslot.UVIndex = 0
|
||||
|
||||
Dim ms As New MemoryStream
|
||||
kvp.Value.Image.Save(ms, Imaging.ImageFormat.Png)
|
||||
'Dim tex As New EmbeddedTexture("png", ms.GetBuffer)
|
||||
ms.Close()
|
||||
|
||||
If kvp.Value.Image IsNot Nothing Then
|
||||
texslot.FilePath = Path.Combine(texDir, mat.Name & ".png")
|
||||
File.WriteAllBytes(texslot.FilePath, ms.GetBuffer)
|
||||
End If
|
||||
|
||||
'mdl.Textures.Add(tex)
|
||||
mat.AddMaterialTexture(texslot)
|
||||
mdl.Materials.Add(mat)
|
||||
|
||||
If kvp.Value.Color IsNot Nothing Then
|
||||
With kvp.Value.Color.Value
|
||||
mat.ColorDiffuse = New Color4D(.R / 255, .G / 255, .B / 255, 1)
|
||||
End With
|
||||
End If
|
||||
|
||||
dicMatIndex.Add(kvp.Value, mdl.Materials.Count - 1)
|
||||
Next
|
||||
|
||||
Dim dicTexMesh As New Dictionary(Of Material, Assimp.Mesh)
|
||||
Dim dicMeshDicVertIndex As New Dictionary(Of Assimp.Mesh, Dictionary(Of Vertex, Integer))
|
||||
Dim dicCounter As New Dictionary(Of Assimp.Mesh, Integer)
|
||||
|
||||
For Each mesh As Mesh In obj.Meshes
|
||||
For Each f As Face In mesh.Faces
|
||||
Dim m As Assimp.Mesh
|
||||
|
||||
If dicTexMesh.ContainsKey(f.Material) Then
|
||||
m = dicTexMesh(f.Material)
|
||||
Else
|
||||
m = New Assimp.Mesh("Mesh_" & mdl.MeshCount + 1)
|
||||
m.PrimitiveType = PrimitiveType.Triangle
|
||||
If dicMatIndex.ContainsKey(f.Material) Then
|
||||
m.MaterialIndex = dicMatIndex(f.Material)
|
||||
End If
|
||||
mdl.Meshes.Add(m)
|
||||
dicTexMesh.Add(f.Material, m)
|
||||
dicMeshDicVertIndex.Add(m, New Dictionary(Of Vertex, Integer))
|
||||
dicCounter.Add(m, 0)
|
||||
End If
|
||||
|
||||
Dim newFace As New Assimp.Face
|
||||
|
||||
For Each p As Point In f.Points
|
||||
newFace.Indices.Add(dicCounter(m))
|
||||
|
||||
If p.Vertex IsNot Nothing Then
|
||||
Dim vert As New Vector3D
|
||||
vert.X = p.Vertex.X
|
||||
vert.Y = p.Vertex.Y
|
||||
vert.Z = p.Vertex.Z
|
||||
m.Vertices.Add(vert)
|
||||
Else
|
||||
m.Vertices.Add(New Vector3D(0, 0, 0))
|
||||
End If
|
||||
|
||||
If p.Normal IsNot Nothing Then
|
||||
Dim norm As New Vector3D
|
||||
norm.X = p.Normal.X
|
||||
norm.Y = p.Normal.Y
|
||||
norm.Z = p.Normal.Z
|
||||
m.Normals.Add(norm)
|
||||
Else
|
||||
m.Normals.Add(New Vector3D(0, 0, 0))
|
||||
End If
|
||||
|
||||
'If p.UV IsNot Nothing Then
|
||||
' Dim uv As New Vector3D
|
||||
' uv.X = p.UV.U
|
||||
' uv.Y = p.UV.V
|
||||
' m.TextureCoordinateChannels(0).Add(uv)
|
||||
'Else
|
||||
' m.TextureCoordinateChannels(0).Add(New Vector3D(0, 0, 0))
|
||||
'End If
|
||||
|
||||
'If p.VertexColor IsNot Nothing Then
|
||||
' Dim vc As New Color4D
|
||||
' vc.R = p.VertexColor.R
|
||||
' vc.G = p.VertexColor.G
|
||||
' vc.B = p.VertexColor.B
|
||||
' vc.A = p.VertexColor.A
|
||||
' m.VertexColorChannels(0).Add(vc)
|
||||
'Else
|
||||
' m.VertexColorChannels(0).Add(New Color4D(0, 0, 0, 0))
|
||||
'End If
|
||||
|
||||
dicCounter(m) += 1
|
||||
Next
|
||||
|
||||
m.Faces.Add(newFace)
|
||||
Next
|
||||
Next
|
||||
|
||||
'Add Root Node
|
||||
mdl.RootNode = New Node(Path.GetFileName(fileName))
|
||||
|
||||
'Add Mesh Indicies
|
||||
For i As Integer = 0 To mdl.MeshCount - 1
|
||||
mdl.RootNode.MeshIndices.Add(i)
|
||||
Next
|
||||
|
||||
Dim ac As New AssimpContext
|
||||
|
||||
Dim formatID As String = ""
|
||||
Dim myExt As String = Path.GetExtension(fileName).ToLower.Substring(1)
|
||||
For Each efd As ExportFormatDescription In ac.GetSupportedExportFormats
|
||||
If myExt = efd.FileExtension Then
|
||||
formatID = efd.FormatId
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
ac.ExportFile(mdl, fileName, formatID)
|
||||
End Sub
|
||||
|
||||
Private Shared Function LoadImage(fileName As String, loadedImages As Dictionary(Of String, Image)) As Image
|
||||
If File.Exists(fileName) Then
|
||||
If loadedImages.ContainsKey(fileName) Then
|
||||
Return loadedImages(fileName)
|
||||
Else
|
||||
Dim fs As New FileStream(fileName, FileMode.Open, FileAccess.Read)
|
||||
Dim img As Image = Image.FromStream(fs)
|
||||
fs.Close()
|
||||
|
||||
For Each kvp In loadedImages
|
||||
If IsTheSameAs(img, kvp.Value) Then
|
||||
Return kvp.Value
|
||||
End If
|
||||
Next
|
||||
|
||||
loadedImages.Add(fileName, img)
|
||||
Return img
|
||||
End If
|
||||
End If
|
||||
Return Nothing
|
||||
End Function
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
Reference in New Issue
Block a user