From fd1e8baac5727cd5e5bd911b1c388a624d9c3e27 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Wed, 15 Sep 2021 13:04:03 +0300 Subject: [PATCH 01/10] Export point clouds --- glTF-BinExporter/Constants.cs | 24 ++ glTF-BinExporter/RhinoDocGltfConverter.cs | 44 ++- glTF-BinExporter/RhinoMeshGltfConverter.cs | 25 +- .../RhinoPointCloudGltfConverter.cs | 260 ++++++++++++++++++ 4 files changed, 320 insertions(+), 33 deletions(-) create mode 100644 glTF-BinExporter/RhinoPointCloudGltfConverter.cs diff --git a/glTF-BinExporter/Constants.cs b/glTF-BinExporter/Constants.cs index d8729b4..381b247 100644 --- a/glTF-BinExporter/Constants.cs +++ b/glTF-BinExporter/Constants.cs @@ -28,6 +28,30 @@ public static class Constants public const string NormalAttributeTag = "NORMAL"; public const string TexCoord0AttributeTag = "TEXCOORD_0"; public const string VertexColorAttributeTag = "COLOR_0"; + + public static readonly Transform ZtoYUp = new Transform() + { + M00 = 1, + M01 = 0, + M02 = 0, + M03 = 0, + + M10 = 0, + M11 = 0, + M12 = 1, + M13 = 0, + + M20 = 0, + M21 = -1, + M22 = 0, + M23 = 0, + + M30 = 0, + M31 = 0, + M32 = 0, + M33 = 1, + }; + } public class DracoGeometryInfo diff --git a/glTF-BinExporter/RhinoDocGltfConverter.cs b/glTF-BinExporter/RhinoDocGltfConverter.cs index c7facbc..b1c0a78 100644 --- a/glTF-BinExporter/RhinoDocGltfConverter.cs +++ b/glTF-BinExporter/RhinoDocGltfConverter.cs @@ -97,7 +97,28 @@ public Gltf ConvertToGltf() dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_ior.Tag); dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_specular.Tag); - var sanitized = SanitizeRhinoObjects(objects); + IEnumerable pointClouds = objects.Where(x => x.ObjectType == ObjectType.PointSet); + + foreach(Rhino.DocObjects.RhinoObject rhinoObject in pointClouds) + { + RhinoPointCloudGltfConverter converter = new RhinoPointCloudGltfConverter(rhinoObject, options, binary, dummy, binaryBuffer); + int meshIndex = converter.AddPointCloud(); + + if(meshIndex != -1) + { + glTFLoader.Schema.Node node = new Node() + { + Mesh = meshIndex, + Name = GetObjectName(rhinoObject), + }; + + int nodeIndex = dummy.Nodes.AddAndReturnIndex(node); + + AddNode(nodeIndex, rhinoObject); + } + } + + List sanitized = SanitizeRhinoObjects(objects); foreach(ObjectExportData exportData in sanitized) { @@ -114,14 +135,7 @@ public Gltf ConvertToGltf() int nodeIndex = dummy.Nodes.AddAndReturnIndex(node); - if(options.ExportLayers) - { - AddToLayer(doc.Layers[exportData.Object.Attributes.LayerIndex], nodeIndex); - } - else - { - dummy.Scenes[dummy.Scene].Nodes.Add(nodeIndex); - } + AddNode(nodeIndex, exportData.Object); } if (binary && binaryBuffer.Count > 0) @@ -137,6 +151,18 @@ public Gltf ConvertToGltf() return dummy.ToSchemaGltf(); } + private void AddNode(int nodeIndex, Rhino.DocObjects.RhinoObject rhinoObject) + { + if (options.ExportLayers) + { + AddToLayer(doc.Layers[rhinoObject.Attributes.LayerIndex], nodeIndex); + } + else + { + dummy.Scenes[dummy.Scene].Nodes.Add(nodeIndex); + } + } + private void AddToLayer(Layer layer, int child) { if(layers.TryGetValue(layer.Index, out Node node)) diff --git a/glTF-BinExporter/RhinoMeshGltfConverter.cs b/glTF-BinExporter/RhinoMeshGltfConverter.cs index 96d5454..bffc7e8 100644 --- a/glTF-BinExporter/RhinoMeshGltfConverter.cs +++ b/glTF-BinExporter/RhinoMeshGltfConverter.cs @@ -32,29 +32,6 @@ public RhinoMeshGltfConverter(ObjectExportData exportData, int? materialIndex, g private DracoGeometryInfo currentGeometryInfo = null; - private readonly Transform ZtoYUp = new Transform() - { - M00 = 1, - M01 = 0, - M02 = 0, - M03 = 0, - - M10 = 0, - M11 = 0, - M12 = 1, - M13 = 0, - - M20 = 0, - M21 = -1, - M22 = 0, - M23 = 0, - - M30 = 0, - M31 = 0, - M32 = 0, - M33 = 1, - }; - public int AddMesh() { List primitives = GetPrimitives(); @@ -71,7 +48,7 @@ private void PreprocessMesh(Mesh rhinoMesh) { if (options.MapRhinoZToGltfY) { - rhinoMesh.Transform(ZtoYUp); + rhinoMesh.Transform(Constants.ZtoYUp); } rhinoMesh.TextureCoordinates.ReverseTextureCoordinates(1); diff --git a/glTF-BinExporter/RhinoPointCloudGltfConverter.cs b/glTF-BinExporter/RhinoPointCloudGltfConverter.cs new file mode 100644 index 0000000..eab73ae --- /dev/null +++ b/glTF-BinExporter/RhinoPointCloudGltfConverter.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace glTF_BinExporter +{ + class RhinoPointCloudGltfConverter + { + public RhinoPointCloudGltfConverter(Rhino.DocObjects.RhinoObject rhinoObject, glTFExportOptions options, bool binary, gltfSchemaDummy dummy, List binaryBuffer) + { + this.rhinoObject = rhinoObject; + this.options = options; + this.binary = binary; + this.dummy = dummy; + this.binaryBuffer = binaryBuffer; + } + + private Rhino.DocObjects.RhinoObject rhinoObject = null; + private glTFExportOptions options = null; + private bool binary = false; + private gltfSchemaDummy dummy = null; + private List binaryBuffer = null; + + public int AddPointCloud() + { + Rhino.Geometry.PointCloud pointCloud = rhinoObject.Geometry.Duplicate() as Rhino.Geometry.PointCloud; + + if(pointCloud == null) + { + return -1; + } + + if(options.MapRhinoZToGltfY) + { + pointCloud.Transform(Constants.ZtoYUp); + } + + Rhino.Geometry.Point3d[] points = pointCloud.GetPoints(); + + int vertexAccessor = GetVertexAccessor(points); + + glTFLoader.Schema.MeshPrimitive primitive = new glTFLoader.Schema.MeshPrimitive() + { + Mode = glTFLoader.Schema.MeshPrimitive.ModeEnum.POINTS, + Attributes = new Dictionary(), + }; + + primitive.Attributes.Add(Constants.PositionAttributeTag, vertexAccessor); + + if(pointCloud.ContainsColors) + { + System.Drawing.Color[] colors = pointCloud.GetColors(); + + int colorsAccessorIdx = GetVertexColorAccessor(colors); + + primitive.Attributes.Add(Constants.VertexColorAttributeTag, colorsAccessorIdx); + } + + glTFLoader.Schema.Mesh mesh = new glTFLoader.Schema.Mesh() + { + Primitives = new glTFLoader.Schema.MeshPrimitive[] { primitive }, + }; + + return dummy.Meshes.AddAndReturnIndex(mesh); + } + + private int GetVertexAccessor(Rhino.Geometry.Point3d[] points) + { + int bufferViewIndex = GetBufferView(points, out Rhino.Geometry.Point3d min, out Rhino.Geometry.Point3d max, out int count); + + glTFLoader.Schema.Accessor accessor = new glTFLoader.Schema.Accessor() + { + BufferView = bufferViewIndex, + ByteOffset = 0, + ComponentType = glTFLoader.Schema.Accessor.ComponentTypeEnum.FLOAT, + Count = count, + Min = min.ToFloatArray(), + Max = max.ToFloatArray(), + Type = glTFLoader.Schema.Accessor.TypeEnum.VEC3, + }; + + return dummy.Accessors.AddAndReturnIndex(accessor); + } + + private int GetBufferView(Rhino.Geometry.Point3d[] points, out Rhino.Geometry.Point3d min, out Rhino.Geometry.Point3d max, out int count) + { + int buffer = 0; + int byteLength = 0; + int byteOffset = 0; + + if (binary) + { + byte[] bytes = GetVertexBytes(points, out min, out max); + buffer = 0; + byteLength = bytes.Length; + byteOffset = binaryBuffer.Count; + binaryBuffer.AddRange(bytes); + } + else + { + buffer = GetVertexBuffer(points, out min, out max, out byteLength); + } + + glTFLoader.Schema.BufferView vertexBufferView = new glTFLoader.Schema.BufferView() + { + Buffer = buffer, + ByteOffset = byteOffset, + ByteLength = byteLength, + Target = glTFLoader.Schema.BufferView.TargetEnum.ARRAY_BUFFER, + }; + + count = points.Length; + + return dummy.BufferViews.AddAndReturnIndex(vertexBufferView); + } + + private int GetVertexBuffer(Rhino.Geometry.Point3d[] points, out Rhino.Geometry.Point3d min, out Rhino.Geometry.Point3d max, out int length) + { + byte[] bytes = GetVertexBytes(points, out min, out max); + + length = bytes.Length; + + glTFLoader.Schema.Buffer buffer = new glTFLoader.Schema.Buffer() + { + Uri = Constants.TextBufferHeader + Convert.ToBase64String(bytes), + ByteLength = length, + }; + + return dummy.Buffers.AddAndReturnIndex(buffer); + } + + private byte[] GetVertexBytes(Rhino.Geometry.Point3d[] points, out Rhino.Geometry.Point3d min, out Rhino.Geometry.Point3d max) + { + min = new Rhino.Geometry.Point3d(Double.PositiveInfinity, Double.PositiveInfinity, Double.PositiveInfinity); + max = new Rhino.Geometry.Point3d(Double.NegativeInfinity, Double.NegativeInfinity, Double.NegativeInfinity); + + List floats = new List(points.Length * 3); + + foreach (Rhino.Geometry.Point3d vertex in points) + { + floats.AddRange(new float[] { (float)vertex.X, (float)vertex.Y, (float)vertex.Z }); + + min.X = Math.Min(min.X, vertex.X); + max.X = Math.Max(max.X, vertex.X); + + min.Y = Math.Min(min.Y, vertex.Y); + max.Y = Math.Max(max.Y, vertex.Y); + + min.Z = Math.Min(min.Z, vertex.Z); + max.Z = Math.Max(max.Z, vertex.Z); + } + + IEnumerable bytesEnumerable = floats.SelectMany(value => BitConverter.GetBytes(value)); + + return bytesEnumerable.ToArray(); + } + + private int GetVertexColorAccessor(System.Drawing.Color[] vertexColors) + { + int vertexColorsBufferViewIdx = GetVertexColorBufferView(vertexColors, out Rhino.Display.Color4f min, out Rhino.Display.Color4f max, out int countVertexColors); + + var type = options.UseDracoCompression ? glTFLoader.Schema.Accessor.ComponentTypeEnum.UNSIGNED_BYTE : glTFLoader.Schema.Accessor.ComponentTypeEnum.FLOAT; + + glTFLoader.Schema.Accessor vertexColorAccessor = new glTFLoader.Schema.Accessor() + { + BufferView = vertexColorsBufferViewIdx, + ByteOffset = 0, + Count = countVertexColors, + ComponentType = type, + Min = min.ToFloatArray(), + Max = max.ToFloatArray(), + Type = glTFLoader.Schema.Accessor.TypeEnum.VEC4, + Normalized = options.UseDracoCompression, + }; + + return dummy.Accessors.AddAndReturnIndex(vertexColorAccessor); + } + + int GetVertexColorBufferView(System.Drawing.Color[] colors, out Rhino.Display.Color4f min, out Rhino.Display.Color4f max, out int countVertexColors) + { + int buffer = 0; + int byteLength = 0; + int byteOffset = 0; + + if (binary) + { + byte[] bytes = GetVertexColorBytes(colors, out min, out max); + byteLength = bytes.Length; + byteOffset = binaryBuffer.Count; + binaryBuffer.AddRange(bytes); + } + else + { + buffer = GetVertexColorBuffer(colors, out min, out max, out byteLength); + } + + glTFLoader.Schema.BufferView vertexColorsBufferView = new glTFLoader.Schema.BufferView() + { + Buffer = buffer, + ByteLength = byteLength, + ByteOffset = byteOffset, + Target = glTFLoader.Schema.BufferView.TargetEnum.ARRAY_BUFFER, + }; + + countVertexColors = colors.Length; + + return dummy.BufferViews.AddAndReturnIndex(vertexColorsBufferView); + } + + int GetVertexColorBuffer(System.Drawing.Color[] colors, out Rhino.Display.Color4f min, out Rhino.Display.Color4f max, out int byteLength) + { + byte[] bytes = GetVertexColorBytes(colors, out min, out max); + + glTFLoader.Schema.Buffer vertexColorsBuffer = new glTFLoader.Schema.Buffer() + { + Uri = Constants.TextBufferHeader + Convert.ToBase64String(bytes), + ByteLength = bytes.Length, + }; + + byteLength = bytes.Length; + + return dummy.Buffers.AddAndReturnIndex(vertexColorsBuffer); + } + + byte[] GetVertexColorBytes(System.Drawing.Color[] colors, out Rhino.Display.Color4f min, out Rhino.Display.Color4f max) + { + float[] minArr = new float[] { float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity }; + float[] maxArr = new float[] { float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity }; + + List colorFloats = new List(colors.Length * 4); + + for (int i = 0; i < colors.Length; i++) + { + Rhino.Display.Color4f color = new Rhino.Display.Color4f(colors[i]); + + colorFloats.AddRange(color.ToFloatArray()); + + minArr[0] = Math.Min(minArr[0], color.R); + minArr[1] = Math.Min(minArr[1], color.G); + minArr[2] = Math.Min(minArr[2], color.B); + minArr[3] = Math.Min(minArr[3], color.A); + + maxArr[0] = Math.Max(maxArr[0], color.R); + maxArr[1] = Math.Max(maxArr[1], color.G); + maxArr[2] = Math.Max(maxArr[2], color.B); + maxArr[3] = Math.Max(maxArr[3], color.A); + } + + min = new Rhino.Display.Color4f(minArr[0], minArr[1], minArr[2], minArr[3]); + max = new Rhino.Display.Color4f(maxArr[0], maxArr[1], maxArr[2], maxArr[3]); + + IEnumerable bytesEnumerable = colorFloats.SelectMany(value => BitConverter.GetBytes(value)); + + return bytesEnumerable.ToArray(); + } + + } +} From 583cc8ebf9c92c837fb3d9a918b751a2757d7bfd Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Wed, 15 Sep 2021 13:49:19 +0300 Subject: [PATCH 02/10] Import point clouds --- glTF-BinImporter/GltfRhinoMeshConverter.cs | 190 ++++++++++++++++++--- 1 file changed, 164 insertions(+), 26 deletions(-) diff --git a/glTF-BinImporter/GltfRhinoMeshConverter.cs b/glTF-BinImporter/GltfRhinoMeshConverter.cs index 8db931f..b48d65c 100644 --- a/glTF-BinImporter/GltfRhinoMeshConverter.cs +++ b/glTF-BinImporter/GltfRhinoMeshConverter.cs @@ -13,6 +13,12 @@ struct GltfMeshMaterialPair public string Name; } + struct GltfPointCloudHolder + { + public string Name; + public Rhino.Geometry.PointCloud PointCloud; + } + class GltfMeshHolder { public GltfMeshHolder(GltfRhinoConverter converter, Rhino.RhinoDoc doc) @@ -25,7 +31,8 @@ public GltfMeshHolder(GltfRhinoConverter converter, Rhino.RhinoDoc doc) private Rhino.RhinoDoc doc = null; private List meshMaterialPairs = new List(); - + private List pointCloudHolders = new List(); + public void AddPrimitive(Rhino.Geometry.Mesh rhinoMesh, int? materialIndex, string name) { meshMaterialPairs.Add(new GltfMeshMaterialPair() @@ -36,6 +43,15 @@ public void AddPrimitive(Rhino.Geometry.Mesh rhinoMesh, int? materialIndex, stri }); } + public void AddPointCloudPrimitive(Rhino.Geometry.PointCloud pointCloud, string name) + { + pointCloudHolders.Add(new GltfPointCloudHolder() + { + Name = name, + PointCloud = pointCloud, + }); + } + public void AddInstance(Rhino.Geometry.Transform transform) { foreach(GltfMeshMaterialPair pair in meshMaterialPairs) @@ -61,8 +77,27 @@ public void AddInstance(Rhino.Geometry.Transform transform) rhinoObject.CommitChanges(); } } - } + foreach(GltfPointCloudHolder holder in pointCloudHolders) + { + Rhino.Geometry.PointCloud pointCloud = holder.PointCloud.Duplicate() as Rhino.Geometry.PointCloud; + + if(pointCloud == null) + { + continue; + } + + pointCloud.Transform(GltfUtils.YupToZup * transform); + + Guid objectId = doc.Objects.Add(pointCloud); + + Rhino.DocObjects.RhinoObject rhinoObject = doc.Objects.Find(objectId); + + rhinoObject.Attributes.Name = holder.Name; + + rhinoObject.CommitChanges(); + } + } } class GltfRhinoMeshConverter @@ -89,28 +124,79 @@ public GltfMeshHolder Convert() foreach (var primitive in mesh.Primitives) { - Rhino.Geometry.Mesh rhinoMesh = GetMesh(primitive); - - if(rhinoMesh == null) + if(primitive.Mode == glTFLoader.Schema.MeshPrimitive.ModeEnum.POINTS) { - continue; + Rhino.Geometry.PointCloud pointCloud = GetPointCloud(primitive); + + if(pointCloud == null) + { + continue; + } + + meshHolder.AddPointCloudPrimitive(pointCloud, mesh.Name); } + else + { + Rhino.Geometry.Mesh rhinoMesh = GetMesh(primitive); - rhinoMesh.Weld(0.01); + if (rhinoMesh == null) + { + continue; + } - rhinoMesh.Compact(); + rhinoMesh.Weld(0.01); - if(!rhinoMesh.IsValidWithLog(out string log)) - { - Rhino.RhinoApp.WriteLine(log); - } + rhinoMesh.Compact(); + + if (!rhinoMesh.IsValidWithLog(out string log)) + { + Rhino.RhinoApp.WriteLine(log); + } - meshHolder.AddPrimitive(rhinoMesh, primitive.Material, mesh.Name); + meshHolder.AddPrimitive(rhinoMesh, primitive.Material, mesh.Name); + } } return meshHolder; } + Rhino.Geometry.PointCloud GetPointCloud(glTFLoader.Schema.MeshPrimitive primitive) + { + if(!AttemptGetVertexFloats(primitive, out List points)) + { + return null; + } + + Rhino.Geometry.PointCloud pointCloud = new Rhino.Geometry.PointCloud(); + + for(int i = 0; i < points.Count; i++) + { + pointCloud.Add(points[i]); + } + + if(AttemptGetVertexColors(primitive, out List colors)) + { + int min = Math.Min(colors.Count, pointCloud.Count); + + for(int i = 0; i < min; i++) + { + pointCloud[i].Color = colors[i]; + } + } + + if(AttemptGetNormals(primitive, out List normals)) + { + int min = Math.Min(normals.Count, pointCloud.Count); + + for(int i = 0; i < min; i++) + { + pointCloud[i].Normal = normals[i]; + } + } + + return pointCloud; + } + Rhino.Geometry.Mesh GetMesh(glTFLoader.Schema.MeshPrimitive primitive) { if (primitive.Extensions != null && primitive.Extensions.TryGetValue(glTFExtensions.KHR_draco_mesh_compression.Tag, out object value)) @@ -320,6 +406,23 @@ private bool AttemptConvertIndices(glTFLoader.Schema.MeshPrimitive primitive, Rh private bool AttemptConvertVertices(glTFLoader.Schema.MeshPrimitive primitive, Rhino.Geometry.Mesh rhinoMesh) { + if (!AttemptGetVertexFloats(primitive, out List vertices)) + { + return false; + } + + for (int i = 0; i < vertices.Count; i++) + { + rhinoMesh.Vertices.Add(vertices[i]); + } + + return true; + } + + private bool AttemptGetVertexFloats(glTFLoader.Schema.MeshPrimitive primitive, out List vertices) + { + vertices = new List(); + glTFLoader.Schema.Accessor vertexAcessor = null; if (!primitive.Attributes.TryGetValue(PositionAttributeTag, out int vertexAcessorIndex)) @@ -336,14 +439,14 @@ private bool AttemptConvertVertices(glTFLoader.Schema.MeshPrimitive primitive, R glTFLoader.Schema.BufferView vertexView = converter.GetBufferView(vertexAcessor.BufferView); - if(vertexView == null) + if (vertexView == null) { return false; } byte[] vertexBuffer = converter.GetBuffer(vertexView.Buffer); - if(vertexBuffer == null) + if (vertexBuffer == null) { return false; } @@ -369,12 +472,12 @@ private bool AttemptConvertVertices(glTFLoader.Schema.MeshPrimitive primitive, R } } - int vertices = floats.Count / 3; + int count = floats.Count / 3; - for (int i = 0; i < vertices; i++) + for (int i = 0; i < count; i++) { int index = i * 3; - rhinoMesh.Vertices.Add((double)floats[index], (double)floats[index + 1], (double)floats[index + 2]); + vertices.Add(new Rhino.Geometry.Point3d(floats[index], floats[index + 1], floats[index + 2])); } return true; @@ -382,6 +485,23 @@ private bool AttemptConvertVertices(glTFLoader.Schema.MeshPrimitive primitive, R private bool AttemptConvertNormals(glTFLoader.Schema.MeshPrimitive primitive, Rhino.Geometry.Mesh rhinoMesh) { + if(!AttemptGetNormals(primitive, out List normals)) + { + return false; + } + + for(int i = 0; i < normals.Count; i++) + { + rhinoMesh.Normals.Add(normals[i]); + } + + return true; + } + + private bool AttemptGetNormals(glTFLoader.Schema.MeshPrimitive primitive, out List normals) + { + normals = new List(); + if (!primitive.Attributes.TryGetValue(NormalAttributeTag, out int normalAttributeAccessorIndex)) { return false; @@ -432,11 +552,12 @@ private bool AttemptConvertNormals(glTFLoader.Schema.MeshPrimitive primitive, Rh } } - int normals = normalsFloats.Count / 3; - for (int i = 0; i < normals; i++) + int count = normalsFloats.Count / 3; + + for (int i = 0; i < count; i++) { int index = i * 3; - rhinoMesh.Normals.Add(normalsFloats[index], normalsFloats[index + 1], normalsFloats[index + 2]); + normals.Add(new Rhino.Geometry.Vector3d(normalsFloats[index], normalsFloats[index + 1], normalsFloats[index + 2])); } return true; @@ -525,6 +646,23 @@ private bool AttemptConvertTextureCoordinates(glTFLoader.Schema.MeshPrimitive pr private bool AttemptConvertVertexColors(glTFLoader.Schema.MeshPrimitive primitive, Rhino.Geometry.Mesh rhinoMesh) { + if(!AttemptGetVertexColors(primitive, out List colors)) + { + return false; + } + + foreach(System.Drawing.Color color in colors) + { + rhinoMesh.VertexColors.Add(color); + } + + return true; + } + + private bool AttemptGetVertexColors(glTFLoader.Schema.MeshPrimitive primitive, out List colors) + { + colors = new List(); + if (!primitive.Attributes.TryGetValue(VertexColorAttributeTag, out int vertexColorAccessorIndex)) { return false; @@ -532,21 +670,21 @@ private bool AttemptConvertVertexColors(glTFLoader.Schema.MeshPrimitive primitiv glTFLoader.Schema.Accessor vertexColorAccessor = converter.GetAccessor(vertexColorAccessorIndex); - if(vertexColorAccessor == null) + if (vertexColorAccessor == null) { return false; } glTFLoader.Schema.BufferView vertexColorBufferView = converter.GetBufferView(vertexColorAccessor.BufferView); - if(vertexColorBufferView == null) + if (vertexColorBufferView == null) { return false; } byte[] vertexColorBuffer = converter.GetBuffer(vertexColorBufferView.Buffer); - if(vertexColorBuffer == null) + if (vertexColorBuffer == null) { return false; } @@ -604,7 +742,7 @@ private bool AttemptConvertVertexColors(glTFLoader.Schema.MeshPrimitive primitiv Rhino.Display.Color4f color = new Rhino.Display.Color4f(r, g, b, 1.0f); - rhinoMesh.VertexColors.Add(color.AsSystemColor()); + colors.Add(color.AsSystemColor()); } else if (vertexColorAccessor.Type == glTFLoader.Schema.Accessor.TypeEnum.VEC4) { @@ -615,7 +753,7 @@ private bool AttemptConvertVertexColors(glTFLoader.Schema.MeshPrimitive primitiv Rhino.Display.Color4f color = new Rhino.Display.Color4f(r, g, b, a); - rhinoMesh.VertexColors.Add(color.AsSystemColor()); + colors.Add(color.AsSystemColor()); } } From f79bbb5403817f7f796e60c8bfff555b92c23be3 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 17 Sep 2021 08:59:52 +0300 Subject: [PATCH 03/10] Export point cloud normals --- glTF-BinExporter/RhinoMeshGltfConverter.cs | 2 +- .../RhinoPointCloudGltfConverter.cs | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/glTF-BinExporter/RhinoMeshGltfConverter.cs b/glTF-BinExporter/RhinoMeshGltfConverter.cs index bffc7e8..bf500c3 100644 --- a/glTF-BinExporter/RhinoMeshGltfConverter.cs +++ b/glTF-BinExporter/RhinoMeshGltfConverter.cs @@ -135,7 +135,7 @@ private void PreprocessMesh(Mesh rhinoMesh) primitive.Extensions.Add(glTFExtensions.KHR_draco_mesh_compression.Tag, dracoCompressionObject); } - + primitive.Material = materialIndex; primitives.Add(primitive); diff --git a/glTF-BinExporter/RhinoPointCloudGltfConverter.cs b/glTF-BinExporter/RhinoPointCloudGltfConverter.cs index eab73ae..887ad99 100644 --- a/glTF-BinExporter/RhinoPointCloudGltfConverter.cs +++ b/glTF-BinExporter/RhinoPointCloudGltfConverter.cs @@ -58,6 +58,15 @@ public int AddPointCloud() primitive.Attributes.Add(Constants.VertexColorAttributeTag, colorsAccessorIdx); } + if(pointCloud.ContainsNormals) + { + Rhino.Geometry.Vector3d[] normals = pointCloud.GetNormals(); + + int normalsAccessorIdx = GetNormalsAccessor(normals); + + primitive.Attributes.Add(Constants.NormalAttributeTag, normalsAccessorIdx); + } + glTFLoader.Schema.Mesh mesh = new glTFLoader.Schema.Mesh() { Primitives = new glTFLoader.Schema.MeshPrimitive[] { primitive }, @@ -256,5 +265,96 @@ byte[] GetVertexColorBytes(System.Drawing.Color[] colors, out Rhino.Display.Colo return bytesEnumerable.ToArray(); } + private int GetNormalsAccessor(Rhino.Geometry.Vector3d[] normals) + { + int normalsBufferIdx = GetNormalsBufferView(normals, out Rhino.Geometry.Vector3f min, out Rhino.Geometry.Vector3f max, out int normalsCount); + + glTFLoader.Schema.Accessor normalAccessor = new glTFLoader.Schema.Accessor() + { + BufferView = normalsBufferIdx, + ByteOffset = 0, + ComponentType = glTFLoader.Schema.Accessor.ComponentTypeEnum.FLOAT, + Count = normalsCount, + Min = min.ToFloatArray(), + Max = max.ToFloatArray(), + Type = glTFLoader.Schema.Accessor.TypeEnum.VEC3, + }; + + return dummy.Accessors.AddAndReturnIndex(normalAccessor); + } + + int GetNormalsBufferView(Rhino.Geometry.Vector3d[] normals, out Rhino.Geometry.Vector3f min, out Rhino.Geometry.Vector3f max, out int normalsCount) + { + int buffer = 0; + int byteOffset = 0; + int byteLength = 0; + + if (binary) + { + byte[] bytes = GetNormalsBytes(normals, out min, out max); + byteLength = bytes.Length; + byteOffset = binaryBuffer.Count; + binaryBuffer.AddRange(bytes); + } + else + { + buffer = GetNormalsBuffer(normals, out min, out max, out byteLength); + } + + glTFLoader.Schema.BufferView normalsBufferView = new glTFLoader.Schema.BufferView() + { + Buffer = buffer, + ByteLength = byteLength, + ByteOffset = byteOffset, + Target = glTFLoader.Schema.BufferView.TargetEnum.ARRAY_BUFFER, + }; + + normalsCount = normals.Length; + + return dummy.BufferViews.AddAndReturnIndex(normalsBufferView); + } + + int GetNormalsBuffer(Rhino.Geometry.Vector3d[] normals, out Rhino.Geometry.Vector3f min, out Rhino.Geometry.Vector3f max, out int byteLength) + { + byte[] bytes = GetNormalsBytes(normals, out min, out max); + + byteLength = bytes.Length; + + glTFLoader.Schema.Buffer normalBuffer = new glTFLoader.Schema.Buffer() + { + Uri = Constants.TextBufferHeader + Convert.ToBase64String(bytes), + ByteLength = bytes.Length, + }; + + return dummy.Buffers.AddAndReturnIndex(normalBuffer); + } + + byte[] GetNormalsBytes(Rhino.Geometry.Vector3d[] normals, out Rhino.Geometry.Vector3f min, out Rhino.Geometry.Vector3f max) + { + min = new Rhino.Geometry.Vector3f(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); + max = new Rhino.Geometry.Vector3f(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); + + //Preallocate + List floats = new List(normals.Length * 3); + + foreach (Rhino.Geometry.Vector3f normal in normals) + { + floats.AddRange(new float[] { normal.X, normal.Y, normal.Z }); + + min.X = Math.Min(min.X, normal.X); + max.X = Math.Max(max.X, normal.X); + + min.Y = Math.Min(min.Y, normal.Y); + max.Y = Math.Max(max.Y, normal.Y); + + max.Z = Math.Max(max.Z, normal.Z); + min.Z = Math.Min(min.Z, normal.Z); + } + + IEnumerable bytesEnumerable = floats.SelectMany(value => BitConverter.GetBytes(value)); + + return bytesEnumerable.ToArray(); + } + } } From f1cd9846db51ac25afb6bfa348706002f6dfe973 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 17 Sep 2021 09:00:50 +0300 Subject: [PATCH 04/10] Add volume to extensions --- glTFExtensions/KHR_materials_volume.cs | 25 +++++++++++++++++++++++++ glTFExtensions/glTFExtensions.csproj | 1 + 2 files changed, 26 insertions(+) create mode 100644 glTFExtensions/KHR_materials_volume.cs diff --git a/glTFExtensions/KHR_materials_volume.cs b/glTFExtensions/KHR_materials_volume.cs new file mode 100644 index 0000000..b547fbd --- /dev/null +++ b/glTFExtensions/KHR_materials_volume.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace glTFExtensions +{ + public class KHR_materials_volume + { + public const string Tag = "KHR_materials_volume"; + + [Newtonsoft.Json.JsonPropertyAttribute("thicknessFactor")] + public float ThicknessFactor = 0.0f; + + [Newtonsoft.Json.JsonPropertyAttribute("thicknessTexture")] + public glTFLoader.Schema.TextureInfo ThicknessTexture = null; + + [Newtonsoft.Json.JsonPropertyAttribute("attenuationDistance")] + public float AttenuationDistance = float.PositiveInfinity; + + [Newtonsoft.Json.JsonPropertyAttribute("attenuationColor")] + public float[] AttenuationColor = new float[] { 1.0f, 1.0f, 1.0f }; + } +} diff --git a/glTFExtensions/glTFExtensions.csproj b/glTFExtensions/glTFExtensions.csproj index 86bbad4..deead71 100644 --- a/glTFExtensions/glTFExtensions.csproj +++ b/glTFExtensions/glTFExtensions.csproj @@ -49,6 +49,7 @@ + From a783754f003886a206cfdcb9094723bc52b2dc85 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 17 Sep 2021 09:41:24 +0300 Subject: [PATCH 05/10] Use volume extension --- glTF-BinExporter/RhinoMaterialGltfConverter.cs | 9 +++++++++ glTFExtensions/KHR_draco_mesh_compression.cs | 3 +++ glTFExtensions/KHR_materials_clearcoat.cs | 3 +++ glTFExtensions/KHR_materials_ior.cs | 3 +++ glTFExtensions/KHR_materials_specular.cs | 3 +++ glTFExtensions/KHR_materials_transmission.cs | 3 +++ glTFExtensions/KHR_materials_volume.cs | 8 ++++++++ 7 files changed, 32 insertions(+) diff --git a/glTF-BinExporter/RhinoMaterialGltfConverter.cs b/glTF-BinExporter/RhinoMaterialGltfConverter.cs index 2e5b6a7..a24c150 100644 --- a/glTF-BinExporter/RhinoMaterialGltfConverter.cs +++ b/glTF-BinExporter/RhinoMaterialGltfConverter.cs @@ -210,6 +210,15 @@ public int AddMaterial() material.Extensions.Add(glTFExtensions.KHR_materials_specular.Tag, specular); + //Volume extension + + glTFExtensions.KHR_materials_volume volume = new glTFExtensions.KHR_materials_volume(); + + //0 is thin surface, all else is the geometries thickness. We don't support anything other than this. + volume.ThicknessFactor = 1.0f; + + material.Extensions.Add(glTFExtensions.KHR_materials_volume.Tag, volume); + return dummy.Materials.AddAndReturnIndex(material); } diff --git a/glTFExtensions/KHR_draco_mesh_compression.cs b/glTFExtensions/KHR_draco_mesh_compression.cs index a828bac..43ac58a 100644 --- a/glTFExtensions/KHR_draco_mesh_compression.cs +++ b/glTFExtensions/KHR_draco_mesh_compression.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md + /// public class KHR_draco_mesh_compression { public const string Tag = "KHR_draco_mesh_compression"; diff --git a/glTFExtensions/KHR_materials_clearcoat.cs b/glTFExtensions/KHR_materials_clearcoat.cs index 6c3260e..04a932e 100644 --- a/glTFExtensions/KHR_materials_clearcoat.cs +++ b/glTFExtensions/KHR_materials_clearcoat.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md + /// public class KHR_materials_clearcoat { public const string Tag = "KHR_materials_clearcoat"; diff --git a/glTFExtensions/KHR_materials_ior.cs b/glTFExtensions/KHR_materials_ior.cs index c22add0..6337fe4 100644 --- a/glTFExtensions/KHR_materials_ior.cs +++ b/glTFExtensions/KHR_materials_ior.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_ior/README.md + /// public class KHR_materials_ior { public const string Tag = "KHR_materials_ior"; diff --git a/glTFExtensions/KHR_materials_specular.cs b/glTFExtensions/KHR_materials_specular.cs index dd2d16a..7be6390 100644 --- a/glTFExtensions/KHR_materials_specular.cs +++ b/glTFExtensions/KHR_materials_specular.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_specular/README.md + /// public class KHR_materials_specular { public const string Tag = "KHR_materials_specular"; diff --git a/glTFExtensions/KHR_materials_transmission.cs b/glTFExtensions/KHR_materials_transmission.cs index a0963f7..a9c2b8e 100644 --- a/glTFExtensions/KHR_materials_transmission.cs +++ b/glTFExtensions/KHR_materials_transmission.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_transmission/README.md + /// public class KHR_materials_transmission { public const string Tag = "KHR_materials_transmission"; diff --git a/glTFExtensions/KHR_materials_volume.cs b/glTFExtensions/KHR_materials_volume.cs index b547fbd..368468e 100644 --- a/glTFExtensions/KHR_materials_volume.cs +++ b/glTFExtensions/KHR_materials_volume.cs @@ -6,6 +6,9 @@ namespace glTFExtensions { + /// + /// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_volume/README.md + /// public class KHR_materials_volume { public const string Tag = "KHR_materials_volume"; @@ -21,5 +24,10 @@ public class KHR_materials_volume [Newtonsoft.Json.JsonPropertyAttribute("attenuationColor")] public float[] AttenuationColor = new float[] { 1.0f, 1.0f, 1.0f }; + + public bool ShouldSerializeThicknessTexture() + { + return ThicknessTexture != null; + } } } From 6ec0f14359e4e99128af63b460b87f2af4bf71f3 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Thu, 7 Oct 2021 12:39:24 +0300 Subject: [PATCH 06/10] Remove using glTFLoader.Schema to make code more explicit --- glTF-BinExporter/RhinoDocGltfConverter.cs | 27 +++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/glTF-BinExporter/RhinoDocGltfConverter.cs b/glTF-BinExporter/RhinoDocGltfConverter.cs index b1c0a78..0d5e90e 100644 --- a/glTF-BinExporter/RhinoDocGltfConverter.cs +++ b/glTF-BinExporter/RhinoDocGltfConverter.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Rhino.DocObjects; using Rhino; -using glTFLoader.Schema; using Rhino.Render; using Rhino.Display; @@ -53,7 +52,7 @@ public RhinoDocGltfConverter(glTFExportOptions options, bool binary, RhinoDoc do private List binaryBuffer = new List(); - private Dictionary layers = new Dictionary(); + private Dictionary layers = new Dictionary(); private RenderMaterial defaultMaterial = null; private RenderMaterial DefaultMaterial @@ -68,22 +67,22 @@ private RenderMaterial DefaultMaterial return defaultMaterial; } } - public Gltf ConvertToGltf() + public glTFLoader.Schema.Gltf ConvertToGltf() { dummy.Scene = 0; dummy.Scenes.Add(new gltfSchemaSceneDummy()); - dummy.Asset = new Asset() + dummy.Asset = new glTFLoader.Schema.Asset() { Version = "2.0", }; - dummy.Samplers.Add(new Sampler() + dummy.Samplers.Add(new glTFLoader.Schema.Sampler() { - MinFilter = Sampler.MinFilterEnum.LINEAR, - MagFilter = Sampler.MagFilterEnum.LINEAR, - WrapS = Sampler.WrapSEnum.REPEAT, - WrapT = Sampler.WrapTEnum.REPEAT, + MinFilter = glTFLoader.Schema.Sampler.MinFilterEnum.LINEAR, + MagFilter = glTFLoader.Schema.Sampler.MagFilterEnum.LINEAR, + WrapS = glTFLoader.Schema.Sampler.WrapSEnum.REPEAT, + WrapT = glTFLoader.Schema.Sampler.WrapTEnum.REPEAT, }); if(options.UseDracoCompression) @@ -106,7 +105,7 @@ public Gltf ConvertToGltf() if(meshIndex != -1) { - glTFLoader.Schema.Node node = new Node() + glTFLoader.Schema.Node node = new glTFLoader.Schema.Node() { Mesh = meshIndex, Name = GetObjectName(rhinoObject), @@ -143,7 +142,7 @@ public Gltf ConvertToGltf() //have to add the empty buffer for the binary file header dummy.Buffers.Add(new glTFLoader.Schema.Buffer() { - ByteLength = (int)binaryBuffer.Count, + ByteLength = binaryBuffer.Count, Uri = null, }); } @@ -165,7 +164,7 @@ private void AddNode(int nodeIndex, Rhino.DocObjects.RhinoObject rhinoObject) private void AddToLayer(Layer layer, int child) { - if(layers.TryGetValue(layer.Index, out Node node)) + if(layers.TryGetValue(layer.Index, out glTFLoader.Schema.Node node)) { if (node.Children == null) { @@ -178,7 +177,7 @@ private void AddToLayer(Layer layer, int child) } else { - node = new Node() + node = new glTFLoader.Schema.Node() { Name = layer.Name, Children = new int[1] { child }, @@ -244,7 +243,7 @@ int CreateSolidColorMaterial(Color4f color) { glTFLoader.Schema.Material material = new glTFLoader.Schema.Material() { - PbrMetallicRoughness = new MaterialPbrMetallicRoughness() + PbrMetallicRoughness = new glTFLoader.Schema.MaterialPbrMetallicRoughness() { BaseColorFactor = color.ToFloatArray(), } From a64762d26902673952f3b536dfea0331feede450 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Thu, 7 Oct 2021 12:42:02 +0300 Subject: [PATCH 07/10] Remove unused function, use object Id when object is unnamed --- glTF-BinExporter/RhinoDocGltfConverter.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/glTF-BinExporter/RhinoDocGltfConverter.cs b/glTF-BinExporter/RhinoDocGltfConverter.cs index 0d5e90e..45ab6c9 100644 --- a/glTF-BinExporter/RhinoDocGltfConverter.cs +++ b/glTF-BinExporter/RhinoDocGltfConverter.cs @@ -202,7 +202,7 @@ private void AddToLayer(Layer layer, int child) public string GetObjectName(RhinoObject rhinoObject) { - return string.IsNullOrEmpty(rhinoObject.Name) ? null : rhinoObject.Name; + return string.IsNullOrEmpty(rhinoObject.Name) ? rhinoObject.Id.ToString() : rhinoObject.Name; } public byte[] GetBinaryBuffer() @@ -343,16 +343,6 @@ public bool MeshIsValidForExport(Rhino.Geometry.Mesh mesh) return true; } - private string GetDebugName(RhinoObject rhinoObject) - { - if (string.IsNullOrEmpty(rhinoObject.Name)) - { - return "(Unnamed)"; - } - - return rhinoObject.Name; - } - public List SanitizeRhinoObjects(IEnumerable rhinoObjects) { List explodedObjects = new List(); From 8deb0b6fd83b08cd822ec87061e3260464769d50 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 8 Oct 2021 15:05:18 +0300 Subject: [PATCH 08/10] Add volume tag to used extensions --- glTF-BinExporter/RhinoDocGltfConverter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/glTF-BinExporter/RhinoDocGltfConverter.cs b/glTF-BinExporter/RhinoDocGltfConverter.cs index 45ab6c9..a0e440e 100644 --- a/glTF-BinExporter/RhinoDocGltfConverter.cs +++ b/glTF-BinExporter/RhinoDocGltfConverter.cs @@ -95,6 +95,7 @@ public glTFLoader.Schema.Gltf ConvertToGltf() dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_clearcoat.Tag); dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_ior.Tag); dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_specular.Tag); + dummy.ExtensionsUsed.Add(glTFExtensions.KHR_materials_volume.Tag); IEnumerable pointClouds = objects.Where(x => x.ObjectType == ObjectType.PointSet); From b0c747487108918c801d532dcf3b887f3963d272 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 8 Oct 2021 15:05:48 +0300 Subject: [PATCH 09/10] Use specular tint texture instead of specular, correctly set emission values --- .../RhinoMaterialGltfConverter.cs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/glTF-BinExporter/RhinoMaterialGltfConverter.cs b/glTF-BinExporter/RhinoMaterialGltfConverter.cs index a24c150..9f82c1a 100644 --- a/glTF-BinExporter/RhinoMaterialGltfConverter.cs +++ b/glTF-BinExporter/RhinoMaterialGltfConverter.cs @@ -68,7 +68,7 @@ public int AddMaterial() Rhino.DocObjects.Texture clearcoatTexture = pbr.GetTexture(TextureType.PBR_Clearcoat); Rhino.DocObjects.Texture clearcoatRoughessTexture = pbr.GetTexture(TextureType.PBR_ClearcoatRoughness); Rhino.DocObjects.Texture clearcoatNormalTexture = pbr.GetTexture(TextureType.PBR_ClearcoatBump); - Rhino.DocObjects.Texture specularTexture = pbr.GetTexture(TextureType.PBR_Specular); + Rhino.DocObjects.Texture specularTintTexture = pbr.GetTexture(TextureType.PBR_SpecularTint); HandleBaseColor(rhinoMaterial, material); @@ -104,7 +104,15 @@ public int AddMaterial() if (emissiveTexture != null && emissiveTexture.Enabled) { material.EmissiveTexture = AddTexture(emissiveTexture.FileReference.FullPath); - + material.EmissiveFactor = new float[] + { + 1.0f, + 1.0f, + 1.0f, + }; + } + else + { float emissionMultiplier = 1.0f; var param = rhinoMaterial.RenderMaterial.GetParameter("emission-multiplier"); @@ -114,20 +122,19 @@ public int AddMaterial() emissionMultiplier = (float)Convert.ToDouble(param); } + float r = rhinoMaterial.PhysicallyBased.Emission.R / emissionMultiplier; + float g = rhinoMaterial.PhysicallyBased.Emission.G / emissionMultiplier; + float b = rhinoMaterial.PhysicallyBased.Emission.B / emissionMultiplier; + + r = Math.Max(Math.Min(r, 0.0f), 1.0f); + g = Math.Max(Math.Min(g, 0.0f), 1.0f); + b = Math.Max(Math.Min(b, 0.0f), 1.0f); + material.EmissiveFactor = new float[] { - emissionMultiplier, - emissionMultiplier, - emissionMultiplier, - }; - } - else - { - material.EmissiveFactor = new float[] - { - rhinoMaterial.PhysicallyBased.Emission.R, - rhinoMaterial.PhysicallyBased.Emission.G, - rhinoMaterial.PhysicallyBased.Emission.B, + r, + g, + b, }; } @@ -197,15 +204,15 @@ public int AddMaterial() glTFExtensions.KHR_materials_specular specular = new glTFExtensions.KHR_materials_specular(); - if(specularTexture != null && specularTexture.Enabled) + if(specularTintTexture != null && specularTintTexture.Enabled) { //Specular is stored in the textures alpha channel - specular.SpecularTexture = GetSingleChannelTexture(specularTexture, RgbaChannel.Alpha, false); - specular.SpecularFactor = GetTextureWeight(specularTexture); + specular.SpecularTexture = GetSingleChannelTexture(specularTintTexture, RgbaChannel.Alpha, false); + specular.SpecularFactor = GetTextureWeight(specularTintTexture); } else { - specular.SpecularFactor = (float)pbr.Specular; + specular.SpecularFactor = (float)pbr.SpecularTint; } material.Extensions.Add(glTFExtensions.KHR_materials_specular.Tag, specular); @@ -462,7 +469,7 @@ private int AddTextureToBuffers(string texturePath) var texture = new glTFLoader.Schema.Texture() { Source = imageIdx, - Sampler = 0 + Sampler = 0, }; return dummy.Textures.AddAndReturnIndex(texture); From 0a15edd2783f2886e112b82e16839b6a19459bc1 Mon Sep 17 00:00:00 2001 From: Joshua Kennedy Date: Fri, 8 Oct 2021 15:28:40 +0300 Subject: [PATCH 10/10] Set use diffuse alpha for transparency on import, correctly set transmission --- glTF-BinImporter/GltfRhinoConverter.cs | 11 ++++++++++- glTF-BinImporter/GltfRhinoMaterialConverter.cs | 4 +++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/glTF-BinImporter/GltfRhinoConverter.cs b/glTF-BinImporter/GltfRhinoConverter.cs index 001f981..23bf394 100644 --- a/glTF-BinImporter/GltfRhinoConverter.cs +++ b/glTF-BinImporter/GltfRhinoConverter.cs @@ -269,7 +269,7 @@ public Rhino.Render.RenderTexture GetRenderTexture(int textureIndex) return renderTexture; } - public Rhino.Render.RenderTexture GetRenderTextureFromChannel(int textureIndex, RgbaChannel channel) + public Rhino.Render.RenderTexture GetRenderTextureFromChannel(int textureIndex, RgbaChannel channel, bool invert = false) { System.Drawing.Bitmap bmp = GetTextureBitmap(textureIndex, out string name); @@ -291,6 +291,15 @@ public Rhino.Render.RenderTexture GetRenderTextureFromChannel(int textureIndex, System.Drawing.Color colorResolved = GetColorFromChannel(color, channel); + if(invert) + { + int r = 255 - colorResolved.R; + int g = 255 - colorResolved.G; + int b = 255 - colorResolved.B; + + colorResolved = System.Drawing.Color.FromArgb(r, g, b); + } + resolvedBmp.SetPixel(i, j, colorResolved); } } diff --git a/glTF-BinImporter/GltfRhinoMaterialConverter.cs b/glTF-BinImporter/GltfRhinoMaterialConverter.cs index f527873..21a8111 100644 --- a/glTF-BinImporter/GltfRhinoMaterialConverter.cs +++ b/glTF-BinImporter/GltfRhinoMaterialConverter.cs @@ -41,6 +41,8 @@ public Rhino.Render.RenderMaterial Convert() pbr.SetChild(texture, Rhino.Render.ParameterNames.PhysicallyBased.BaseColor); pbr.SetChildSlotOn(Rhino.Render.ParameterNames.PhysicallyBased.BaseColor, true, RenderContent.ChangeContexts.Program); + + pbr.SetParameter("alpha-transparency", true); } baseColor = GltfUtils.UnapplyGamma(baseColor); @@ -221,7 +223,7 @@ void HandleTransmission(string text, RenderMaterial pbr) } else { - pbr.SetParameter(PhysicallyBased.Opacity, 1.0 - transmission.TransmissionFactor); + pbr.SetParameter(PhysicallyBased.Opacity, transmission.TransmissionFactor); } } }