revert to VB and update to new project file format

This commit is contained in:
schedpas
2020-09-25 09:04:15 +02:00
parent 04869b2814
commit 9feaf658be
313 changed files with 9895 additions and 17566 deletions

View File

@@ -1,273 +0,0 @@
using System.Collections.Generic;
using System.Drawing;
using global::System.Globalization;
using global::System.IO;
using global::System.Threading;
using global::Aspose.ThreeD;
using global::Aspose.ThreeD.Entities;
using global::Aspose.ThreeD.Shading;
using global::Aspose.ThreeD.Utilities;
using Microsoft.VisualBasic.CompilerServices;
namespace Pilz.S3DFileParser.Aspose3DModule
{
public class Aspose3DLoader
{
private static bool hasActivatedMemoryPatching = false;
private static void ActivateMemoryPatching()
{
if (!hasActivatedMemoryPatching)
{
LicenseHelper.AsposeModifyInMemory.ActivateMemoryPatching();
hasActivatedMemoryPatching = true;
}
}
public static Object3D FromFile(string fileName, bool LoadMaterials, UpAxis UpAxis)
{
ActivateMemoryPatching();
// Create new Model
var obj3d = new Object3D();
// Create new temporary CultureInfo
var curThread = Thread.CurrentThread;
var curCultInfo = curThread.CurrentCulture;
var newCultInfo = 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
var scene = new Scene(fileName);
// Reset Cultur-Info
curThread.CurrentCulture = curCultInfo;
// Triangulate the Model
PolygonModifier.Triangulate(scene);
// Create Dictionary for Materials
var dicMaterials = new Dictionary<Aspose.ThreeD.Shading.Material, Material>();
// Create List of all avaiable Map-States
var MapNames = new[] { 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 };
var ColorNames = new[] { "DiffuseColor", "AmbientColor", "SpecularColor", "EmissiveColor" };
foreach (Node node in scene.RootNode.ChildNodes)
{
// Add new Materials, if not added
foreach (Aspose.ThreeD.Shading.Material mat in node.Materials)
{
if (!dicMaterials.ContainsKey(mat))
{
// Create new Material
var newMat = new Material();
// Get TextureBase
TextureBase texBase = null;
byte curmnindex = 0;
while (texBase is null && curmnindex < MapNames.Length)
{
texBase = mat.GetTexture(MapNames[curmnindex]);
curmnindex = (byte)(curmnindex + 1);
}
if (texBase is object)
{
if (LoadMaterials)
{
// Get Texture Image
string imgFile = Conversions.ToString(texBase.GetPropertyValue("FileName"));
imgFile = imgFile.Replace("/", @"\");
// Load and set Image
if (!string.IsNullOrEmpty(imgFile))
{
var fs = new FileStream(imgFile, FileMode.Open, FileAccess.Read);
newMat.Image = Image.FromStream(fs);
fs.Close();
}
}
}
// Get Texture Color
Vector3? texcol = default;
byte curcnindex = 0;
while (texcol is null && curcnindex < ColorNames.Length)
{
texcol = (Vector3?)mat.GetPropertyValue(ColorNames[curcnindex]);
curcnindex = (byte)(curcnindex + 1);
}
if (texcol is object)
{
newMat.Color = Color.FromArgb((int)texcol?.x, (int)texcol?.y, (int)texcol?.z);
}
// Add Material to Object3D
obj3d.Materials.Add(mat.Name, newMat);
// Add Dictionary-Entry
dicMaterials.Add(mat, newMat);
}
}
// Get Aspose-Mesh
var curMesh = node.GetEntity<Aspose.ThreeD.Entities.Mesh>();
if (curMesh is object)
{
// Create new Mesh
var newMesh = new Mesh();
// Create Vertices
foreach (Vector4 vert in curMesh.ControlPoints)
{
// Create new Vertex
var newVert = new Vertex();
// Set Vertex Data
newVert.X = vert.x;
newVert.Y = vert.y;
newVert.Z = vert.z;
// Add new Vertex
newMesh.Vertices.Add(newVert);
}
// Create Normals
VertexElementNormal veNormals = (VertexElementNormal)curMesh.GetElement(VertexElementType.Normal);
if (veNormals is object)
{
foreach (Vector4 n in veNormals.Data)
{
// Create new Normal
var newNormal = new Normal();
// Set Normal Data
newNormal.X = (float)n.x;
newNormal.Y = (float)n.y;
newNormal.Z = (float)n.z;
// Add new Normal
newMesh.Normals.Add(newNormal);
}
}
// Create Normals
VertexElementUV veUVs = (VertexElementUV)curMesh.GetElement(VertexElementType.UV);
if (veUVs is object)
{
foreach (Vector4 uv in veUVs.Data)
{
// Create new UV
var newUV = new UV();
// Set UV Data
newUV.U = (float)uv.x;
newUV.V = (float)uv.y;
// Add new UV
newMesh.UVs.Add(newUV);
}
}
// Create Normals
VertexElementVertexColor veVertexColor = (VertexElementVertexColor)curMesh.GetElement(VertexElementType.VertexColor);
if (veVertexColor is object)
{
foreach (Vector4 n in veVertexColor.Data)
{
// Create new Normal
var newVC = new VertexColor();
// Set Normal Data
newVC.R = (float)n.x;
newVC.G = (float)n.y;
newVC.B = (float)n.z;
newVC.A = (float)n.w;
// Add new Normal
newMesh.VertexColors.Add(newVC);
}
}
// Get Material-Indicies
VertexElementMaterial veMaterials = (VertexElementMaterial)curMesh.GetElement(VertexElementType.Material);
// Definde Index for VertexElement.Indicies
int veIndex = 0;
// Build Polygones
for (int iPoly = 0, loopTo = curMesh.Polygons.Count - 1; iPoly <= loopTo; iPoly++)
{
// Get current Polygon
var poly = curMesh.Polygons[iPoly];
// Create new Face
var f = new Face();
// Set Texture, if avaiable
if (veMaterials is object)
{
f.Material = dicMaterials[node.Materials[veMaterials.Indices[iPoly]]];
}
else if (node.Material is object)
{
f.Material = dicMaterials[node.Material];
}
foreach (int index in poly)
{
// Create new Point
var p = new Point();
// Set Vertex
p.Vertex = newMesh.Vertices[index];
// Set Normal
if (veNormals is object)
{
p.Normal = newMesh.Normals[veNormals.Indices[veIndex]];
}
// Set UV
if (veUVs is object)
{
p.UV = newMesh.UVs[veUVs.Indices[veIndex]];
}
// Set Vertex Color
if (veVertexColor is object)
{
p.VertexColor = newMesh.VertexColors[veVertexColor.Indices[veIndex]];
}
// Add new Point
f.Points.Add(p);
// Increment VertexElementIndicies-Index
veIndex += 1;
}
// Add new Face
newMesh.Faces.Add(f);
}
// Add new Mesh
obj3d.Meshes.Add(newMesh);
}
}
// Return the new Object3D
return obj3d;
}
}
}

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

@@ -1,540 +0,0 @@
using System.Collections.Generic;
using System.Drawing;
using global::System.IO;
using System.Linq;
using global::Assimp;
using global::Assimp.Unmanaged;
namespace Pilz.S3DFileParser.AssimpModule
{
internal class ConversionContext
{
public Scene DaeMdl { get; set; }
public UpAxis UpAxis { get; set; }
public Mesh NewMesh { get; set; } = new Mesh();
public Object3D NewObj { get; set; } = new Object3D();
public Dictionary<Material, int> ChannelIndicies { get; set; } = new Dictionary<Material, int>();
public ConversionContext(Scene daeMdlP, UpAxis upAxis)
{
DaeMdl = daeMdlP;
UpAxis = upAxis;
NewObj.Meshes.Add(NewMesh);
}
}
internal class ParsingContext
{
public ConversionContext ConversionContext { get; private set; }
public Dictionary<Vector3D, Vertex> DicVertices { get; set; } = new Dictionary<Vector3D, Vertex>();
public Dictionary<Vector3D, Normal> DicNormals { get; set; } = new Dictionary<Vector3D, Normal>();
public Dictionary<Vector3D, UV> DicUVs { get; set; } = new Dictionary<Vector3D, UV>();
public Dictionary<Color4D, VertexColor> DicVertexColors { get; set; } = new Dictionary<Color4D, VertexColor>();
public ParsingContext(ConversionContext ctx)
{
ConversionContext = ctx;
}
}
public class AssimpLoader
{
public static event LoadingAssimpLibsEventHandler LoadingAssimpLibs;
public delegate void LoadingAssimpLibsEventHandler();
public static event LoadedAssimpLibsEventHandler LoadedAssimpLibs;
public delegate void LoadedAssimpLibsEventHandler();
public static string PathToAssimpLib32 { get; set; } = "Assimp32.dll";
public static string PathToAssimpLib64 { get; set; } = "Assimp64.dll";
internal static void LoadAssimpLibs()
{
if (!AssimpLibrary.Instance.IsLibraryLoaded)
{
LoadingAssimpLibs?.Invoke();
AssimpLibrary.Instance.LoadLibrary(PathToAssimpLib32, PathToAssimpLib64);
LoadedAssimpLibs?.Invoke();
}
}
private static void ComputeNewObj(ConversionContext cc)
{
var identity = Matrix4x4.Identity;
ComputeNode(cc.DaeMdl.RootNode, identity, new ParsingContext(cc));
}
private static void ComputeNode(Node node, Matrix4x4 trafo, ParsingContext pc)
{
var newObj = pc.ConversionContext.NewObj;
var newMesh = pc.ConversionContext.NewMesh;
var daeMdl = pc.ConversionContext.DaeMdl;
var channelIndicies = pc.ConversionContext.ChannelIndicies;
var UpAxis = pc.ConversionContext.UpAxis;
var dicVertices = pc.DicVertices;
var dicNormals = pc.DicNormals;
var dicUVs = pc.DicUVs;
var dicVertexColors = pc.DicVertexColors;
trafo = trafo * node.Transform;
if (node.HasMeshes)
{
foreach (var meshIndex in node.MeshIndices)
{
var m = daeMdl.Meshes[meshIndex];
Material curMat;
if (m.MaterialIndex > -1 && newObj.Materials.Count > m.MaterialIndex)
{
curMat = newObj.Materials.ElementAt(m.MaterialIndex).Value;
}
else
{
curMat = null;
}
foreach (Vector3D untransformedN in m.Normals)
{
var n = trafo * untransformedN;
if (!dicNormals.ContainsKey(n))
{
var newNormal = new Normal();
switch (UpAxis)
{
case UpAxis.Y:
{
newNormal.X = n.X;
newNormal.Y = n.Y;
newNormal.Z = n.Z;
break;
}
case UpAxis.Z:
{
newNormal.X = n.Y;
newNormal.Y = n.Z;
newNormal.Z = n.X;
break;
}
}
newMesh.Normals.Add(newNormal);
dicNormals.Add(n, newNormal);
}
}
foreach (Vector3D untranformedV in m.Vertices)
{
var v = trafo * untranformedV;
if (!dicVertices.ContainsKey(v))
{
var newVert = new Vertex();
switch (UpAxis)
{
case UpAxis.Y:
{
newVert.X = v.X;
newVert.Y = v.Y;
newVert.Z = v.Z;
break;
}
case UpAxis.Z:
{
newVert.X = v.Y;
newVert.Y = v.Z;
newVert.Z = v.X;
break;
}
}
newMesh.Vertices.Add(newVert);
dicVertices.Add(v, newVert);
}
}
foreach (List<Vector3D> uvList in m.TextureCoordinateChannels)
{
foreach (Vector3D uv in uvList)
{
if (!dicUVs.ContainsKey(uv))
{
var newUV = new UV();
newUV.U = uv.X;
newUV.V = uv.Y;
newMesh.UVs.Add(newUV);
dicUVs.Add(uv, newUV);
}
}
}
foreach (List<Color4D> vcList in m.VertexColorChannels)
{
foreach (Color4D vc in vcList)
{
if (!dicVertexColors.ContainsKey(vc))
{
var newVC = 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);
}
}
}
foreach (Assimp.Face f in m.Faces)
{
if (f.HasIndices)
{
var newFace = new Face() { Material = curMat };
foreach (int index in f.Indices)
{
if (index > -1)
{
var newPoint = new Point();
if (m.HasVertices)
{
var v = trafo * m.Vertices[index];
newPoint.Vertex = dicVertices[v];
}
if (m.HasNormals)
{
var n = trafo * m.Normals[index];
newPoint.Normal = dicNormals[n];
}
if (curMat is object && channelIndicies.ContainsKey(curMat))
{
int tkey = channelIndicies[curMat];
if (m.HasTextureCoords(tkey))
{
newPoint.UV = dicUVs[m.TextureCoordinateChannels[tkey][index]];
}
if (m.HasVertexColors(tkey))
{
newPoint.VertexColor = dicVertexColors[m.VertexColorChannels[tkey][index]];
}
}
newFace.Points.Add(newPoint);
}
}
if (newFace.Points.Count == 3)
{
newMesh.Faces.Add(newFace);
}
}
}
}
}
foreach (var n in node.Children)
ComputeNode(n, trafo, pc);
}
public static Object3D FromFile(string fileName, bool LoadMaterials, UpAxis UpAxis)
{
var LoadedImages = new Dictionary<string, Image>();
var ac = new AssimpContext();
var cc = new ConversionContext(ac.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessSteps.Triangulate), UpAxis);
var newObj = cc.NewObj;
var daeMdl = cc.DaeMdl;
var channelIndicies = cc.ChannelIndicies;
foreach (EmbeddedTexture et in daeMdl.Textures)
{
if (et.HasCompressedData)
{
var newMat = new Material();
var ms = new MemoryStream(et.CompressedData);
newMat.Image = Image.FromStream(ms);
ms.Close();
newObj.Materials.Add("tex_" + daeMdl.Textures.IndexOf(et), newMat);
}
}
foreach (Assimp.Material mat in daeMdl.Materials)
{
var newMat = new Material();
TextureSlot? texSlot = default;
Color4D? col4d = default;
newMat.Opacity = mat.Opacity;
switch (true)
{
case object _ when mat.HasTextureNormal:
{
texSlot = mat.TextureNormal;
break;
}
case object _ when mat.HasTextureDiffuse:
{
texSlot = mat.TextureDiffuse;
break;
}
case object _ when mat.HasTextureAmbient:
{
texSlot = mat.TextureAmbient;
break;
}
case object _ when mat.HasTextureSpecular:
{
texSlot = mat.TextureSpecular;
break;
}
}
switch (true)
{
case object _ when mat.HasColorDiffuse:
{
col4d = mat.ColorDiffuse;
break;
}
case object _ when mat.HasColorAmbient:
{
col4d = mat.ColorAmbient;
break;
}
case object _ when mat.HasColorSpecular:
{
col4d = mat.ColorSpecular;
break;
}
}
if (texSlot is object)
{
string filePath = texSlot.Value.FilePath;
if (LoadMaterials)
{
if (!string.IsNullOrEmpty(filePath))
{
string combiPath = Path.Combine(Path.GetDirectoryName(fileName), filePath);
if (File.Exists(combiPath))
{
newMat.Image = LoadImage(combiPath, LoadedImages);
}
else if (File.Exists(filePath))
{
newMat.Image = LoadImage(filePath, LoadedImages);
}
}
else if (texSlot.Value.TextureIndex > -1 && daeMdl.Textures.Count > texSlot.Value.TextureIndex)
{
var et = daeMdl.Textures[texSlot.Value.TextureIndex];
if (et.HasCompressedData)
{
var ms = new MemoryStream(et.CompressedData);
newMat.Image = Image.FromStream(ms);
ms.Close();
}
}
}
channelIndicies.Add(newMat, texSlot.Value.UVIndex);
}
if (col4d is object)
{
newMat.Color = Color.FromArgb((int)(col4d.Value.R * 255f), (int)(col4d.Value.G * 255f), (int)(col4d.Value.B * 255f));
}
newObj.Materials.Add(mat.Name, newMat);
}
ComputeNewObj(cc);
return newObj;
}
public static void ToFile(string fileName, Object3D obj)
{
var mdl = new Scene();
var dicMatIndex = new Dictionary<Material, int>();
string texDir = "";
if (obj.Materials.Count > 0)
{
texDir = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName));
if (!Directory.Exists(texDir))
{
Directory.CreateDirectory(texDir);
}
}
foreach (KeyValuePair<string, Material> kvp in obj.Materials)
{
var mat = new Assimp.Material();
mat.Name = !string.IsNullOrEmpty(kvp.Key) ? kvp.Key : "_" + mdl.Materials.Count;
mat.Opacity = mat.Opacity;
var texslot = new TextureSlot();
texslot.TextureIndex = mdl.Textures.Count;
texslot.TextureType = TextureType.Diffuse;
texslot.UVIndex = 0;
var ms = new MemoryStream();
kvp.Value.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
// Dim tex As New EmbeddedTexture("png", ms.GetBuffer)
ms.Close();
if (kvp.Value.Image is object)
{
texslot.FilePath = Path.Combine(texDir, mat.Name + ".png");
File.WriteAllBytes(texslot.FilePath, ms.GetBuffer());
}
// mdl.Textures.Add(tex)
mat.AddMaterialTexture(ref texslot);
mdl.Materials.Add(mat);
if (kvp.Value.Color is object)
{
{
var withBlock = kvp.Value.Color.Value;
mat.ColorDiffuse = new Color4D((float)(withBlock.R / 255d), (float)(withBlock.G / 255d), (float)(withBlock.B / 255d), 1f);
}
}
dicMatIndex.Add(kvp.Value, mdl.Materials.Count - 1);
}
var dicTexMesh = new Dictionary<Material, Assimp.Mesh>();
var dicMeshDicVertIndex = new Dictionary<Assimp.Mesh, Dictionary<Vertex, int>>();
var dicCounter = new Dictionary<Assimp.Mesh, int>();
foreach (Mesh mesh in obj.Meshes)
{
foreach (Face f in mesh.Faces)
{
Assimp.Mesh m;
if (dicTexMesh.ContainsKey(f.Material))
{
m = dicTexMesh[f.Material];
}
else
{
m = new Assimp.Mesh("Mesh_" + (mdl.MeshCount + 1));
m.PrimitiveType = PrimitiveType.Triangle;
if (dicMatIndex.ContainsKey(f.Material))
{
m.MaterialIndex = dicMatIndex[f.Material];
}
mdl.Meshes.Add(m);
dicTexMesh.Add(f.Material, m);
dicMeshDicVertIndex.Add(m, new Dictionary<Vertex, int>());
dicCounter.Add(m, 0);
}
var newFace = new Assimp.Face();
foreach (Point p in f.Points)
{
newFace.Indices.Add(dicCounter[m]);
if (p.Vertex is object)
{
var vert = new Vector3D();
vert.X = (float)p.Vertex.X;
vert.Y = (float)p.Vertex.Y;
vert.Z = (float)p.Vertex.Z;
m.Vertices.Add(vert);
}
else
{
m.Vertices.Add(new Vector3D(0f, 0f, 0f));
}
if (p.Normal is object)
{
var norm = 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(0f, 0f, 0f));
}
// 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;
}
m.Faces.Add(newFace);
}
}
// Add Root Node
mdl.RootNode = new Node(Path.GetFileName(fileName));
// Add Mesh Indicies
for (int i = 0, loopTo = mdl.MeshCount - 1; i <= loopTo; i++)
mdl.RootNode.MeshIndices.Add(i);
var ac = new AssimpContext();
string formatID = "";
string myExt = Path.GetExtension(fileName).ToLower().Substring(1);
foreach (ExportFormatDescription efd in ac.GetSupportedExportFormats())
{
if ((myExt ?? "") == (efd.FileExtension ?? ""))
{
formatID = efd.FormatId;
break;
}
}
ac.ExportFile(mdl, fileName, formatID);
}
private static Image LoadImage(string fileName, Dictionary<string, Image> loadedImages)
{
if (File.Exists(fileName))
{
if (loadedImages.ContainsKey(fileName))
{
return loadedImages[fileName];
}
else
{
var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
var img = Image.FromStream(fs);
fs.Close();
foreach (var kvp in loadedImages)
{
if (((Bitmap)img).IsTheSameAs((Bitmap)kvp.Value))
{
return kvp.Value;
}
}
loadedImages.Add(fileName, img);
return img;
}
}
return null;
}
}
}

View 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

View File

@@ -1,476 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using global::System.Globalization;
using global::System.IO;
using System.Linq;
using global::System.Threading;
using Microsoft.VisualBasic.CompilerServices;
using global::Pilz.S3DFileParser.Exceptions;
namespace Pilz.S3DFileParser.ObjModule
{
public class ObjFile
{
public static Object3D FromFile(string FileName, bool LoadMaterials, UpAxis UpAxis)
{
var curThread = Thread.CurrentThread;
var curCultInfo = curThread.CurrentCulture;
var newCultInfo = 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;
var newObj = new Object3D();
var newMesh = new Mesh();
string curObjPath = Path.GetDirectoryName(FileName);
var mtllibs = new Dictionary<string, MaterialLib>();
MaterialLib curMaterialLib = null;
Material curMaterial = null;
var srObj = new StreamReader(FileName, System.Text.Encoding.ASCII);
string line = "";
while (!srObj.EndOfStream)
{
line = srObj.ReadLine().Trim();
if (!string.IsNullOrEmpty(line))
{
switch (true)
{
case object _ when line.StartsWith("mtllib "):
{
string name = line.Substring(7);
if (!mtllibs.ContainsKey(name))
{
string mtlfile = Path.Combine(curObjPath, name);
if (!File.Exists(mtlfile))
throw new MaterialException("Material Library not found!");
var newmtl = new MaterialLib();
newmtl.FromFile(mtlfile, LoadMaterials);
mtllibs.Add(name, newmtl);
curMaterialLib = newmtl;
foreach (KeyValuePair<string, Material> kvp in curMaterialLib.Materials)
{
if (!newObj.Materials.ContainsKey(kvp.Key))
newObj.Materials.Add(kvp.Key, kvp.Value);
}
}
else
{
curMaterialLib = mtllibs[name];
}
break;
}
case object _ when line.StartsWith("usemtl "):
{
curMaterial = curMaterialLib.Materials[line.Substring(7)];
break;
}
case object _ when line.StartsWith("v "):
{
if (line.Contains("nan"))
line = line.Replace("nan", "0");
var splitXYZ = line.Substring(2).Split(' ');
double tX = Convert.ToDouble(splitXYZ[0]);
double tY = Convert.ToDouble(splitXYZ[1]);
double tZ = Convert.ToDouble(splitXYZ[2]);
var v = new Vertex();
switch (UpAxis)
{
case UpAxis.Y:
{
v.X = tX;
v.Y = tY;
v.Z = tZ;
break;
}
case UpAxis.Z:
{
v.X = tY;
v.Y = tZ;
v.Z = tX;
break;
}
}
newMesh.Vertices.Add(v);
break;
}
case object _ when line.StartsWith("vt "):
{
var uvstr = line.Substring(3).Split(' ');
var uv = new UV()
{
U = Convert.ToSingle(uvstr[0]),
V = Convert.ToSingle(uvstr[1])
};
newMesh.UVs.Add(uv);
break;
}
case object _ when line.StartsWith("vn "):
{
var splitXYZ = line.Substring(3).Split(' ');
float tX = Convert.ToSingle(splitXYZ[0]);
float tY = Convert.ToSingle(splitXYZ[1]);
float tZ = Convert.ToSingle(splitXYZ[2]);
var n = new Normal();
switch (UpAxis)
{
case UpAxis.Y:
{
n.X = tX;
n.Y = tY;
n.Z = tZ;
break;
}
case UpAxis.Z:
{
n.X = tZ;
n.Y = tY;
n.Z = tX;
break;
}
}
newMesh.Normals.Add(n);
break;
}
case object _ when line.StartsWith("vc "):
{
var splitRGB = line.Substring(3).Split(' ');
float tX = Convert.ToSingle(splitRGB[0]);
float tY = Convert.ToSingle(splitRGB[1]);
float tZ = Convert.ToSingle(splitRGB[2]);
var vc = new VertexColor();
switch (UpAxis)
{
case UpAxis.Y:
{
vc.R = tX;
vc.G = tY;
vc.B = tZ;
break;
}
case UpAxis.Z:
{
vc.R = tY;
vc.G = tZ;
vc.B = tX;
break;
}
}
newMesh.VertexColors.Add(vc);
break;
}
case object _ when line.StartsWith("f "):
{
var tri = new Face() { Material = curMaterial };
foreach (string xyz1 in line.Substring(2).Split(' '))
{
var xyz = xyz1.Trim();
if (string.IsNullOrEmpty(xyz))
continue;
string[] splitsub = null;
var p = new Point();
switch (true)
{
case object _ when xyz.Contains("/"):
{
splitsub = xyz.Split('/');
break;
}
case object _ when xyz.Contains(@"\"):
{
splitsub = xyz.Split('\\');
break;
}
default:
{
splitsub = new string[] { 0.ToString(), 0.ToString(), 0.ToString() };
break;
}
}
string v1 = splitsub[0];
string v2 = splitsub[1];
string v3 = splitsub[2];
if (!string.IsNullOrEmpty(v1))
{
p.Vertex = newMesh.Vertices[Convert.ToInt32(v1) - 1];
}
if (!string.IsNullOrEmpty(v2))
{
p.UV = newMesh.UVs[Convert.ToInt32(v2) - 1];
}
else
{
var newUV = new UV() { U = 0f, V = 0f };
p.UV = newUV;
newMesh.UVs.Add(newUV);
}
if (!string.IsNullOrEmpty(v3))
{
p.Normal = newMesh.Normals[Convert.ToInt32(v3) - 1];
}
if (splitsub.Count() > 3)
{
string v4 = splitsub[3];
if (!string.IsNullOrEmpty(v4))
p.VertexColor = newMesh.VertexColors[Convert.ToInt32(v4) - 1];
}
tri.Points.Add(p);
}
newMesh.Faces.Add(tri);
break;
}
}
}
}
newObj.Meshes.Add(newMesh);
curThread.CurrentCulture = curCultInfo;
srObj.Close();
return newObj;
}
public static void ToFile(string FileName, Object3D obj)
{
var fs = new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite);
var sw = new StreamWriter(fs, System.Text.Encoding.ASCII);
if (obj.Materials.Count > 0)
{
string mtlName = Path.GetFileNameWithoutExtension(FileName) + ".mtl";
string mtlFile = Path.Combine(Path.GetDirectoryName(FileName), mtlName);
sw.WriteLine($"mtllib {mtlName}");
MaterialLib.ToFile(mtlFile, obj);
}
int curVertCount = 1;
int curUVCount = 1;
int curNormCount = 1;
int curVertColCount = 1;
foreach (Mesh m in obj.Meshes)
{
foreach (Vertex vert in m.Vertices)
sw.WriteLine($"v {vert.X.ToString().Replace(",", ".")} {vert.Y.ToString().Replace(",", ".")} {vert.Z.ToString().Replace(",", ".")}");
foreach (UV uv in m.UVs)
sw.WriteLine($"vt {uv.U.ToString().Replace(",", ".")} {uv.V.ToString().Replace(",", ".")}");
foreach (Normal norm in m.Normals)
sw.WriteLine($"vn {norm.X.ToString().Replace(",", ".")} {norm.Y.ToString().Replace(",", ".")} {norm.Z.ToString().Replace(",", ".")}");
foreach (VertexColor vertcol in m.VertexColors)
sw.WriteLine($"vc {vertcol.R.ToString().Replace(",", ".")} {vertcol.G.ToString().Replace(",", ".")} {vertcol.B.ToString().Replace(",", ".")}");
Material curMtl = null;
foreach (Face f in m.Faces)
{
if (!ReferenceEquals(curMtl, f.Material))
{
curMtl = f.Material;
sw.WriteLine($"usemtl _{GetIndexOfMaterialInList(obj, curMtl)}");
}
sw.Write("f");
foreach (Point p in f.Points)
{
sw.Write(" ");
sw.Write(curVertCount + m.Vertices.IndexOf(p.Vertex));
sw.Write("/");
if (p.UV is object)
sw.Write(curUVCount + m.UVs.IndexOf(p.UV));
sw.Write("/");
if (p.Normal is object)
sw.Write(curNormCount + m.Normals.IndexOf(p.Normal));
if (m.VertexColors.Count > 0)
{
sw.Write("/");
if (p.VertexColor is object)
sw.Write(curVertColCount + m.VertexColors.IndexOf(p.VertexColor));
}
}
sw.WriteLine();
}
curVertCount += m.Vertices.Count;
curUVCount += m.UVs.Count;
curNormCount += m.Normals.Count;
curVertColCount += m.VertexColors.Count;
}
sw.Flush();
fs.Close();
}
public static int GetIndexOfMaterialInList(Object3D obj, Material matToFind)
{
for (int Index = 0, loopTo = obj.Materials.Count - 1; Index <= loopTo; Index++)
{
if (obj.Materials.ElementAt(Index).Value.Equals(matToFind))
{
return Index;
}
}
return -1;
}
}
public class MaterialLib
{
public Dictionary<string, Material> Materials { get; private set; } = new Dictionary<string, Material>();
private readonly Dictionary<string, Image> LoadedImages = new Dictionary<string, Image>();
public void FromFile(string fileName, bool LoadMaterials)
{
LoadedImages.Clear();
string curMatLibPath = Path.GetDirectoryName(fileName);
Material curMat = null;
string curName = "";
var srMtl = new StreamReader(fileName, System.Text.Encoding.ASCII);
string line = "";
while (!srMtl.EndOfStream)
{
line = srMtl.ReadLine();
switch (true)
{
case object _ when line.StartsWith("newmtl "):
{
curMat = new Material();
curName = line.Substring(7);
Materials.Add(curName, curMat);
break;
}
case object _ when line.ToLower().StartsWith("kd "):
{
var splitColor = line.Substring(3).Split(' ');
var col = Color.FromArgb((int)Convert.ToSingle(Math.Round(255d * Conversions.ToDouble(splitColor[0]))), (int)Convert.ToSingle(Math.Round(255d * Conversions.ToDouble(splitColor[1]))), (int)Convert.ToSingle(Math.Round(255d * Conversions.ToDouble(splitColor[2]))));
curMat.Color = col;
break;
}
case object _ when line.ToLower().StartsWith("d "):
{
curMat.Opacity = Convert.ToSingle(line.Substring(2));
break;
}
case object _ when line.ToLower().StartsWith("tr "):
{
curMat.Opacity = 1f - Convert.ToSingle(line.Substring(2));
break;
}
case object _ when line.ToLower().StartsWith("map_kd "):
{
if (LoadMaterials)
{
string mtlpath = line.Substring(7);
string combipath = Path.Combine(curMatLibPath, line.Substring(7));
string imgfile;
if (File.Exists(combipath))
{
imgfile = combipath;
}
else if (File.Exists(line.Substring(7)))
{
imgfile = mtlpath;
}
else
{
imgfile = "";
}
if (!string.IsNullOrEmpty(imgfile))
{
if (LoadedImages.ContainsKey(imgfile))
{
curMat.Image = LoadedImages[imgfile];
}
else
{
var fs = new FileStream(imgfile, FileMode.Open, FileAccess.Read);
curMat.Image = Image.FromStream(fs);
fs.Close();
bool imgExists = false;
foreach (var kvp in LoadedImages)
{
if (!imgExists && ((Bitmap)kvp.Value).IsTheSameAs((Bitmap)curMat.Image))
{
curMat.Image = kvp.Value;
imgExists = true;
}
}
if (!imgExists)
{
LoadedImages.Add(imgfile, curMat.Image);
}
}
}
}
break;
}
}
}
srMtl.Close();
}
public static void ToFile(string fileName, Object3D obj)
{
var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
var sw = new StreamWriter(fs, System.Text.Encoding.ASCII);
string imgDirName = Path.GetFileNameWithoutExtension(fileName);
string imgDirFull = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName));
foreach (KeyValuePair<string, Material> kvp in obj.Materials)
{
var mat = kvp.Value;
string name = "_" + ObjFile.GetIndexOfMaterialInList(obj, mat);
sw.WriteLine($"newmtl {name}");
if (mat.Color is object)
{
sw.WriteLine($"kd {(mat.Color.Value.R / 255d).ToString().Replace(",", ".")} {(mat.Color.Value.G / 255d).ToString().Replace(",", ".")} {(mat.Color.Value.B / 255d).ToString().Replace(",", ".")}");
}
if (mat.Opacity is object)
{
sw.WriteLine($"d {mat.Opacity.Value.ToString().Replace(",", ".")}");
}
if (mat.Image is object)
{
string imgFile = name + ".png";
if (!Directory.Exists(imgDirFull))
Directory.CreateDirectory(imgDirFull);
mat.Image.Save(Path.Combine(imgDirFull, imgFile), System.Drawing.Imaging.ImageFormat.Png);
sw.WriteLine($"map_kd {Path.Combine(imgDirName, imgFile)}");
}
}
sw.Flush();
fs.Close();
}
}
}

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 / 255).ToString.Replace(",", ".")} {(mat.Color.Value.G / 255).ToString.Replace(",", ".")} {(mat.Color.Value.B / 255).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