diff --git a/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb b/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb index f5df5f5..9dd5fbe 100644 --- a/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb +++ b/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb @@ -3,6 +3,40 @@ Imports Assimp Imports Assimp.Unmanaged Namespace AssimpModule + Structure ConversionContext + Public Sub New(daeMdlP As Scene, upAxis As UpAxis) + daeMdl = daeMdlP + upAxis = upAxis + newMesh = New Mesh + newObj = New Object3D + + newObj.Meshes.Add(newMesh) + + channelIndicies = New Dictionary(Of Material, Integer) + End Sub + + Dim daeMdl As Scene + Dim UpAxis As UpAxis + Dim newMesh As Mesh + Dim newObj As Object3D + Dim channelIndicies As Dictionary(Of Material, Integer) + End Structure + + Structure ParsingContext + Public Sub New(ctx As ConversionContext) + cc = ctx + dicVertices = New Dictionary(Of Vector3D, Vertex) + dicNormals = New Dictionary(Of Vector3D, Normal) + dicUVs = New Dictionary(Of Vector3D, UV) + dicVertexColors = New Dictionary(Of Color4D, VertexColor) + End Sub + + ReadOnly cc As ConversionContext + Dim dicVertices As Dictionary(Of Vector3D, Vertex) + Dim dicNormals As Dictionary(Of Vector3D, Normal) + Dim dicUVs As Dictionary(Of Vector3D, UV) + Dim dicVertexColors As Dictionary(Of Color4D, VertexColor) + End Structure Public Class AssimpLoader @@ -15,14 +49,163 @@ Namespace AssimpModule 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, ByRef pc As ParsingContext) + Dim newObj = pc.cc.newObj + Dim newMesh = pc.cc.newMesh + Dim daeMdl = pc.cc.daeMdl + Dim channelIndicies = pc.cc.channelIndicies + Dim UpAxis = pc.cc.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 newObj As New Object3D - Dim daeMdl As Scene = Nothing Dim ac As New AssimpContext - Dim channelIndicies As New Dictionary(Of Material, Integer) - daeMdl = ac.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality Or PostProcessSteps.Triangulate) + 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 @@ -94,130 +277,7 @@ Namespace AssimpModule newObj.Materials.Add(mat.Name, newMat) Next - Dim newMesh As New Mesh - newObj.Meshes.Add(newMesh) - - Dim dicVertices As New Dictionary(Of Vector3D, Vertex) - Dim dicNormals As New Dictionary(Of Vector3D, Normal) - Dim dicUVs As New Dictionary(Of Vector3D, UV) - Dim dicVertexColors As New Dictionary(Of Color4D, VertexColor) - - For Each m As Assimp.Mesh In daeMdl.Meshes - 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 n As Vector3D In m.Normals - 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 v As Vector3D In m.Vertices - 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 - newPoint.Vertex = dicVertices(m.Vertices(index)) - End If - - If m.HasNormals Then - newPoint.Normal = dicNormals(m.Normals(index)) - 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 + ComputeNewObj(cc) Return newObj End Function