190607 c1

- Add Pilz.Drawing.Drawing3D.OpenGLFactory
- Fix small bugs in Pilz.UI.PaintingControl
This commit is contained in:
2019-06-07 20:56:19 +02:00
parent ef15e45df7
commit 2f09834fa0
65 changed files with 6670 additions and 118 deletions

View File

@@ -0,0 +1,250 @@
Imports System.Globalization
Imports System.IO
Imports System.Threading
Imports Aspose.ThreeD
Imports Aspose.ThreeD.Entities
Imports Aspose.ThreeD.Formats
Imports Aspose.ThreeD.Shading
Imports Aspose.ThreeD.Utilities
Namespace Aspose3DModule
Public Class Aspose3DLoader
Private Shared hasActivatedMemoryPatching As Boolean = False
Private Shared Sub ActivateMemoryPatching()
If Not hasActivatedMemoryPatching Then
LicenseHelper.AsposeModifyInMemory.ActivateMemoryPatching()
hasActivatedMemoryPatching = True
End If
End Sub
Public Shared Function FromFile(fileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D
ActivateMemoryPatching()
'Create new Model
Dim obj3d As New Object3D
'Create new temporary CultureInfo
Dim curThread As Thread = Thread.CurrentThread
Dim curCultInfo As CultureInfo = curThread.CurrentCulture
Dim newCultInfo As New CultureInfo(curCultInfo.Name)
newCultInfo.NumberFormat.NumberDecimalSeparator = "."
newCultInfo.NumberFormat.PercentDecimalSeparator = "."
newCultInfo.NumberFormat.CurrencyDecimalSeparator = "."
newCultInfo.NumberFormat.NumberGroupSeparator = ","
newCultInfo.NumberFormat.PercentGroupSeparator = ","
newCultInfo.NumberFormat.CurrencyGroupSeparator = ","
curThread.CurrentCulture = newCultInfo
'Load Model from file
Dim scene As New Scene(fileName)
'Reset Cultur-Info
curThread.CurrentCulture = curCultInfo
'Triangulate the Model
PolygonModifier.Triangulate(scene)
'Create Dictionary for Materials
Dim dicMaterials As New Dictionary(Of Aspose.ThreeD.Shading.Material, Material)
'Create List of all avaiable Map-States
Dim MapNames As String() = {Aspose.ThreeD.Shading.Material.MapDiffuse, Aspose.ThreeD.Shading.Material.MapAmbient, Aspose.ThreeD.Shading.Material.MapSpecular, Aspose.ThreeD.Shading.Material.MapEmissive, Aspose.ThreeD.Shading.Material.MapNormal}
Dim ColorNames As String() = {"DiffuseColor", "AmbientColor", "SpecularColor", "EmissiveColor"}
For Each node As Node In scene.RootNode.ChildNodes
'Add new Materials, if not added
For Each mat As Aspose.ThreeD.Shading.Material In node.Materials
If Not dicMaterials.ContainsKey(mat) Then
'Create new Material
Dim newMat As New Material
'Get TextureBase
Dim texBase As TextureBase = Nothing
Dim curmnindex As Byte = 0
Do While texBase Is Nothing AndAlso curmnindex < MapNames.Length
texBase = mat.GetTexture(MapNames(curmnindex))
curmnindex += 1
Loop
If texBase IsNot Nothing Then
If LoadMaterials Then
'Get Texture Image
Dim imgFile As String = texBase.GetPropertyValue("FileName")
imgFile = imgFile.Replace("/", "\")
'Load and set Image
If imgFile <> "" Then
Dim fs As New FileStream(imgFile, FileMode.Open, FileAccess.Read)
newMat.Image = Image.FromStream(fs)
fs.Close()
End If
End If
End If
'Get Texture Color
Dim texcol As Vector3? = Nothing
Dim curcnindex As Byte = 0
Do While texcol Is Nothing AndAlso curcnindex < ColorNames.Length
texcol = mat.GetPropertyValue(ColorNames(curcnindex))
curcnindex += 1
Loop
If texcol IsNot Nothing Then
newMat.Color = Color.FromArgb(texcol?.x, texcol?.y, texcol?.z)
End If
'Add Material to Object3D
obj3d.Materials.Add(mat.Name, newMat)
'Add Dictionary-Entry
dicMaterials.Add(mat, newMat)
End If
Next
'Get Aspose-Mesh
Dim curMesh As Entities.Mesh = node.GetEntity(Of Entities.Mesh)
If curMesh IsNot Nothing Then
'Create new Mesh
Dim newMesh As New Mesh
'Create Vertices
For Each vert As Vector4 In curMesh.ControlPoints
'Create new Vertex
Dim newVert As New Vertex
'Set Vertex Data
newVert.X = vert.x
newVert.Y = vert.y
newVert.Z = vert.z
'Add new Vertex
newMesh.Vertices.Add(newVert)
Next
'Create Normals
Dim veNormals As VertexElementNormal = curMesh.GetElement(VertexElementType.Normal)
If veNormals IsNot Nothing Then
For Each n As Vector4 In veNormals.Data
'Create new Normal
Dim newNormal As New Normal
'Set Normal Data
newNormal.X = n.x
newNormal.Y = n.y
newNormal.Z = n.z
'Add new Normal
newMesh.Normals.Add(newNormal)
Next
End If
'Create Normals
Dim veUVs As VertexElementUV = curMesh.GetElement(VertexElementType.UV)
If veUVs IsNot Nothing Then
For Each uv As Vector4 In veUVs.Data
'Create new UV
Dim newUV As New UV
'Set UV Data
newUV.U = uv.x
newUV.V = uv.y
'Add new UV
newMesh.UVs.Add(newUV)
Next
End If
'Create Normals
Dim veVertexColor As VertexElementVertexColor = curMesh.GetElement(VertexElementType.VertexColor)
If veVertexColor IsNot Nothing Then
For Each n As Vector4 In veVertexColor.Data
'Create new Normal
Dim newVC As New VertexColor
'Set Normal Data
newVC.R = n.x
newVC.G = n.y
newVC.B = n.z
newVC.A = n.w
'Add new Normal
newMesh.VertexColors.Add(newVC)
Next
End If
'Get Material-Indicies
Dim veMaterials As VertexElementMaterial = curMesh.GetElement(VertexElementType.Material)
'Definde Index for VertexElement.Indicies
Dim veIndex As Integer = 0
'Build Polygones
For iPoly = 0 To curMesh.Polygons.Count - 1
'Get current Polygon
Dim poly As Integer() = curMesh.Polygons(iPoly)
'Create new Face
Dim f As New Face
'Set Texture, if avaiable
If veMaterials IsNot Nothing Then
f.Material = dicMaterials(node.Materials(veMaterials.Indices(iPoly)))
ElseIf node.Material IsNot Nothing Then
f.Material = dicMaterials(node.Material)
End If
For Each index As Integer In poly
'Create new Point
Dim p As New Point
'Set Vertex
p.Vertex = newMesh.Vertices(index)
'Set Normal
If veNormals IsNot Nothing Then
p.Normal = newMesh.Normals(veNormals.Indices(veIndex))
End If
'Set UV
If veUVs IsNot Nothing Then
p.UV = newMesh.UVs(veUVs.Indices(veIndex))
End If
'Set Vertex Color
If veVertexColor IsNot Nothing Then
p.VertexColor = newMesh.VertexColors(veVertexColor.Indices(veIndex))
End If
'Add new Point
f.Points.Add(p)
'Increment VertexElementIndicies-Index
veIndex += 1
Next
'Add new Face
newMesh.Faces.Add(f)
Next
'Add new Mesh
obj3d.Meshes.Add(newMesh)
End If
Next
'Return the new Object3D
Return obj3d
End Function
End Class
End Namespace

View File

@@ -0,0 +1,391 @@
Imports System.IO
Imports Assimp
Imports Assimp.Unmanaged
Namespace AssimpModule
Public Class AssimpLoader
Public Shared PathToAssimpLib32 As String = "Assimp32.dll"
Public Shared PathToAssimpLib64 As String = "Assimp64.dll"
Friend Shared Sub LoadAssimpLibs()
If Not AssimpLibrary.Instance.IsLibraryLoaded Then
AssimpLibrary.Instance.LoadLibrary(PathToAssimpLib32, PathToAssimpLib64)
End If
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)
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
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
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

View File

@@ -0,0 +1,391 @@
Imports System.Globalization
Imports System.IO
Imports System.Threading
Imports Pilz.S3DFileParser.Exceptions
Namespace ObjModule
Public Class ObjFile
Public Shared Function FromFile(FileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D
Dim curThread As Thread = Thread.CurrentThread
Dim curCultInfo As CultureInfo = curThread.CurrentCulture
Dim newCultInfo As New CultureInfo(curCultInfo.Name)
newCultInfo.NumberFormat.NumberDecimalSeparator = "."
newCultInfo.NumberFormat.PercentDecimalSeparator = "."
newCultInfo.NumberFormat.CurrencyDecimalSeparator = "."
newCultInfo.NumberFormat.NumberGroupSeparator = ","
newCultInfo.NumberFormat.PercentGroupSeparator = ","
newCultInfo.NumberFormat.CurrencyGroupSeparator = ","
curThread.CurrentCulture = newCultInfo
Dim newObj As New Object3D
Dim newMesh As New Mesh
Dim curObjPath As String = Path.GetDirectoryName(FileName)
Dim mtllibs As New Dictionary(Of String, MaterialLib)
Dim curMaterialLib As MaterialLib = Nothing
Dim curMaterial As Material = Nothing
Dim srObj As New StreamReader(FileName, Text.Encoding.ASCII)
Dim line As String = ""
Do Until srObj.EndOfStream
line = srObj.ReadLine.Trim
If line <> "" Then
Select Case True
Case line.StartsWith("mtllib ")
Dim name As String = line.Substring(7)
If Not mtllibs.ContainsKey(name) Then
Dim mtlfile As String = Path.Combine(curObjPath, name)
If Not File.Exists(mtlfile) Then Throw New MaterialException("Material Library not found!")
Dim newmtl As New MaterialLib
newmtl.FromFile(mtlfile, LoadMaterials)
mtllibs.Add(name, newmtl)
curMaterialLib = newmtl
For Each kvp As KeyValuePair(Of String, Material) In curMaterialLib.Materials
If Not newObj.Materials.ContainsKey(kvp.Key) Then newObj.Materials.Add(kvp.Key, kvp.Value)
Next
Else
curMaterialLib = mtllibs(name)
End If
Case line.StartsWith("usemtl ")
curMaterial = curMaterialLib.Materials(line.Substring(7))
Case line.StartsWith("v ")
If line.Contains("nan") Then line = line.Replace("nan", "0")
Dim splitXYZ() As String = line.Substring(2).Split(" "c)
Dim tX As Double = Convert.ToDouble(splitXYZ(0))
Dim tY As Double = Convert.ToDouble(splitXYZ(1))
Dim tZ As Double = Convert.ToDouble(splitXYZ(2))
Dim v As New Vertex
Select Case UpAxis
Case UpAxis.Y
v.X = tX
v.Y = tY
v.Z = tZ
Case UpAxis.Z
v.X = tY
v.Y = tZ
v.Z = tX
End Select
newMesh.Vertices.Add(v)
Case line.StartsWith("vt ")
Dim uvstr() As String = line.Substring(3).Split(" "c)
Dim uv As New UV With {
.U = Convert.ToSingle(uvstr(0)),
.V = Convert.ToSingle(uvstr(1))}
newMesh.UVs.Add(uv)
Case line.StartsWith("vn ")
Dim splitXYZ() As String = line.Substring(3).Split(" "c)
Dim tX As Single = Convert.ToSingle(splitXYZ(0))
Dim tY As Single = Convert.ToSingle(splitXYZ(1))
Dim tZ As Single = Convert.ToSingle(splitXYZ(2))
Dim n As New Normal
Select Case UpAxis
Case UpAxis.Y
n.X = tX
n.Y = tY
n.Z = tZ
Case UpAxis.Z
n.X = tZ
n.Y = tY
n.Z = tX
End Select
newMesh.Normals.Add(n)
Case line.StartsWith("vc ")
Dim splitRGB() As String = line.Substring(3).Split(" "c)
Dim tX As Single = Convert.ToSingle(splitRGB(0))
Dim tY As Single = Convert.ToSingle(splitRGB(1))
Dim tZ As Single = Convert.ToSingle(splitRGB(2))
Dim vc As New VertexColor
Select Case UpAxis
Case UpAxis.Y
vc.R = tX
vc.G = tY
vc.B = tZ
Case UpAxis.Z
vc.R = tY
vc.G = tZ
vc.B = tX
End Select
newMesh.VertexColors.Add(vc)
Case line.StartsWith("f ")
Dim tri As New Face With {.Material = curMaterial}
For Each xyz As String In line.Substring(2).Split(" "c)
xyz = xyz.Trim
If xyz = "" Then Continue For
Dim splitsub() As String = Nothing
Dim p As New Point
Select Case True
Case xyz.Contains("/")
splitsub = xyz.Split("/"c)
Case xyz.Contains("\")
splitsub = xyz.Split("\"c)
Case Else
splitsub = {0, 0, 0}
End Select
Dim v1 As String = splitsub(0)
Dim v2 As String = splitsub(1)
Dim v3 As String = splitsub(2)
If v1 <> "" Then
p.Vertex = newMesh.Vertices(Convert.ToInt32(v1) - 1)
End If
If v2 <> "" Then
p.UV = newMesh.UVs(Convert.ToInt32(v2) - 1)
Else
Dim newUV As New UV With {.U = 0, .V = 0}
p.UV = newUV
newMesh.UVs.Add(newUV)
End If
If v3 <> "" Then
p.Normal = newMesh.Normals(Convert.ToInt32(v3) - 1)
End If
If splitsub.Count > 3 Then
Dim v4 As String = splitsub(3)
If v4 <> "" Then p.VertexColor = newMesh.VertexColors(Convert.ToInt32(v4) - 1)
End If
tri.Points.Add(p)
Next
newMesh.Faces.Add(tri)
End Select
End If
Loop
newObj.Meshes.Add(newMesh)
curThread.CurrentCulture = curCultInfo
srObj.Close()
Return newObj
End Function
Public Shared Sub ToFile(FileName As String, obj As Object3D)
Dim fs As New FileStream(FileName, FileMode.Create, FileAccess.ReadWrite)
Dim sw As New StreamWriter(fs, Text.Encoding.ASCII)
If obj.Materials.Count > 0 Then
Dim mtlName As String = Path.GetFileNameWithoutExtension(FileName) & ".mtl"
Dim mtlFile As String = Path.Combine(Path.GetDirectoryName(FileName), mtlName)
sw.WriteLine($"mtllib {mtlName}")
MaterialLib.ToFile(mtlFile, obj)
End If
Dim curVertCount As Integer = 1
Dim curUVCount As Integer = 1
Dim curNormCount As Integer = 1
Dim curVertColCount As Integer = 1
For Each m As Mesh In obj.Meshes
For Each vert As Vertex In m.Vertices
sw.WriteLine($"v {vert.X.ToString.Replace(",", ".")} {vert.Y.ToString.Replace(",", ".")} {vert.Z.ToString.Replace(",", ".")}")
Next
For Each uv As UV In m.UVs
sw.WriteLine($"vt {uv.U.ToString.Replace(",", ".")} {uv.V.ToString.Replace(",", ".")}")
Next
For Each norm As Normal In m.Normals
sw.WriteLine($"vn {norm.X.ToString.Replace(",", ".")} {norm.Y.ToString.Replace(",", ".")} {norm.Z.ToString.Replace(",", ".")}")
Next
For Each vertcol As VertexColor In m.VertexColors
sw.WriteLine($"vc {vertcol.R.ToString.Replace(",", ".")} {vertcol.G.ToString.Replace(",", ".")} {vertcol.B.ToString.Replace(",", ".")}")
Next
Dim curMtl As Material = Nothing
For Each f As Face In m.Faces
If curMtl IsNot f.Material Then
curMtl = f.Material
sw.WriteLine($"usemtl _{GetIndexOfMaterialInList(obj, curMtl)}")
End If
sw.Write("f")
For Each p As Point In f.Points
sw.Write(" ")
sw.Write(curVertCount + m.Vertices.IndexOf(p.Vertex))
sw.Write("/")
If p.UV IsNot Nothing Then sw.Write(curUVCount + m.UVs.IndexOf(p.UV))
sw.Write("/")
If p.Normal IsNot Nothing Then sw.Write(curNormCount + m.Normals.IndexOf(p.Normal))
If m.VertexColors.Count > 0 Then
sw.Write("/")
If p.VertexColor IsNot Nothing Then sw.Write(curVertColCount + m.VertexColors.IndexOf(p.VertexColor))
End If
Next
sw.WriteLine()
Next
curVertCount += m.Vertices.Count
curUVCount += m.UVs.Count
curNormCount += m.Normals.Count
curVertColCount += m.VertexColors.Count
Next
sw.Flush()
fs.Close()
End Sub
Public Shared Function GetIndexOfMaterialInList(obj As Object3D, matToFind As Material) As Integer
For Index As Integer = 0 To obj.Materials.Count - 1
If obj.Materials.ElementAt(Index).Value.Equals(matToFind) Then
Return Index
End If
Next
Return -1
End Function
End Class
Public Class MaterialLib
Public ReadOnly Property Materials As New Dictionary(Of String, Material)
Private ReadOnly LoadedImages As New Dictionary(Of String, Image)
Public Sub FromFile(fileName As String, LoadMaterials As Boolean)
LoadedImages.Clear()
Dim curMatLibPath As String = Path.GetDirectoryName(fileName)
Dim curMat As Material = Nothing
Dim curName As String = ""
Dim srMtl As New StreamReader(fileName, Text.Encoding.ASCII)
Dim line As String = ""
Do Until srMtl.EndOfStream
line = srMtl.ReadLine
Select Case True
Case line.StartsWith("newmtl ")
curMat = New Material
curName = line.Substring(7)
Materials.Add(curName, curMat)
Case line.ToLower.StartsWith("kd ")
Dim splitColor() As String = line.Substring(3).Split(" "c)
Dim col As Color = Color.FromArgb(
Convert.ToSingle(Math.Round(255 * splitColor(0))),
Convert.ToSingle(Math.Round(255 * splitColor(1))),
Convert.ToSingle(Math.Round(255 * splitColor(2))))
curMat.Color = col
Case line.ToLower.StartsWith("d ")
curMat.Opacity = Convert.ToSingle(line.Substring(2))
Case line.ToLower.StartsWith("tr ")
curMat.Opacity = 1 - Convert.ToSingle(line.Substring(2))
Case line.ToLower.StartsWith("map_kd ")
If LoadMaterials Then
Dim mtlpath As String = line.Substring(7)
Dim combipath As String = Path.Combine(curMatLibPath, line.Substring(7))
Dim imgfile As String
If File.Exists(combipath) Then
imgfile = combipath
ElseIf File.Exists(line.Substring(7)) Then
imgfile = mtlpath
Else
imgfile = ""
End If
If imgfile <> "" Then
If LoadedImages.ContainsKey(imgfile) Then
curMat.Image = LoadedImages(imgfile)
Else
Dim fs As New FileStream(imgfile, FileMode.Open, FileAccess.Read)
curMat.Image = Image.FromStream(fs)
fs.Close()
Dim imgExists As Boolean = False
For Each kvp In LoadedImages
If Not imgExists AndAlso IsTheSameAs(kvp.Value, curMat.Image) Then
curMat.Image = kvp.Value
imgExists = True
End If
Next
If Not imgExists Then
LoadedImages.Add(imgfile, curMat.Image)
End If
End If
End If
End If
End Select
Loop
srMtl.Close()
End Sub
Public Shared Sub ToFile(fileName As String, obj As Object3D)
Dim fs As New FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)
Dim sw As New StreamWriter(fs, Text.Encoding.ASCII)
Dim imgDirName As String = Path.GetFileNameWithoutExtension(fileName)
Dim imgDirFull As String = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName))
For Each kvp As KeyValuePair(Of String, Material) In obj.Materials
Dim mat As Material = kvp.Value
Dim name As String = "_" & ObjFile.GetIndexOfMaterialInList(obj, mat)
sw.WriteLine($"newmtl {name}")
If mat.Color IsNot Nothing Then
sw.WriteLine($"kd {mat.Color.Value.R.ToString.Replace(",", ".")} {mat.Color.Value.G.ToString.Replace(",", ".")} {mat.Color.Value.B.ToString.Replace(",", ".")}")
End If
If mat.Opacity IsNot Nothing Then
sw.WriteLine($"d {mat.Opacity.Value.ToString.Replace(",", ".")}")
End If
If mat.Image IsNot Nothing Then
Dim imgFile As String = name & ".png"
If Not Directory.Exists(imgDirFull) Then Directory.CreateDirectory(imgDirFull)
mat.Image.Save(Path.Combine(imgDirFull, imgFile), Imaging.ImageFormat.Png)
sw.WriteLine($"map_kd {Path.Combine(imgDirName, imgFile)}")
End If
Next
sw.Flush()
fs.Close()
End Sub
End Class
End Namespace