diff --git a/Common_glTF_Exporter/Common_glTF_Exporter.projitems b/Common_glTF_Exporter/Common_glTF_Exporter.projitems
index 8005c04..1b0f1dc 100644
--- a/Common_glTF_Exporter/Common_glTF_Exporter.projitems
+++ b/Common_glTF_Exporter/Common_glTF_Exporter.projitems
@@ -9,24 +9,10 @@
Common_glTF_Exporter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -54,9 +40,7 @@
-
-
diff --git a/Common_glTF_Exporter/Core/GLTFAccessor.cs b/Common_glTF_Exporter/Core/GLTFAccessor.cs
deleted file mode 100644
index ed37c9e..0000000
--- a/Common_glTF_Exporter/Core/GLTFAccessor.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System.Collections.Generic;
- using Revit_glTF_Exporter;
-
- ///
- /// A reference to a subsection of a BufferView containing a particular data type
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#accessors.
- ///
- public class GLTFAccessor
- {
- public GLTFAccessor(int bufferView, int byteOffset, ComponentType componentType, int count, string type, List max, List min, string name)
- {
- this.bufferView = bufferView;
- this.byteOffset = byteOffset;
- this.componentType = componentType;
- this.count = count;
- this.type = type;
- this.max = max;
- this.min = min;
- this.name = name;
- }
-
- ///
- /// Gets or sets the index of the bufferView.
- ///
- public int bufferView { get; set; }
-
- ///
- /// Gets or sets the offset relative to the start of the bufferView in bytes.
- ///
- public int byteOffset { get; set; }
-
- ///
- /// Gets or sets the datatype of the components in the attribute.
- ///
- public ComponentType componentType { get; set; }
-
- ///
- /// Gets or sets the number of attributes referenced by this accessor.
- ///
- public int count { get; set; }
-
- ///
- /// Gets or sets the specifies if the attribute is a scala, vector, or matrix.
- ///
- public string type { get; set; }
-
- ///
- /// Gets or sets the maximum value of each component in this attribute.
- ///
- public List max { get; set; }
-
- ///
- /// Gets or sets the minimum value of each component in this attribute.
- ///
- public List min { get; set; }
-
- ///
- /// Gets or sets a user defined name for this accessor.
- ///
- public string name { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFAttribute.cs b/Common_glTF_Exporter/Core/GLTFAttribute.cs
deleted file mode 100644
index b1c4a57..0000000
--- a/Common_glTF_Exporter/Core/GLTFAttribute.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- ///
- /// The list of accessors available to the renderer for a particular mesh
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes.
- ///
- public class GLTFAttribute
- {
- ///
- /// Gets or sets the index of the accessor for position data.
- ///
- public int POSITION { get; set; }
-
- ///
- /// Gets or sets the index of the accessor for normal data.
- ///
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public int? NORMAL { get; set; }
-
- ///
- /// Gets or sets the index of the accessor for batchId data.
- ///
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public int? _BATCHID { get; set; }
-
- ///
- /// Gets or sets the index of the UV Coordinates of the material's textures.
- ///
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public int? TEXCOORD_0 { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFBinaryData.cs b/Common_glTF_Exporter/Core/GLTFBinaryData.cs
deleted file mode 100644
index 7908002..0000000
--- a/Common_glTF_Exporter/Core/GLTFBinaryData.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- ///
- /// A binary data store serialized to a *.bin file
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#binary-data-storage.
- ///
- public class GLTFBinaryData
- {
- public List vertexBuffer { get; set; } = new List();
-
- public List normalBuffer { get; set; } = new List();
-
- public List indexBuffer { get; set; } = new List();
-
- public List batchIdBuffer { get; set; } = new List();
-
- public int vertexAccessorIndex { get; set; }
-
- public int normalsAccessorIndex { get; set; }
-
- public int indexAccessorIndex { get; set; }
-
- public int batchIdAccessorIndex { get; set; }
-
- public string name { get; set; }
-
- public List uvBuffer { get; set; } = new List();
- public int uvAccessorIndex { get; set; } = -1;
-
- public byte[] byteData { get; set; } = null;
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFBuffer.cs b/Common_glTF_Exporter/Core/GLTFBuffer.cs
deleted file mode 100644
index a973d3a..0000000
--- a/Common_glTF_Exporter/Core/GLTFBuffer.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- ///
- /// A reference to the location and size of binary data
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#buffers-and-buffer-views.
- ///
- public class GLTFBuffer
- {
- ///
- /// Gets or sets the uri of the buffer.
- ///
- public string uri { get; set; }
-
- ///
- /// Gets or sets the total byte length of the buffer.
- ///
- public int byteLength { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFBufferView.cs b/Common_glTF_Exporter/Core/GLTFBufferView.cs
deleted file mode 100644
index 11e3306..0000000
--- a/Common_glTF_Exporter/Core/GLTFBufferView.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using Newtonsoft.Json;
- using Revit_glTF_Exporter;
-
- ///
- /// A reference to a subsection of a buffer containing either vector or scalar data.
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#buffers-and-buffer-views
- ///
- public class GLTFBufferView
- {
- public GLTFBufferView(int buffer, int byteOffset, int byteLength, Targets target, string name)
- {
- this.buffer = buffer;
- this.byteOffset = byteOffset;
- this.byteLength = byteLength;
- this.target = target;
- this.name = name;
- }
-
- [JsonProperty("buffer")]
- public int buffer { get; set; }
-
- [JsonProperty("byteOffset")]
- public int byteOffset { get; set; }
-
- [JsonProperty("byteLength")]
- public int byteLength { get; set; }
-
- [JsonIgnore] // Ignore the raw enum field so we can customize serialization
- public Targets target { get; set; }
-
- [JsonProperty("target")]
- public int? TargetValue
- {
- get
- {
- if (target == Targets.ARRAY_BUFFER)
- return 34962;
- else if (target == Targets.ELEMENT_ARRAY_BUFFER)
- return 34963;
- else
- return null;
- }
- }
-
- public bool ShouldSerializeTargetValue()
- {
- return TargetValue != null;
- }
-
- [JsonProperty("name")]
- public string name { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFExtras.cs b/Common_glTF_Exporter/Core/GLTFExtras.cs
deleted file mode 100644
index c5aa8ef..0000000
--- a/Common_glTF_Exporter/Core/GLTFExtras.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System.Collections.Generic;
- using Common_glTF_Exporter.Export;
- using Revit_glTF_Exporter;
-
- public class GLTFExtras
- {
- ///
- /// Gets or sets the Revit created UniqueId for this object.
- ///
- public string uniqueId { get; set; }
-
- public RevitGridParametersObject gridParameters { get; set; }
-
- public Dictionary parameters { get; set; }
-
- public long elementId { get; set; }
-
- public string elementCategory { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFImage.cs b/Common_glTF_Exporter/Core/GLTFImage.cs
deleted file mode 100644
index e47bb30..0000000
--- a/Common_glTF_Exporter/Core/GLTFImage.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Newtonsoft.Json;
-
-namespace Common_glTF_Exporter.Core
-{
- ///
- /// An image used by a texture
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#images
- ///
- public class GLTFImage
- {
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public string uri { get; set; }
-
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public int? bufferView { get; set; }
-
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public string mimeType { get; set; }
- }
-}
\ No newline at end of file
diff --git a/Common_glTF_Exporter/Core/GLTFMaterial.cs b/Common_glTF_Exporter/Core/GLTFMaterial.cs
deleted file mode 100644
index 842338b..0000000
--- a/Common_glTF_Exporter/Core/GLTFMaterial.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Text;
- using Newtonsoft.Json;
- using Revit_glTF_Exporter;
-
- ///
- /// The glTF PBR Material format
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materials.
- ///
- public class GLTFMaterial
- {
- public string alphaMode { get; set; }
-
- public float? alphaCutoff { get; set; }
-
- public string name { get; set; }
-
- public GLTFPBR pbrMetallicRoughness { get; set; }
-
- public bool doubleSided { get; set; }
-
- public GLTFTexture normalTexture { get; set; }
- public GLTFTexture occlusionTexture { get; set; }
- public GLTFTexture emissiveTexture { get; set; }
- public List emissiveFactor { get; set; }
-
- [JsonIgnore]
- public string EmbeddedTexturePath { get; set; } = null;
- [JsonIgnore]
- public double Fadevalue { get; set; } = 1;
-
- [JsonIgnore]
- public Autodesk.Revit.DB.Color TintColour { get; set; }
-
- [JsonIgnore]
- public Autodesk.Revit.DB.Color BaseColor { get; set; }
-
- [JsonIgnore]
- public string UniqueId { get; set; } = null;
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFMesh.cs b/Common_glTF_Exporter/Core/GLTFMesh.cs
deleted file mode 100644
index ebc1238..0000000
--- a/Common_glTF_Exporter/Core/GLTFMesh.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Revit_glTF_Exporter;
-
- ///
- /// The array of primitives defining the mesh of an object
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes.
- ///
- public class GLTFMesh
- {
- public List primitives { get; set; }
-
- public string name { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFMeshPrimitive.cs b/Common_glTF_Exporter/Core/GLTFMeshPrimitive.cs
deleted file mode 100644
index f3eed35..0000000
--- a/Common_glTF_Exporter/Core/GLTFMeshPrimitive.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using static Revit_glTF_Exporter.GLTF;
-
- ///
- /// Properties defining where the GPU should look to find the mesh and material data
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes.
- ///
- public class GLTFMeshPrimitive
- {
- public GLTFAttribute attributes { get; set; } = new GLTFAttribute();
-
- public int indices { get; set; }
-
- public int? material { get; set; } = null;
-
- public int mode { get; set; } = 4; // 4 is triangles
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFNode.cs b/Common_glTF_Exporter/Core/GLTFNode.cs
deleted file mode 100644
index d0d9d29..0000000
--- a/Common_glTF_Exporter/Core/GLTFNode.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Autodesk.Revit.DB;
- using Revit_glTF_Exporter;
-
- ///
- /// The nodes defining individual (or nested) elements in the scene
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy.
- ///
- public class GLTFNode
- {
- ///
- /// Gets or sets the user-defined name of this object.
- ///
- public string name { get; set; }
-
- ///
- /// Gets or sets the index of the mesh in this node.
- ///
- public int? mesh { get; set; } = null;
-
- ///
- /// Gets or sets a floating-point 4x4 transformation matrix stored in column major order.
- ///
- public List matrix { get; set; }
-
- ///
- /// Gets or sets the indices of this node's children.
- ///
- public List children { get; set; }
-
- ///
- /// Gets or sets the extras describing this node.
- ///
- public GLTFExtras extras { get; set; }
-
- ///
- /// Gets or sets rotation of the node.
- ///
- public List rotation { get; set; }
-
- ///
- /// Gets or sets translation of the node.
- ///
- public List translation { get; set; }
-
- ///
- /// Gets or sets scale of the node.
- ///
- public List scale { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFScene.cs b/Common_glTF_Exporter/Core/GLTFScene.cs
deleted file mode 100644
index 1c30c67..0000000
--- a/Common_glTF_Exporter/Core/GLTFScene.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System.Collections.Generic;
-
- ///
- /// The scenes available to render
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes.
- ///
- public class GLTFScene
- {
- public List nodes = new List();
- }
-}
diff --git a/Common_glTF_Exporter/Core/GLTFTextureInfo.cs b/Common_glTF_Exporter/Core/GLTFTextureInfo.cs
deleted file mode 100644
index daa9480..0000000
--- a/Common_glTF_Exporter/Core/GLTFTextureInfo.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
-
- ///
- /// Texture information for a material property
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#texture-info
- ///
- public class GLTFTexture
- {
- public int source { get; set; }
- }
-
- public class GLTFTextureInfo
- {
- public int index { get; set; }
- public int texCoord { get; set; } = 0;
-
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
- public GLTFTextureExtensions extensions { get; set; }
- }
-
- public class GLTFTextureTransform
- {
- public float[] offset { get; set; } = new float[] { 0.0f, 0.0f };
- public float[] scale { get; set; } = new float[] { 1.0f, 1.0f };
- public float rotation { get; set; } = 0.0f;
- public int texCoord { get; set; } = 0;
- }
-
- public class GLTFTextureExtensions
- {
- [JsonProperty("KHR_texture_transform")]
- public GLTFTextureTransform TextureTransform { get; set; }
- }
-}
\ No newline at end of file
diff --git a/Common_glTF_Exporter/Core/GLTFVersion.cs b/Common_glTF_Exporter/Core/GLTFVersion.cs
deleted file mode 100644
index 192cc9d..0000000
--- a/Common_glTF_Exporter/Core/GLTFVersion.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using Common_glTF_Exporter.Utils;
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- ///
- /// Required glTF asset information
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#asset.
- ///
- public class GLTFVersion
- {
- public string version = "2.0";
- public string generator = string.Concat("e-verse custom generator ", SettingsConfig.currentVersion);
- public string copyright = "free tool created by e-verse";
- }
-}
diff --git a/Common_glTF_Exporter/Core/GlTFExportContext.cs b/Common_glTF_Exporter/Core/GlTFExportContext.cs
index bbe45e0..60821a8 100644
--- a/Common_glTF_Exporter/Core/GlTFExportContext.cs
+++ b/Common_glTF_Exporter/Core/GlTFExportContext.cs
@@ -1,16 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Autodesk.Revit.DB;
+using Autodesk.Revit.DB;
+using Common_glTF_Exporter.EportUtils;
using Common_glTF_Exporter.Export;
using Common_glTF_Exporter.Model;
using Common_glTF_Exporter.Transform;
using Common_glTF_Exporter.Utils;
using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
using Revit_glTF_Exporter;
-using Common_glTF_Exporter.EportUtils;
-using System.Windows.Media.Media3D;
-using System.Windows.Controls;
+using System.Collections.Generic;
+using System.Linq;
+using Buffer = glTF.Manipulator.Schema.Buffer;
namespace Common_glTF_Exporter.Core
{
@@ -31,10 +31,8 @@ public class GLTFExportContext : IExportContext
private Document currentDocument;
private Autodesk.Revit.DB.View currentView;
- private GLTFNode currentNode;
private Element currentElement;
- private Face currentFace;
- private GLTFMaterial currentMaterial;
+ private BaseMaterial currentMaterial;
private Stack transformStack = new Stack();
///
@@ -52,20 +50,22 @@ public class GLTFExportContext : IExportContext
///
/// Reference to the rootNode to add children.
///
- private GLTFNode rootNode;
-
- public IndexedDictionary nodes = new IndexedDictionary();
-
- public IndexedDictionary materials = new IndexedDictionary();
- public List textures { get; } = new List();
- public List images { get; } = new List();
- public List scenes { get; } = new List();
- public IndexedDictionary meshes { get; } = new IndexedDictionary();
- public List buffers { get; } = new List();
- public List bufferViews { get; } = new List();
- public List accessors { get; } = new List();
+ private Node rootNode;
+
+ public IndexedDictionary nodes = new IndexedDictionary();
+
+ public IndexedDictionary materials = new IndexedDictionary();
+ public List textures { get; } = new List();
+ public List images { get; } = new List();
+ public List scenes { get; } = new List();
+ public IndexedDictionary meshes { get; } = new IndexedDictionary();
+ public List buffers { get; } = new List();
+ public List bufferViews { get; } = new List();
+ public List accessors { get; } = new List();
public List binaryFileData { get; } = new List();
+ GLTFBinaryData globalBuffer = new GLTFBinaryData();
+
private Autodesk.Revit.DB.Transform CurrentTransform
{
get
@@ -93,7 +93,7 @@ public bool Start()
transformStack.Push(Autodesk.Revit.DB.Transform.Identity);
// Creation Root Node
- rootNode = new GLTFNode();
+ rootNode = new Node();
rootNode.name = "rootNode";
rootNode.rotation = ModelRotation.Get(preferences.flipAxis);
rootNode.scale = ModelScale.Get(preferences);
@@ -104,7 +104,7 @@ public bool Start()
nodes.AddOrUpdateCurrent("rootNode", rootNode);
// Creation default scene
- GLTFScene defaultScene = new GLTFScene();
+ Scene defaultScene = new Scene();
defaultScene.nodes.Add(0);
scenes.Add(defaultScene);
@@ -112,7 +112,9 @@ public bool Start()
currentVertices = new IndexedDictionary();
currentMaterial = GLTFExportUtils.CreateDefaultGLTFMaterial(1, true);
- materials.AddOrUpdateCurrentMaterial(currentMaterial.UniqueId, currentMaterial, false);
+
+ materials.AddOrUpdateCurrentMaterial(currentMaterial.uuid, currentMaterial, false);
+
return true;
}
@@ -127,14 +129,27 @@ public void Finish()
return;
}
+ Buffer buffer = new Buffer();
+ buffer.uri = string.Concat(preferences.fileName, ".bin");
+
+ if (preferences.materials == MaterialsEnum.textures)
+ {
+ GLTFBinaryDataUtils.ExportImageBuffer(images, bufferViews, globalBuffer);
+ }
+
if (preferences.grids)
{
RevitGrids.Export(currentDocument, ref nodes, ref rootNode, preferences);
}
+ buffer.byteLength = globalBuffer.GetCurrentByteOffset();
+ buffers.Add(buffer);
+
if (bufferViews.Count != 0)
{
- FileExport.Run(preferences, bufferViews, buffers, binaryFileData,
+ ProgressBarWindow.ViewModel.Message = "Saving to File";
+
+ FileExport.Run(preferences, bufferViews, buffers, globalBuffer,
scenes, nodes, meshes, materials, accessors, textures, images);
Compression.Run(preferences, ProgressBarWindow.ViewModel);
}
@@ -174,7 +189,6 @@ public RenderNodeAction OnElementBegin(ElementId elementId)
}
}
- currentNode = GLTFNodeActions.CreateGLTFNodeFromElement(currentElement, preferences);
currentGeometry.Reset();
currentVertices.Reset();
@@ -182,8 +196,6 @@ public RenderNodeAction OnElementBegin(ElementId elementId)
return RenderNodeAction.Proceed;
}
- const char UNDERSCORE = '_';
-
///
/// Runs at the end of an element being processed, after all other calls for that element.
/// Here we compile all the "_current" variables (geometry and vertices) onto glTF buffers.
@@ -199,76 +211,11 @@ public void OnElementEnd(ElementId elementId)
return;
}
- nodes.AddOrUpdateCurrent(currentElement.UniqueId, currentNode);
- rootNode.children.Add(nodes.CurrentIndex);
-
- GLTFMesh newMesh = new GLTFMesh
- {
- name = currentElement.Name,
- primitives = new List()
- };
- meshes.AddOrUpdateCurrent(currentElement.UniqueId, newMesh);
- nodes.CurrentItem.mesh = meshes.CurrentIndex;
-
- // Convert _currentGeometry objects into glTFMeshPrimitives
- foreach (KeyValuePair kvp in currentGeometry.Dict)
- {
- string material_key = kvp.Key.Split(UNDERSCORE)[1];
- GLTFMaterial mat = materials.GetElement(material_key);
-
- GLTFBinaryData elementBinary = GLTFExportUtils.AddGeometryMeta(
- buffers,
- accessors,
- bufferViews,
- kvp.Value,
- kvp.Key,
-#if REVIT2024 || REVIT2025 || REVIT2026
- elementId.Value,
-#else
- elementId.IntegerValue,
-#endif
- preferences,
- mat,
- images,
- textures);
-
- binaryFileData.Add(elementBinary);
-
+ ProcessGeometry.ProcessNode(nodes, rootNode, meshes, preferences,
+ globalBuffer, bufferViews, accessors, materials, currentGeometry, currentElement);
- GLTFMeshPrimitive primitive = new GLTFMeshPrimitive();
-
- primitive.attributes.POSITION = elementBinary.vertexAccessorIndex;
-
- if (preferences.normals)
- {
- primitive.attributes.NORMAL = elementBinary.normalsAccessorIndex;
- }
-
- if (preferences.batchId)
- {
- primitive.attributes._BATCHID = elementBinary.batchIdAccessorIndex;
- }
-
- if (elementBinary.uvAccessorIndex != -1 &&
- preferences.materials == MaterialsEnum.textures &&
- mat.EmbeddedTexturePath != null)
- {
- primitive.attributes.TEXCOORD_0 = elementBinary.uvAccessorIndex;
- }
-
- primitive.indices = elementBinary.indexAccessorIndex;
-
- if (preferences.materials == MaterialsEnum.materials || preferences.materials == MaterialsEnum.textures)
- {
- if (materials.Contains(material_key))
- {
- primitive.material = materials.GetIndexFromUUID(material_key);
- }
- }
-
- meshes.CurrentItem.primitives.Add(primitive);
- meshes.CurrentItem.name = currentElement.Name;
- }
+ currentGeometry.Reset();
+ currentVertices.Reset();
}
///
@@ -283,11 +230,11 @@ public void OnMaterial(MaterialNode node)
{
if (node.MaterialId == ElementId.InvalidElementId)
{
- currentMaterial = GLTFExportUtils.GetGLTFMaterial(materials, node.Transparency, false);
+ currentMaterial = GLTFExportUtils.GetGLTFMaterial(materials);
}
else
{
- currentMaterial = RevitMaterials.ProcessMaterial(node, preferences, currentDocument, materials);
+ currentMaterial = RevitMaterials.ProcessMaterial(node, preferences, currentDocument, materials, textures, images);
}
}
}
@@ -323,10 +270,14 @@ public void OnPolymesh(PolymeshTopology polymesh)
new PointIntObject(vertex), geomItem.Vertices);
geomItem.Faces.Add(vertexIndex);
- if (preferences.materials == MaterialsEnum.textures && currentMaterial?.EmbeddedTexturePath != null)
+ if (preferences.materials == MaterialsEnum.textures && currentMaterial.hasTexture)
{
UV uv = uvs[index];
- UV flippedUV = new UV(uv.U, 1.0 - uv.V);
+ GltfUV flippedUV = new GltfUV
+ {
+ U = (float)uv.U,
+ V = (float)(1.0 - uv.V)
+ };
geomItem.Uvs.Add(flippedUV);
}
}
@@ -431,7 +382,7 @@ public void OnRPC(RPCNode node)
if (preferences.materials == MaterialsEnum.materials || preferences.materials == MaterialsEnum.textures)
{
currentMaterial = MaterialUtils.GetGltfMeshMaterial(currentDocument, preferences, mesh, materials, true);
- materials.AddOrUpdateCurrentMaterial(currentMaterial.UniqueId, currentMaterial, true);
+ materials.AddOrUpdateCurrentMaterial(currentMaterial.name, currentMaterial, true);
}
GLTFExportUtils.AddOrUpdateCurrentItem(currentElement, currentGeometry, currentVertices, currentMaterial);
@@ -477,12 +428,10 @@ public void OnLight(LightNode node)
public RenderNodeAction OnFaceBegin(FaceNode node)
{
- currentFace = node.GetFace();
return RenderNodeAction.Proceed;
}
public void OnFaceEnd(FaceNode node)
{
- currentFace = null;
}
}
}
\ No newline at end of file
diff --git a/Common_glTF_Exporter/Core/IndexedDictionary.cs b/Common_glTF_Exporter/Core/IndexedDictionary.cs
index 3230c82..67f28b4 100644
--- a/Common_glTF_Exporter/Core/IndexedDictionary.cs
+++ b/Common_glTF_Exporter/Core/IndexedDictionary.cs
@@ -101,9 +101,9 @@ public bool AddOrUpdateCurrentMaterial(string uuid, T elem, bool doubleSided)
this.CurrentKey = uuid;
- if (elem is GLTFMaterial)
+ if (elem is glTF.Manipulator.Schema.Material)
{
- var mat = this.GetElement(uuid) as GLTFMaterial;
+ var mat = this.GetElement(uuid) as glTF.Manipulator.Schema.Material;
mat.doubleSided = doubleSided;
}
@@ -159,5 +159,23 @@ public void Reset()
this.Dict.Clear();
this.CurrentKey = string.Empty;
}
+
+ public IndexedDictionary Clone(Func cloneFunc)
+ {
+ var newDict = new IndexedDictionary();
+
+ foreach (var kv in this.dict)
+ {
+ string key = kv.Key;
+ int index = kv.Value;
+ T original = this.List[index];
+
+ T cloneItem = cloneFunc(original);
+
+ newDict.AddOrUpdateCurrent(key, cloneItem);
+ }
+
+ return newDict;
+ }
}
}
diff --git a/Common_glTF_Exporter/Core/ProcessGeometry.cs b/Common_glTF_Exporter/Core/ProcessGeometry.cs
new file mode 100644
index 0000000..9981552
--- /dev/null
+++ b/Common_glTF_Exporter/Core/ProcessGeometry.cs
@@ -0,0 +1,105 @@
+using Autodesk.Revit.DB;
+using Common_glTF_Exporter.Model;
+using Common_glTF_Exporter.Utils;
+using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
+using Revit_glTF_Exporter;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace Common_glTF_Exporter.Core
+{
+ public static class ProcessGeometry
+ {
+ public static void ProcessNode(IndexedDictionary nodes, Node rootNode, IndexedDictionary meshes,
+ Preferences preferences, GLTFBinaryData globalBuffer, List bufferViews, List accessors, IndexedDictionary materials,
+ IndexedDictionary dataObject, Element currentElement)
+ {
+
+ Extras extras = new Extras();
+
+ if (preferences.properties)
+ {
+ var parameters = Util.GetElementParameters(currentElement, true);
+ parameters["UniqueId"] = currentElement.UniqueId;
+
+ if (currentElement.Category != null)
+ parameters["Category"] = currentElement.Category.Name;
+
+ extras.parameters = parameters;
+ }
+
+ Node newNode = new Node()
+ {
+ name = Util.ElementDescription(currentElement),
+ extras = extras
+ };
+
+ long elmId;
+
+ #if REVIT2024 || REVIT2025 || REVIT2026
+ elmId = currentElement.Id.Value;
+ #else
+ elmId = currentElement.Id.IntegerValue;
+ #endif
+
+ nodes.AddOrUpdateCurrent(currentElement.UniqueId, newNode);
+ rootNode.children.Add(nodes.CurrentIndex);
+
+ glTF.Manipulator.Schema.Mesh newMesh = new glTF.Manipulator.Schema.Mesh
+ {
+ name = currentElement.Name,
+ primitives = new List()
+ };
+
+ meshes.AddOrUpdateCurrent(currentElement.UniqueId, newMesh);
+ nodes.CurrentItem.mesh = meshes.CurrentIndex;
+
+ foreach (KeyValuePair kvp in dataObject.Dict)
+ {
+ MeshPrimitive primitive = new MeshPrimitive();
+ GLTFBinaryData gLTFBinaryDataElement = globalBuffer;
+
+ if (preferences.materials == MaterialsEnum.textures)
+ {
+ GLTFBinaryDataUtils.ExportUVs(kvp.Value, gLTFBinaryDataElement, bufferViews, accessors, primitive);
+ }
+
+ GLTFBinaryDataUtils.ExportVertices(kvp.Value, gLTFBinaryDataElement, bufferViews, accessors, primitive);
+
+ if (preferences.normals)
+ {
+ GLTFBinaryDataUtils.ExportNormals(kvp.Value, gLTFBinaryDataElement, bufferViews, accessors, primitive);
+ }
+
+ if (preferences.batchId)
+ {
+ GLTFBinaryDataUtils.ExportBatchId(elmId, kvp.Value, gLTFBinaryDataElement, bufferViews, accessors, primitive);
+ }
+
+ int indexAcessor = GLTFBinaryDataUtils.ExportFaces(kvp.Value, gLTFBinaryDataElement, bufferViews, accessors);
+
+ primitive.indices = indexAcessor;
+
+ if (preferences.materials != MaterialsEnum.nonematerials)
+ {
+ primitive.material = materials.GetIndexFromUUID(kvp.Value.MaterialInfo.uuid);
+ }
+
+ meshes.CurrentItem.primitives.Add(primitive);
+ meshes.CurrentItem.name = currentElement.Name;
+
+ var g = kvp.Value;
+ g.Vertices.Clear();
+ g.Normals.Clear();
+ g.Uvs.Clear();
+ g.Faces.Clear();
+ }
+ }
+ }
+}
diff --git a/Common_glTF_Exporter/Core/glTF.cs b/Common_glTF_Exporter/Core/glTF.cs
deleted file mode 100644
index 9b04486..0000000
--- a/Common_glTF_Exporter/Core/glTF.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-namespace Revit_glTF_Exporter
-{
- using System.Collections.Generic;
- using Common_glTF_Exporter.Core;
-
- ///
- /// Magic numbers to differentiate scalar and vector array buffers
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#buffers-and-buffer-views.
- ///
- public enum Targets
- {
- NONE = 0,
- ARRAY_BUFFER = 34962, // signals vertex data
- ELEMENT_ARRAY_BUFFER = 34963, // signals index or face data
- }
-
- ///
- /// Magic numbers to differentiate array buffer component types
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#accessor-element-size.
- ///
- public enum ComponentType
- {
- BYTE = 5120,
- UNSIGNED_BYTE = 5121,
- SHORT = 5122,
- UNSIGNED_SHORT = 5123,
- UNSIGNED_INT = 5125,
- FLOAT = 5126,
- }
-
- ///
- /// The json serializable glTF file format
- /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0.
- ///
- public struct GLTF
- {
- public GLTFVersion asset;
- public List extensionsUsed;
- public List scenes;
- public List nodes;
- public List meshes;
- public List buffers;
- public List bufferViews;
- public List accessors;
- public List materials;
- public List textures;
- public List images;
- }
-}
diff --git a/Common_glTF_Exporter/Core/glTFPBR.cs b/Common_glTF_Exporter/Core/glTFPBR.cs
deleted file mode 100644
index d7606e9..0000000
--- a/Common_glTF_Exporter/Core/glTFPBR.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Common_glTF_Exporter.Core
-{
- using System.Collections.Generic;
-
- public class GLTFPBR
- {
- public List baseColorFactor { get; set; }
-
- public float metallicFactor { get; set; }
-
- public float roughnessFactor { get; set; }
-
- // Texture properties
- public GLTFTextureInfo baseColorTexture { get; set; }
- public GLTFTexture metallicRoughnessTexture { get; set; }
- }
-}
diff --git a/Common_glTF_Exporter/EportUtils/ElementValidations.cs b/Common_glTF_Exporter/EportUtils/ElementValidations.cs
index b12dbe8..cbd79d2 100644
--- a/Common_glTF_Exporter/EportUtils/ElementValidations.cs
+++ b/Common_glTF_Exporter/EportUtils/ElementValidations.cs
@@ -1,24 +1,25 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
-using Autodesk.Revit.DB;
+using Autodesk.Revit.DB;
+using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.EportUtils;
using Common_glTF_Exporter.Export;
using Common_glTF_Exporter.Model;
using Common_glTF_Exporter.Transform;
using Common_glTF_Exporter.Utils;
using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.Schema;
using Revit_glTF_Exporter;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
using Transform = Autodesk.Revit.DB.Transform;
-using Common_glTF_Exporter.EportUtils;
-using Common_glTF_Exporter.Core;
namespace Common_glTF_Exporter.EportUtils
{
public static class ElementValidations
{
public static bool ShouldSkipElement(Element currentElement, Autodesk.Revit.DB.View currentView,
- Document currentDocument, Preferences preferences, IndexedDictionary nodes)
+ Document currentDocument, Preferences preferences, IndexedDictionary nodes)
{
if (currentElement == null)
{
diff --git a/Common_glTF_Exporter/EportUtils/GLTFNodeActions.cs b/Common_glTF_Exporter/EportUtils/GLTFNodeActions.cs
deleted file mode 100644
index 28f2586..0000000
--- a/Common_glTF_Exporter/EportUtils/GLTFNodeActions.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Autodesk.Revit.DB;
-using Revit_glTF_Exporter;
-using Common_glTF_Exporter.Core;
-using Common_glTF_Exporter.Windows.MainWindow;
-
-namespace Common_glTF_Exporter.EportUtils
-{
- public static class GLTFNodeActions
- {
- public static GLTFNode CreateGLTFNodeFromElement(Element currentElement, Preferences preferences)
- {
- // create a new node for the element
- GLTFNode newNode = new GLTFNode();
- newNode.name = Util.ElementDescription(currentElement);
-
- if (preferences.properties)
- {
- // get the extras for this element
- GLTFExtras extras = new GLTFExtras
- {
- uniqueId = currentElement.UniqueId,
- parameters = Util.GetElementParameters(currentElement, true)
- };
-
- if (currentElement.Category != null)
- {
- extras.elementCategory = currentElement.Category.Name;
- }
-
-#if REVIT2024 || REVIT2025 || REVIT2026
- extras.elementId = currentElement.Id.Value;
-#else
- extras.elementId = currentElement.Id.IntegerValue;
-#endif
-
- newNode.extras = extras;
- }
-
- return newNode;
- }
- }
-}
diff --git a/Common_glTF_Exporter/Export/BinFile.cs b/Common_glTF_Exporter/Export/BinFile.cs
index 9c242a8..7f0fa6e 100644
--- a/Common_glTF_Exporter/Export/BinFile.cs
+++ b/Common_glTF_Exporter/Export/BinFile.cs
@@ -1,74 +1,26 @@
-namespace Common_glTF_Exporter.Export
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using Common_glTF_Exporter.Core;
- using Common_glTF_Exporter.Windows.MainWindow;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.GenericSchema;
- public static class BinFile
+public static class BinFile
+{
+ ///
+ /// Create a new .bin file using the optimized GLTFBinaryData.
+ ///
+ public static void Create(string filename, GLTFBinaryData globalBuffer)
{
- ///
- /// Create a new .bin file.
- ///
- /// .bin file name.
- /// binary file data.
- /// export normals.
- /// export BatchId.
- public static void Create(string filename, List binaryFileData,
- Preferences preferences)
- {
- using (FileStream f = File.Create(filename))
- using (var writer = new BinaryWriter(new BufferedStream(f), Encoding.UTF8))
- {
- foreach (var bin in binaryFileData)
- {
- for (int i = 0; i < bin.vertexBuffer.Count; i++)
- {
- writer.Write((float)bin.vertexBuffer[i]);
- }
-
- if (preferences.normals)
- {
- for (int i = 0; i < bin.normalBuffer.Count; i++)
- {
- writer.Write((float)bin.normalBuffer[i]);
- }
- }
-
- if (preferences.materials == MaterialsEnum.textures)
- {
- if (bin.byteData != null)
- {
- writer.Write((byte[])bin.byteData);
- }
+ // Obtiene los bytes finales del MemoryStream
+ byte[] data = globalBuffer.ToArray();
- if (bin.uvBuffer != null && bin.uvBuffer.Count > 0)
- {
- for (int i = 0; i < bin.uvBuffer.Count; i++)
- {
- writer.Write((float)bin.uvBuffer[i]);
- }
- }
- }
-
- if (preferences.batchId)
- {
- for (int i = 0; i < bin.batchIdBuffer.Count; i++)
- {
- writer.Write((float)bin.batchIdBuffer[i]);
- }
- }
-
- for (int i = 0; i < bin.indexBuffer.Count; i++)
- {
- writer.Write((int)bin.indexBuffer[i]);
- }
- }
-
- writer.Flush();
- }
+ using (FileStream f = File.Create(filename))
+ using (var writer = new BinaryWriter(new BufferedStream(f)))
+ {
+ writer.Write(data);
+ writer.Flush();
}
}
}
diff --git a/Common_glTF_Exporter/Export/BufferConfig.cs b/Common_glTF_Exporter/Export/BufferConfig.cs
index 403d412..9680694 100644
--- a/Common_glTF_Exporter/Export/BufferConfig.cs
+++ b/Common_glTF_Exporter/Export/BufferConfig.cs
@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
-using System.Text;
using Common_glTF_Exporter.Core;
using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.Schema;
+using Buffer = glTF.Manipulator.Schema.Buffer;
namespace Common_glTF_Exporter.Export
{
@@ -10,7 +11,7 @@ public static class BufferConfig
{
const string BIN = ".bin";
- public static void Run(List bufferViews, List buffers,
+ public static void Run(List bufferViews, List buffers,
Preferences preferences)
{
int bytePosition = 0;
@@ -32,7 +33,7 @@ public static void Run(List bufferViews, List buffer
}
}
- GLTFBuffer buffer = new GLTFBuffer();
+ Buffer buffer = new Buffer();
if (preferences.format == FormatEnum.gltf)
{
diff --git a/Common_glTF_Exporter/Export/Draco.cs b/Common_glTF_Exporter/Export/Draco.cs
index ca070db..1ec10ff 100644
--- a/Common_glTF_Exporter/Export/Draco.cs
+++ b/Common_glTF_Exporter/Export/Draco.cs
@@ -1,21 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Nodes;
using Common_glTF_Exporter.Model;
using Common_glTF_Exporter.Windows.MainWindow;
using dracowrapper;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
namespace Common_glTF_Exporter.Export
{
-
internal sealed class GlbData
{
public string Json;
public byte[] Bin;
+
public GlbData(string json, byte[] bin)
{
Json = json;
@@ -25,12 +24,21 @@ public GlbData(string json, byte[] bin)
internal static class GltfExtrasPatcher
{
+
+ private static JsonNode DeepClone(JsonNode node)
+ {
+ if (node == null) return null;
+
+ string json = node.ToJsonString(new JsonSerializerOptions { WriteIndented = false });
+ return JsonNode.Parse(json);
+ }
+
public static void PatchExtras(string originalPath, string tempPath)
{
if (string.IsNullOrEmpty(originalPath) || string.IsNullOrEmpty(tempPath))
throw new ArgumentNullException();
- string ext = (Path.GetExtension(originalPath) ?? "").ToLowerInvariant();
+ string ext = (Path.GetExtension(originalPath) ?? string.Empty).ToLowerInvariant();
if (ext == ".gltf")
{
PatchExtrasGltf(originalPath, tempPath);
@@ -43,15 +51,15 @@ public static void PatchExtras(string originalPath, string tempPath)
private static void PatchExtrasGltf(string originalGltf, string tempGltf)
{
- JObject src = JObject.Parse(File.ReadAllText(originalGltf));
- JObject dst = JObject.Parse(File.ReadAllText(tempGltf));
+ JsonObject src = JsonNode.Parse(File.ReadAllText(originalGltf)).AsObject();
+ JsonObject dst = JsonNode.Parse(File.ReadAllText(tempGltf)).AsObject();
PatchArrayByIndex(src, dst, "nodes", PatchNodeLike);
MergeExtensionsUsedAndRequired(src, dst);
string baseDir = Path.GetDirectoryName(tempGltf);
- string tempBinFileName = Path.GetFileName(tempGltf).Replace(".gltf", ".bin"); // ej: MyModelTemp.bin
+ string tempBinFileName = Path.GetFileName(tempGltf).Replace(".gltf", ".bin");
byte[] binBytes = null;
InlineExternalImagesIntoBin_JObject(dst, baseDir, tempBinFileName, ref binBytes, false, true);
@@ -62,7 +70,8 @@ private static void PatchExtrasGltf(string originalGltf, string tempGltf)
File.WriteAllBytes(binPath, binBytes);
}
- File.WriteAllText(tempGltf, dst.ToString(Formatting.None));
+ string jsonOut = dst.ToJsonString(new JsonSerializerOptions { WriteIndented = false });
+ File.WriteAllText(tempGltf, jsonOut);
}
private static void PatchExtrasGlb(string originalGlb, string tempGlb)
@@ -70,128 +79,235 @@ private static void PatchExtrasGlb(string originalGlb, string tempGlb)
GlbData srcGlb = ReadGlb(originalGlb);
GlbData dstGlb = ReadGlb(tempGlb);
- JObject src = JObject.Parse(srcGlb.Json);
- JObject dst = JObject.Parse(dstGlb.Json);
+ JsonObject src = JsonNode.Parse(srcGlb.Json).AsObject();
+ JsonObject dst = JsonNode.Parse(dstGlb.Json).AsObject();
PatchArrayByIndex(src, dst, "nodes", PatchNodeLike);
-
MergeExtensionsUsedAndRequired(src, dst);
byte[] glbBin = dstGlb.Bin;
string baseDir = Path.GetDirectoryName(tempGlb);
InlineExternalImagesIntoBin_JObject(dst, baseDir, null, ref glbBin, true, true);
- string newJson = dst.ToString(Formatting.None);
- WriteGlb(tempGlb, newJson, glbBin);
+ string newJson = dst.ToJsonString(new JsonSerializerOptions { WriteIndented = false });
+ WriteGlb(tempGlb, newJson, glbBin);
}
- private static void PatchNodeLike(JObject srcNode, JObject dstNode)
+ private static void PatchNodeLike(JsonObject srcNode, JsonObject dstNode)
{
CopyExtras(srcNode, dstNode);
CopyUnknownExtensions(srcNode, dstNode, new[] { "KHR_draco_mesh_compression" });
}
- private static void PatchArrayByIndex(JObject src, JObject dst, string name, Action patchItem)
+ private static void PatchArrayByIndex(JsonObject src, JsonObject dst, string name, Action patchItem)
{
- JArray sa = src[name] as JArray;
- JArray da = dst[name] as JArray;
+ JsonNode saNode = src[name];
+ JsonNode daNode = dst[name];
+
+ JsonArray sa = saNode as JsonArray;
+ JsonArray da = daNode as JsonArray;
+
if (sa == null || da == null) return;
int count = Math.Min(sa.Count, da.Count);
for (int i = 0; i < count; i++)
- patchItem((JObject)sa[i], (JObject)da[i]);
+ {
+ JsonObject sItem = sa[i] as JsonObject;
+ JsonObject dItem = da[i] as JsonObject;
+ if (sItem == null || dItem == null) continue;
+
+ patchItem(sItem, dItem);
+ }
}
- private static void CopyExtras(JObject src, JObject dst)
+ private static void CopyExtras(JsonObject src, JsonObject dst)
{
- if (src["extras"] != null)
- dst["extras"] = src["extras"].DeepClone();
+ JsonNode extras;
+ if (src.TryGetPropertyValue("extras", out extras) && extras != null)
+ {
+ dst["extras"] = DeepClone(extras);
+ }
}
- private static void CopyUnknownExtensions(JObject src, JObject dst, IEnumerable keepKnown)
+ private static void CopyUnknownExtensions(JsonObject src, JsonObject dst, IEnumerable keepKnown)
{
- JObject sExt = src["extensions"] as JObject;
+ JsonNode sExtNode;
+ if (!src.TryGetPropertyValue("extensions", out sExtNode)) return;
+
+ JsonObject sExt = sExtNode as JsonObject;
if (sExt == null) return;
- JObject dExt = dst["extensions"] as JObject;
- if (dExt == null) dExt = new JObject();
+ JsonNode dExtNode;
+ JsonObject dExt = null;
+ if (dst.TryGetPropertyValue("extensions", out dExtNode) && dExtNode is JsonObject)
+ {
+ dExt = (JsonObject)dExtNode;
+ }
+ else
+ {
+ dExt = new JsonObject();
+ }
HashSet known = new HashSet(keepKnown ?? new string[0], StringComparer.Ordinal);
- foreach (JProperty prop in sExt.Properties())
+ foreach (KeyValuePair kvp in sExt)
{
- if (known.Contains(prop.Name) && dExt[prop.Name] != null) continue;
+ string name = kvp.Key;
+ JsonNode value = kvp.Value;
+ if (value == null) continue;
+
+ if (known.Contains(name) && dExt.ContainsKey(name)) continue;
- dExt[prop.Name] = prop.Value.DeepClone();
+ dExt[name] = DeepClone(value);
}
- if (dExt.HasValues)
+ if (dExt.Count > 0)
dst["extensions"] = dExt;
}
- private static void MergeExtensionsUsedAndRequired(JObject src, JObject dst)
+ private static void MergeExtensionsUsedAndRequired(JsonObject src, JsonObject dst)
{
- JArray srcUsed = src["extensionsUsed"] as JArray;
+ JsonArray srcUsed = null;
+ JsonNode srcUsedNode;
+ if (src.TryGetPropertyValue("extensionsUsed", out srcUsedNode))
+ srcUsed = srcUsedNode as JsonArray;
+
if (srcUsed != null && srcUsed.Count > 0)
{
- JArray dstUsed = dst["extensionsUsed"] as JArray;
- if (dstUsed == null) { dstUsed = new JArray(); dst["extensionsUsed"] = dstUsed; }
+ JsonArray dstUsed = null;
+ JsonNode dstUsedNode;
+ if (dst.TryGetPropertyValue("extensionsUsed", out dstUsedNode) && dstUsedNode is JsonArray)
+ {
+ dstUsed = (JsonArray)dstUsedNode;
+ }
+ else
+ {
+ dstUsed = new JsonArray();
+ dst["extensionsUsed"] = dstUsed;
+ }
- var set = new HashSet(StringComparer.Ordinal);
- foreach (var t in dstUsed) set.Add((string)t);
+ HashSet set = new HashSet(StringComparer.Ordinal);
+ foreach (JsonNode t in dstUsed)
+ {
+ if (t == null) continue;
+ set.Add(t.GetValue());
+ }
- foreach (var t in srcUsed)
+ foreach (JsonNode t in srcUsed)
{
- string name = (string)t;
- if (!set.Contains(name)) { dstUsed.Add(name); set.Add(name); }
+ if (t == null) continue;
+ string name = t.GetValue();
+ if (!set.Contains(name))
+ {
+ dstUsed.Add(name);
+ set.Add(name);
+ }
}
}
- JArray srcReq = src["extensionsRequired"] as JArray;
+ JsonArray srcReq = null;
+ JsonNode srcReqNode;
+ if (src.TryGetPropertyValue("extensionsRequired", out srcReqNode))
+ srcReq = srcReqNode as JsonArray;
+
if (srcReq != null && srcReq.Count > 0)
{
- JArray dstReq = dst["extensionsRequired"] as JArray;
- if (dstReq == null) { dstReq = new JArray(); dst["extensionsRequired"] = dstReq; }
+ JsonArray dstReq = null;
+ JsonNode dstReqNode;
+ if (dst.TryGetPropertyValue("extensionsRequired", out dstReqNode) && dstReqNode is JsonArray)
+ {
+ dstReq = (JsonArray)dstReqNode;
+ }
+ else
+ {
+ dstReq = new JsonArray();
+ dst["extensionsRequired"] = dstReq;
+ }
- var setR = new HashSet(StringComparer.Ordinal);
- foreach (var t in dstReq) setR.Add((string)t);
+ HashSet setR = new HashSet(StringComparer.Ordinal);
+ foreach (JsonNode t in dstReq)
+ {
+ if (t == null) continue;
+ setR.Add(t.GetValue());
+ }
- foreach (var t in srcReq)
+ foreach (JsonNode t in srcReq)
{
- string name = (string)t;
- if (!setR.Contains(name)) { dstReq.Add(name); setR.Add(name); }
+ if (t == null) continue;
+ string name = t.GetValue();
+ if (!setR.Contains(name))
+ {
+ dstReq.Add(name);
+ setR.Add(name);
+ }
}
}
- // asegurar Draco en extensionsUsed
EnsureExtInArray(dst, "extensionsUsed", "KHR_draco_mesh_compression");
}
- private static void EnsureExtInArray(JObject dst, string arrayName, string ext)
+ private static void EnsureExtInArray(JsonObject dst, string arrayName, string ext)
{
- JArray arr = dst[arrayName] as JArray;
- if (arr == null) { arr = new JArray(); dst[arrayName] = arr; }
- foreach (var t in arr) if (string.Equals((string)t, ext, StringComparison.Ordinal)) return;
+ JsonArray arr = null;
+ JsonNode arrNode;
+
+ if (dst.TryGetPropertyValue(arrayName, out arrNode) && arrNode is JsonArray)
+ {
+ arr = (JsonArray)arrNode;
+ }
+ else
+ {
+ arr = new JsonArray();
+ dst[arrayName] = arr;
+ }
+
+ foreach (JsonNode t in arr)
+ {
+ if (t == null) continue;
+ if (string.Equals(t.GetValue(), ext, StringComparison.Ordinal))
+ return;
+ }
+
arr.Add(ext);
}
private static void InlineExternalImagesIntoBin_JObject(
- JObject model,
+ JsonObject model,
string baseDir,
string desiredBinFileName,
ref byte[] binBytes,
bool isGlb,
bool removeExternalImageFiles)
{
- var buffers = model["buffers"] as JArray;
- if (buffers == null) { buffers = new JArray(); model["buffers"] = buffers; }
- if (buffers.Count == 0) buffers.Add(new JObject { ["byteLength"] = 0 });
+ // buffers
+ JsonArray buffers = model["buffers"] as JsonArray;
+ if (buffers == null)
+ {
+ buffers = new JsonArray();
+ model["buffers"] = buffers;
+ }
+ if (buffers.Count == 0)
+ {
+ JsonObject bufObj = new JsonObject();
+ bufObj["byteLength"] = 0;
+ buffers.Add(bufObj);
+ }
- var bufferViews = model["bufferViews"] as JArray;
- if (bufferViews == null) { bufferViews = new JArray(); model["bufferViews"] = bufferViews; }
+ // bufferViews
+ JsonArray bufferViews = model["bufferViews"] as JsonArray;
+ if (bufferViews == null)
+ {
+ bufferViews = new JsonArray();
+ model["bufferViews"] = bufferViews;
+ }
- var buf0 = (JObject)buffers[0];
+ JsonObject buf0 = buffers[0] as JsonObject;
+ if (buf0 == null)
+ {
+ buf0 = new JsonObject();
+ buffers[0] = buf0;
+ }
if (!isGlb)
{
@@ -204,20 +320,22 @@ private static void InlineExternalImagesIntoBin_JObject(
}
int appendOffset = binBytes != null ? binBytes.Length : 0;
- var images = model["images"] as JArray;
- var consumedFiles = new HashSet(StringComparer.OrdinalIgnoreCase);
+ JsonArray images = model["images"] as JsonArray;
+ HashSet consumedFiles = new HashSet(StringComparer.OrdinalIgnoreCase);
if (images != null && images.Count > 0)
{
for (int i = 0; i < images.Count; i++)
{
- var img = images[i] as JObject;
+ JsonObject img = images[i] as JsonObject;
if (img == null) continue;
- if (img["bufferView"] != null) continue; // ya embebida
- string uri = (string)img["uri"];
+ if (img["bufferView"] != null) continue;
+
+ JsonNode uriNode = img["uri"];
+ string uri = uriNode != null ? uriNode.GetValue() : null;
if (string.IsNullOrEmpty(uri)) continue;
- if (uri.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) continue; // data URI
+ if (uri.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) continue;
string imgPath = Path.Combine(baseDir, uri);
if (!File.Exists(imgPath)) continue;
@@ -231,17 +349,16 @@ private static void InlineExternalImagesIntoBin_JObject(
appendOffset = binBytes.Length;
int bvIndex = bufferViews.Count;
- var bv = new JObject
- {
- ["buffer"] = 0,
- ["byteOffset"] = thisOffset,
- ["byteLength"] = thisLength
- };
+ JsonObject bv = new JsonObject();
+ bv["buffer"] = 0;
+ bv["byteOffset"] = thisOffset;
+ bv["byteLength"] = thisLength;
bufferViews.Add(bv);
img.Remove("uri");
img["bufferView"] = bvIndex;
- if (!string.IsNullOrEmpty(mime)) img["mimeType"] = mime;
+ if (!string.IsNullOrEmpty(mime))
+ img["mimeType"] = mime;
if (removeExternalImageFiles)
consumedFiles.Add(imgPath);
@@ -250,19 +367,24 @@ private static void InlineExternalImagesIntoBin_JObject(
buf0["byteLength"] = binBytes != null ? binBytes.Length : 0;
- // Eliminar los archivos externos que incrustamos
if (removeExternalImageFiles && consumedFiles.Count > 0)
{
- foreach (var path in consumedFiles)
+ foreach (string path in consumedFiles)
{
- try { if (File.Exists(path)) File.Delete(path); } catch { /* swallow */ }
+ try
+ {
+ if (File.Exists(path)) File.Delete(path);
+ }
+ catch
+ {
+ }
}
}
}
private static string MimeFromExtension(string ext)
{
- ext = (ext ?? "").ToLowerInvariant();
+ ext = (ext ?? string.Empty).ToLowerInvariant();
if (ext == ".png") return "image/png";
if (ext == ".jpg" || ext == ".jpeg") return "image/jpeg";
if (ext == ".ktx2") return "image/ktx2";
@@ -273,10 +395,14 @@ private static byte[] AppendBytes(byte[] bin, byte[] add, bool padTo4, byte padB
{
if (bin == null) bin = new byte[0];
int oldLen = bin.Length;
- int newLen = oldLen + (add != null ? add.Length : 0);
+ int addLen = (add != null ? add.Length : 0);
+ int newLen = oldLen + addLen;
+
byte[] outArr = new byte[newLen];
- if (oldLen > 0) Buffer.BlockCopy(bin, 0, outArr, 0, oldLen);
- if (add != null && add.Length > 0) Buffer.BlockCopy(add, 0, outArr, oldLen, add.Length);
+ if (oldLen > 0)
+ Buffer.BlockCopy(bin, 0, outArr, 0, oldLen);
+ if (add != null && add.Length > 0)
+ Buffer.BlockCopy(add, 0, outArr, oldLen, add.Length);
if (padTo4)
{
@@ -286,10 +412,12 @@ private static byte[] AppendBytes(byte[] bin, byte[] add, bool padTo4, byte padB
int pad = 4 - mod;
byte[] padded = new byte[outArr.Length + pad];
Buffer.BlockCopy(outArr, 0, padded, 0, outArr.Length);
- for (int i = 0; i < pad; i++) padded[outArr.Length + i] = padByte;
+ for (int i = 0; i < pad; i++)
+ padded[outArr.Length + i] = padByte;
return padded;
}
}
+
return outArr;
}
@@ -324,7 +452,7 @@ private static GlbData ReadGlb(string path)
private static void WriteGlb(string path, string json, byte[] bin)
{
byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(json);
- jsonBytes = PadTo4(jsonBytes, 0x20); // espacios
+ jsonBytes = PadTo4(jsonBytes, 0x20);
byte[] binBytes = (bin ?? new byte[0]);
binBytes = PadTo4(binBytes, 0x00);
@@ -371,6 +499,7 @@ private static byte[] PadTo4(byte[] data, byte padByte)
return outArr;
}
}
+
public static class Draco
{
public static void Compress(Preferences preferences)
@@ -432,23 +561,29 @@ public static void Compress(Preferences preferences)
GltfExtrasPatcher.PatchExtras(fileToCompress, fileToCompressTemp);
- foreach (var x in files)
+ foreach (string x in files)
{
- try { if (File.Exists(x)) File.Delete(x); } catch { /* ignore */ }
+ try
+ {
+ if (File.Exists(x)) File.Delete(x);
+ }
+ catch
+ {
+ // ignore
+ }
}
File_MoveOverwrite(fileToCompressTemp, fileToCompress);
if (preferences.format == FormatEnum.gltf)
{
- string binTemp = fileToCompressTemp.Replace(".gltf", ".bin");
- string binFinal = fileToCompressTemp.Replace("Temp.gltf", ".bin");
+ string binTemp = fileToCompressTemp.Replace(".gltf", ".bin");
+ string binFinal = preferences.path + ".bin";
if (File.Exists(binTemp))
{
File_MoveOverwrite(binTemp, binFinal);
}
-
if (File.Exists(fileToCompress))
{
string text = File.ReadAllText(fileToCompress);
@@ -463,12 +598,12 @@ public static void Compress(Preferences preferences)
}
}
-
private static void File_MoveOverwrite(string src, string dst)
{
if (File.Exists(dst))
{
- try { File.Delete(dst); } catch { /* ignore */ }
+ try { File.Delete(dst); }
+ catch { /* ignore */ }
}
File.Move(src, dst);
}
diff --git a/Common_glTF_Exporter/Export/FileExport.cs b/Common_glTF_Exporter/Export/FileExport.cs
index 522d7d0..6d05dc5 100644
--- a/Common_glTF_Exporter/Export/FileExport.cs
+++ b/Common_glTF_Exporter/Export/FileExport.cs
@@ -1,13 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using Autodesk.Revit.DB;
+using Autodesk.Revit.DB;
using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.Model;
using Common_glTF_Exporter.Windows.MainWindow;
-using Newtonsoft.Json;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
using Revit_glTF_Exporter;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Buffer = glTF.Manipulator.Schema.Buffer;
+using Material = glTF.Manipulator.Schema.Material;
namespace Common_glTF_Exporter.Export
{
@@ -18,21 +20,22 @@ public static class FileExport
public static void Run(
Preferences preferences,
- List bufferViews,
- List buffers,
- List binaryFileData, List scenes,
- IndexedDictionary nodes,
- IndexedDictionary meshes,
- IndexedDictionary materials,
- List accessors,
- List textures,
- List images)
+ List bufferViews,
+ List buffers,
+ GLTFBinaryData binaryFileData,
+ List scenes,
+ IndexedDictionary nodes,
+ IndexedDictionary meshes,
+ IndexedDictionary materials,
+ List accessors,
+ List textures,
+ List images)
{
if (preferences.format == FormatEnum.gltf)
{
BufferConfig.Run(bufferViews, buffers, preferences);
string fileDirectory = string.Concat(preferences.path, BIN);
- BinFile.Create(fileDirectory, binaryFileData, preferences);
+ BinFile.Create(fileDirectory, binaryFileData);
string gltfJson = GltfJson.Get(scenes, nodes.List, meshes.List, materials.List, buffers,
bufferViews, accessors, textures, images, preferences);
diff --git a/Common_glTF_Exporter/Export/GlbBinInfo.cs b/Common_glTF_Exporter/Export/GlbBinInfo.cs
index 33a469f..2dffdcc 100644
--- a/Common_glTF_Exporter/Export/GlbBinInfo.cs
+++ b/Common_glTF_Exporter/Export/GlbBinInfo.cs
@@ -1,89 +1,41 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Autodesk.Revit.DB.Visual;
-using Common_glTF_Exporter.Core;
using Common_glTF_Exporter.Model;
-using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.GenericSchema;
namespace Common_glTF_Exporter.Export
{
public static class GlbBinInfo
{
- public static byte[] Get(List binaryFileData, Preferences preferences)
+ public static byte[] Get(GLTFBinaryData globalBuffer)
{
- List binData = new List();
-
- foreach (var bin in binaryFileData)
- {
- foreach (var coord in bin.vertexBuffer)
- {
- List vertex = BitConverter.GetBytes((float)coord).ToList();
- binData.AddRange(vertex);
- }
-
- if (preferences.normals)
- {
- foreach (var normal in bin.normalBuffer)
- {
- List normalBuffer = BitConverter.GetBytes((float)normal).ToList();
- binData.AddRange(normalBuffer);
- }
- }
+ GlbBin glbBin = new GlbBin();
- if (preferences.materials == MaterialsEnum.textures)
- {
- if (bin.byteData != null)
- {
- binData.AddRange(bin.byteData);
- }
+ // Usar MemoryStream → ToArray()
+ glbBin.ChunkData = globalBuffer.ToArray();
- if (bin.uvBuffer != null && bin.uvBuffer.Count > 0)
- {
- foreach (var uv in bin.uvBuffer)
- {
- List uvBytes = BitConverter.GetBytes((float)uv).ToList();
- binData.AddRange(uvBytes);
- }
- }
- }
+ // Length del chunk BIN
+ glbBin.Length = BitConverter.GetBytes((uint)glbBin.ChunkData.Length);
- if (preferences.batchId)
- {
- foreach (var batchId in bin.batchIdBuffer)
- {
- List batchIdBuffer = BitConverter.GetBytes((float)batchId).ToList();
- binData.AddRange(batchIdBuffer);
- }
- }
+ // 📌 Construcción del chunk final:
+ // [byteLength][CHUNK_TYPE][binary data]
+ byte[] result = new byte[
+ glbBin.Length.Length
+ + glbBin.ChunkType().Length
+ + glbBin.ChunkData.Length];
- foreach (var index in bin.indexBuffer)
- {
- List indexIdBuffer = BitConverter.GetBytes((int)index).ToList();
- binData.AddRange(indexIdBuffer);
- }
- }
+ int offset = 0;
- if (binData.Count % 4 != 0)
- {
- int missingNumbers = 4 - (binData.Count % 4);
- for (int i = 0; i < missingNumbers; i++)
- {
- byte emptyByte = (byte)00;
- List zeros = new List { emptyByte };
- binData.AddRange(zeros);
- }
- }
+ // Copiar chunk length
+ Buffer.BlockCopy(glbBin.Length, 0, result, offset, glbBin.Length.Length);
+ offset += glbBin.Length.Length;
- GlbBin glbBin = new GlbBin();
- glbBin.ChunkData = binData.ToArray();
- glbBin.Length = BitConverter.GetBytes(Convert.ToUInt32(glbBin.ChunkData.Length));
+ // Copiar chunk type
+ byte[] type = glbBin.ChunkType();
+ Buffer.BlockCopy(type, 0, result, offset, type.Length);
+ offset += type.Length;
- byte[] result = new byte[] { };
- result = result.Concat(glbBin.Length).ToArray();
- result = result.Concat(glbBin.ChunkType()).ToArray();
- result = result.Concat(glbBin.ChunkData).ToArray();
+ // Copiar datos binarios
+ Buffer.BlockCopy(glbBin.ChunkData, 0, result, offset, glbBin.ChunkData.Length);
return result;
}
diff --git a/Common_glTF_Exporter/Export/GlbFile.cs b/Common_glTF_Exporter/Export/GlbFile.cs
index b86d25e..7ad56b9 100644
--- a/Common_glTF_Exporter/Export/GlbFile.cs
+++ b/Common_glTF_Exporter/Export/GlbFile.cs
@@ -6,16 +6,17 @@
using System.Windows.Forms;
using Common_glTF_Exporter.Core;
using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.GenericSchema;
namespace Common_glTF_Exporter.Export
{
internal class GlbFile
{
- public static void Create(Preferences preferences, List binaryFileData, string json)
+ public static void Create(Preferences preferences, GLTFBinaryData binaryFileData, string json)
{
byte[] jsonChunk = GlbJsonInfo.Get(json);
int lenggg = jsonChunk.Length;
- byte[] binChunk = GlbBinInfo.Get(binaryFileData, preferences);
+ byte[] binChunk = GlbBinInfo.Get(binaryFileData);
byte[] headerChunk = GlbHeaderInfo.Get(jsonChunk, binChunk);
string fileDirectory = string.Concat(preferences.path, ".glb");
diff --git a/Common_glTF_Exporter/Export/GltfJson.cs b/Common_glTF_Exporter/Export/GltfJson.cs
index 4fb8230..5c187fe 100644
--- a/Common_glTF_Exporter/Export/GltfJson.cs
+++ b/Common_glTF_Exporter/Export/GltfJson.cs
@@ -1,33 +1,43 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Autodesk.Revit.DB;
+using Autodesk.Revit.DB;
using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.Model;
+using Common_glTF_Exporter.Utils;
using Common_glTF_Exporter.Windows.MainWindow;
-using Newtonsoft.Json;
-using Revit_glTF_Exporter;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Buffer = glTF.Manipulator.Schema.Buffer;
namespace Common_glTF_Exporter.Export
{
public static class GltfJson
{
public static string Get(
- List scenes,
- List nodes,
- List meshes,
- List materials,
- List buffers,
- List bufferViews,
- List accessors,
- List textures,
- List images,
+ List scenes,
+ List nodes,
+ List meshes,
+ List materials,
+ List buffers,
+ List bufferViews,
+ List accessors,
+ List textures,
+ List images,
Preferences preferences)
{
+ glTF.Manipulator.Schema.Version version = new glTF.Manipulator.Schema.Version
+ {
+ version = "2.0",
+ generator = string.Concat("e-verse custom generator ", SettingsConfig.currentVersion),
+ copyright = "free tool created by e-verse"
+ };
+
GLTF model = new GLTF
{
- asset = new GLTFVersion(),
+ asset = version,
scenes = scenes,
nodes = nodes,
meshes = meshes,
@@ -38,9 +48,9 @@ public static string Get(
model.extensionsUsed = new List { "KHR_texture_transform" };
}
- if (materials.Any())
+ if (materials.Any() && preferences.materials != MaterialsEnum.nonematerials)
{
- model.materials = materials;
+ model.materials = transformMaterials(materials);
}
if (preferences.materials == MaterialsEnum.textures)
@@ -52,7 +62,7 @@ public static string Get(
if (images.Any())
{
- model.images = images;
+ model.images = cleanImages(images);
}
}
@@ -60,12 +70,75 @@ public static string Get(
model.bufferViews = bufferViews;
model.accessors = accessors;
- // Write the *.gltf file
- string serializedModel = JsonConvert.SerializeObject(
- model,
- new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
+ var options = new JsonSerializerOptions
+ {
+
+ PropertyNamingPolicy = null,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+ WriteIndented = false
+ };
+
+ string serializedModel = System.Text.Json.JsonSerializer.Serialize(model, options);
return serializedModel;
}
+
+ public static List cleanImages(List images)
+ {
+ List resultImages = new List ();
+ foreach (glTFImage img in images)
+ {
+ glTFImage newImg = new glTFImage
+ {
+ bufferView = img.bufferView,
+ mimeType = img.mimeType
+ };
+
+ resultImages.Add(newImg);
+ }
+
+ return resultImages;
+ }
+
+ public static List transformMaterials(List baseMaterials)
+ {
+ List materials = new List();
+ foreach (BaseMaterial baseMat in baseMaterials)
+ {
+ glTF.Manipulator.Schema.Material mat = new glTF.Manipulator.Schema.Material();
+ mat.alphaMode = baseMat.alphaMode;
+ mat.alphaCutoff = baseMat.alphaCutoff;
+ mat.name = baseMat.name;
+ mat.doubleSided = baseMat.doubleSided;
+
+
+ PBR pbrMetallicRoughness = new PBR();
+ pbrMetallicRoughness.metallicFactor = baseMat.metallicFactor;
+ pbrMetallicRoughness.baseColorFactor = baseMat.baseColorFactor;
+ pbrMetallicRoughness.roughnessFactor = baseMat.roughnessFactor;
+
+ if (baseMat.hasTexture)
+ {
+ TextureInfo baseColorTexture = new TextureInfo();
+ baseColorTexture.index = baseMat.textureIndex;
+
+ KHR_texture_transform kHR_Texture_Transform = new KHR_texture_transform();
+ kHR_Texture_Transform.rotation = baseMat.rotation;
+ kHR_Texture_Transform.scale = baseMat.scale;
+ kHR_Texture_Transform.offset = baseMat.offset;
+
+ TextureExtensions extensions = new TextureExtensions();
+ extensions.KHR_texture_transform = kHR_Texture_Transform;
+
+ baseColorTexture.extensions = extensions;
+ pbrMetallicRoughness.baseColorTexture = baseColorTexture;
+ }
+
+ mat.pbrMetallicRoughness = pbrMetallicRoughness;
+
+ materials.Add(mat);
+ }
+ return materials;
+ }
}
}
diff --git a/Common_glTF_Exporter/Export/RevitGrids.cs b/Common_glTF_Exporter/Export/RevitGrids.cs
index 57bd704..a067575 100644
--- a/Common_glTF_Exporter/Export/RevitGrids.cs
+++ b/Common_glTF_Exporter/Export/RevitGrids.cs
@@ -1,11 +1,12 @@
-namespace Common_glTF_Exporter.Export
-{
- using System.Collections.Generic;
- using Autodesk.Revit.DB;
- using Common_glTF_Exporter.Core;
- using Common_glTF_Exporter.Windows.MainWindow;
- using Revit_glTF_Exporter;
+using Autodesk.Revit.DB;
+using Common_glTF_Exporter.Windows.MainWindow;
+using glTF.Manipulator.Schema;
+using Revit_glTF_Exporter;
+using System.Collections.Generic;
+using System.Globalization;
+namespace Common_glTF_Exporter.Export
+{
///
/// Revit grids.
///
@@ -18,7 +19,7 @@ public static class RevitGrids
/// Nodes.
/// root node.
/// preferences.
- public static void Export(Document doc, ref IndexedDictionary nodes, ref GLTFNode rootNode, Preferences preferences)
+ public static void Export(Document doc, ref IndexedDictionary nodes, ref Node rootNode, Preferences preferences)
{
using (FilteredElementCollector col = new FilteredElementCollector(doc).OfClass(typeof(Grid)))
{
@@ -38,25 +39,33 @@ public static void Export(Document doc, ref IndexedDictionary nodes, r
var direction = l.Direction;
var length = l.Length;
- var xtras = new GLTFExtras();
- var grid = new RevitGridParametersObject();
+ Extras xtras = new Extras();
- grid.origin = new List() { origin.X, origin.Y, origin.Z };
+ Dictionary parameters = preferences.properties
+ ? Util.GetElementParameters(g, true) ?? new Dictionary()
+ : new Dictionary();
- grid.direction = new List() { direction.X, direction.Y, direction.Z, };
- grid.length = length;
+ parameters["UniqueId"] = g.UniqueId;
- xtras.gridParameters = grid;
- xtras.uniqueId = g.UniqueId;
+ parameters["GridOrigin"] = string.Format(
+ CultureInfo.InvariantCulture,
+ "{0},{1},{2}",
+ origin.X, origin.Y, origin.Z);
- if (preferences.properties)
- {
- xtras.parameters = Util.GetElementParameters(g, true);
- }
+ parameters["GridDirection"] = string.Format(
+ CultureInfo.InvariantCulture,
+ "{0},{1},{2}",
+ direction.X, direction.Y, direction.Z);
- var gridNode = new GLTFNode();
- gridNode.name = g.Name;
- gridNode.extras = xtras;
+ parameters["GridLength"] = length.ToString(CultureInfo.InvariantCulture);
+
+ xtras.parameters = parameters;
+
+ Node gridNode = new Node
+ {
+ name = g.Name,
+ extras = xtras
+ };
nodes.AddOrUpdateCurrent(g.UniqueId, gridNode);
rootNode.children.Add(nodes.CurrentIndex);
diff --git a/Common_glTF_Exporter/Materials/MaterialProperties.cs b/Common_glTF_Exporter/Materials/MaterialProperties.cs
index b5de6fd..f74d389 100644
--- a/Common_glTF_Exporter/Materials/MaterialProperties.cs
+++ b/Common_glTF_Exporter/Materials/MaterialProperties.cs
@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
+using System.Linq;
using System.Xml.Linq;
using Autodesk.Revit.DB;
using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.Model;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
namespace Common_glTF_Exporter.Materials
{
@@ -11,52 +15,43 @@ public static class MaterialProperties
{
private const string BLEND = "BLEND";
private const string OPAQUE = "OPAQUE";
- public static void SetProperties(MaterialNode node, float opacity, ref GLTFPBR pbr, ref GLTFMaterial gl_mat)
+ public static void SetProperties(MaterialNode node, float opacity, ref BaseMaterial material)
{
- pbr.metallicFactor = 0f;
- pbr.roughnessFactor = opacity != 1 ? 0.5f : 1f;
- gl_mat.pbrMetallicRoughness = pbr;
-
- gl_mat.alphaMode = opacity != 1 ? BLEND : OPAQUE;
- gl_mat.alphaCutoff = null;
+ material.metallicFactor = 0f;
+ material.roughnessFactor = opacity != 1 ? 0.5f : 1f;
+ material.alphaMode = opacity != 1 ? BLEND : OPAQUE;
+ material.alphaCutoff = null;
}
- public static void SetMaterialColour(MaterialNode node,
- float opacity, ref GLTFPBR pbr, ref GLTFMaterial gl_mat)
+ public static List SetMaterialColour(MaterialNode node,
+ float opacity, Autodesk.Revit.DB.Color baseColor, Autodesk.Revit.DB.Color tintColor)
{
- if (gl_mat.EmbeddedTexturePath == null)
- {
+
(float, float, float) baseColours;
- if (gl_mat.BaseColor == null)
+ if (baseColor == null)
{
baseColours = RgbToUnit(node.Color);
}
else
{
- baseColours = RgbToUnit(gl_mat.BaseColor);
+ baseColours = RgbToUnit(baseColor);
}
- if (gl_mat.TintColour == null)
+ if (tintColor == null)
{
- pbr.baseColorFactor = GetLinearColour(baseColours, opacity);
+ return GetLinearColour(baseColours, opacity);
}
else
{
- (float, float, float) baseTintColour = RgbToUnit(gl_mat.TintColour);
+ (float, float, float) baseTintColour = RgbToUnit(tintColor);
(float, float, float) blendColour = BlendColour(baseColours, baseTintColour);
- pbr.baseColorFactor = GetLinearColour(blendColour, opacity);
+ return GetLinearColour(blendColour, opacity);
}
- }
- else
- {
- gl_mat.pbrMetallicRoughness.baseColorFactor = GetDefaultColour(opacity);
- }
-
- gl_mat.pbrMetallicRoughness = pbr;
}
+
public static List GetDefaultColour(float opacity)
{
return new List(4) { 1, 1, 1, opacity };
diff --git a/Common_glTF_Exporter/Materials/MaterialTexture.cs b/Common_glTF_Exporter/Materials/MaterialTexture.cs
new file mode 100644
index 0000000..cc9ec91
--- /dev/null
+++ b/Common_glTF_Exporter/Materials/MaterialTexture.cs
@@ -0,0 +1,12 @@
+namespace Common_glTF_Exporter.Core
+{
+ public class MaterialTexture
+ {
+ public string EmbeddedTexturePath { get; set; } = null;
+ public double Fadevalue { get; set; } = 1;
+
+ public Autodesk.Revit.DB.Color TintColour { get; set; }
+
+ public Autodesk.Revit.DB.Color BaseColor { get; set; }
+ }
+}
diff --git a/Common_glTF_Exporter/Materials/MaterialTextures.cs b/Common_glTF_Exporter/Materials/MaterialTextures.cs
index 74d0455..c162a6b 100644
--- a/Common_glTF_Exporter/Materials/MaterialTextures.cs
+++ b/Common_glTF_Exporter/Materials/MaterialTextures.cs
@@ -1,66 +1,71 @@
-using System.Collections.Generic;
-using System.IO;
-using Autodesk.Revit.DB;
+using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Visual;
using Common_glTF_Exporter.Core;
-using Common_glTF_Exporter.Windows.MainWindow;
-using Revit_glTF_Exporter;
-using Common_glTF_Exporter.Materials;
using Common_glTF_Exporter.Model;
-using System.IO.Ports;
-using System.Windows.Controls;
-using System.Windows.Media.Media3D;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
+using Revit_glTF_Exporter;
+using System.Collections.Generic;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Windows.Interop;
using Material = Autodesk.Revit.DB.Material;
-using System;
-using Common_glTF_Exporter.Utils;
-using System.Diagnostics;
namespace Common_glTF_Exporter.Materials
{
public static class MaterialTextures
{
- public static GLTFMaterial SetMaterialTextures(Material material, GLTFMaterial gl_mat,
- Document doc, float opacity)
+ public static (Autodesk.Revit.DB.Color, Autodesk.Revit.DB.Color) SetMaterialTextures(Material revitMaterial, BaseMaterial material,
+ Document doc, float opacity, List textures, List images)
{
- ElementId appearanceId = material.AppearanceAssetId;
+ ElementId appearanceId = revitMaterial.AppearanceAssetId;
if (appearanceId == ElementId.InvalidElementId)
{
- return gl_mat;
+ return (null,null);
}
var appearanceElem = doc.GetElement(appearanceId) as AppearanceAssetElement;
if (appearanceElem == null)
{
- return gl_mat;
+ return (null, null);
}
Asset theAsset = appearanceElem.GetRenderingAsset();
AssetPropertyString baseSchema = theAsset.FindByName("BaseSchema") as AssetPropertyString;
if (baseSchema == null)
{
- return gl_mat;
+ return (null, null);
}
string schemaName = baseSchema.Value;
Asset connectedAsset = AssetPropertiesUtils.GetDiffuseBitmap(theAsset, schemaName);
string texturePath = AssetPropertiesUtils.GetTexturePath(connectedAsset);
- gl_mat.TintColour = AssetPropertiesUtils.GetTint(theAsset);
- gl_mat.BaseColor = AssetPropertiesUtils.GetAppearanceColor(theAsset, schemaName);
+ Autodesk.Revit.DB.Color tintColour = AssetPropertiesUtils.GetTint(theAsset);
+ Autodesk.Revit.DB.Color baseColor = AssetPropertiesUtils.GetAppearanceColor(theAsset, schemaName);
+ double Fadevalue = AssetPropertiesUtils.GetFade(theAsset);
- if (!string.IsNullOrEmpty(texturePath) && File.Exists(texturePath))
+ if (!string.IsNullOrEmpty(texturePath))
{
- SetTextureProperties(gl_mat, texturePath, connectedAsset, theAsset, opacity);
+ int indexImage = createOrGetBaseImage(tintColour, baseColor, Fadevalue, texturePath, images);
+
+ Texture baseTexture = createTexture(material, texturePath, connectedAsset, theAsset, opacity, indexImage);
+ textures.Add(baseTexture);
+
+ material.hasTexture = true;
+ material.textureIndex = textures.Count - 1;
}
- return gl_mat;
+ return (baseColor, tintColour);
}
- private static void SetTextureProperties(GLTFMaterial gl_mat, string texturePath, Asset connectedAsset,
- Asset theAsset, float opacity)
+ private static Texture createTexture(BaseMaterial material, string texturePath, Asset connectedAsset,
+ Asset theAsset, float opacity, int imageIndex)
{
- gl_mat.EmbeddedTexturePath = texturePath;
+
+ Texture texture = new Texture();
float scaleX = AssetPropertiesUtils.GetScale(connectedAsset, UnifiedBitmap.TextureRealWorldScaleX);
float scaleY = AssetPropertiesUtils.GetScale(connectedAsset, UnifiedBitmap.TextureRealWorldScaleY);
@@ -68,8 +73,6 @@ private static void SetTextureProperties(GLTFMaterial gl_mat, string texturePath
float offsetY = AssetPropertiesUtils.GetOffset(connectedAsset, UnifiedBitmap.TextureRealWorldOffsetY);
float rotation = AssetPropertiesUtils.GetRotationRadians(connectedAsset);
- gl_mat.Fadevalue = AssetPropertiesUtils.GetFade(theAsset);
-
float[] gltfScale = new float[] { 1f / scaleX, 1f / scaleY };
float[] gltfOffset = new float[]
{
@@ -77,19 +80,40 @@ private static void SetTextureProperties(GLTFMaterial gl_mat, string texturePath
offsetY / scaleY - gltfScale[1]
};
- gl_mat.pbrMetallicRoughness.baseColorTexture = new GLTFTextureInfo
+ material.offset = gltfOffset;
+ material.rotation = rotation;
+ material.scale = gltfScale;
+ texture.source = imageIndex;
+
+ return texture;
+ }
+
+ private static int createOrGetBaseImage(Autodesk.Revit.DB.Color TintColour, Autodesk.Revit.DB.Color BaseColor, double Fadevalue, string texturePath, List images)
+ {
+
+ bool checkIfImageExists = images.Any(x => x.uuid == texturePath);
+
+ if (checkIfImageExists)
{
- index = -1,
- extensions = new GLTFTextureExtensions
- {
- TextureTransform = new GLTFTextureTransform
- {
- offset = gltfOffset,
- scale = gltfScale,
- rotation = rotation
- }
- }
- };
+ int index = images.FindIndex(x => x.uuid == texturePath);
+
+ return index;
+ }
+ else
+ {
+ glTFImage Image = new glTFImage();
+ Image.uuid = texturePath;
+ (string, ImageFormat) mimeType = BitmapsUtils.GetMimeType(texturePath);
+ Image.mimeType = mimeType.Item1;
+ byte[] imageBytes = BitmapsUtils.CleanGamma(texturePath, mimeType.Item2);
+ byte[] blendedBytes = BitmapsUtils.BlendImageWithColor(imageBytes, Fadevalue,
+ BaseColor, mimeType.Item2, TintColour);
+ Image.imageData = blendedBytes;
+ images.Add(Image);
+ int index = images.Count - 1;
+
+ return index;
+ }
}
}
}
diff --git a/Common_glTF_Exporter/Materials/RevitMaterials.cs b/Common_glTF_Exporter/Materials/RevitMaterials.cs
index 67c508c..3006039 100644
--- a/Common_glTF_Exporter/Materials/RevitMaterials.cs
+++ b/Common_glTF_Exporter/Materials/RevitMaterials.cs
@@ -12,6 +12,8 @@
using System.Windows.Media.Media3D;
using Material = Autodesk.Revit.DB.Material;
using Common_glTF_Exporter.Utils;
+using glTF.Manipulator.Schema;
+using glTF.Manipulator.GenericSchema;
namespace Common_glTF_Exporter.Export
@@ -20,61 +22,69 @@ public static class RevitMaterials
{
const int ONEINTVALUE = 1;
- public static GLTFMaterial ProcessMaterial(MaterialNode node,
- Preferences preferences, Document doc, IndexedDictionary materials)
+ public static BaseMaterial ProcessMaterial(MaterialNode node,
+ Preferences preferences, Document doc, IndexedDictionary materials,
+ List textures, List images)
{
- GLTFMaterial gl_mat;
-
+ BaseMaterial material = new BaseMaterial();
string materialId = node.MaterialId.ToString();
+ material.uuid = materialId;
+
if (materials.Contains(materialId))
{
- gl_mat = materials.GetElement(materialId);
+ material = materials.GetElement(materialId);
}
else
{
- Autodesk.Revit.DB.Material material = doc.GetElement(node.MaterialId) as Autodesk.Revit.DB.Material;
+ Autodesk.Revit.DB.Material revitMaterial = doc.GetElement(node.MaterialId) as Autodesk.Revit.DB.Material;
- if (material == null)
+ if (revitMaterial == null)
{
- gl_mat = GLTFExportUtils.GetGLTFMaterial(materials, node.Transparency, false);
- materialId = gl_mat.UniqueId;
+ material = GLTFExportUtils.GetGLTFMaterial(materials);
}
else
{
- gl_mat = RevitMaterials.Export(node, preferences, doc, material);
+ material = RevitMaterials.Export(node, preferences, doc, revitMaterial, textures, images, material);
}
}
- materials.AddOrUpdateCurrentMaterial(materialId, gl_mat, false);
+ materials.AddOrUpdateCurrentMaterial(material.uuid, material, false);
- return gl_mat;
+ return material;
}
///
/// Export Revit materials.
///
- public static GLTFMaterial Export(MaterialNode node,
- Preferences preferences, Document doc, Material material)
+ public static BaseMaterial Export(MaterialNode node,
+ Preferences preferences, Document doc,
+ Material revitMaterial, List textures,
+ List images, BaseMaterial material)
{
- GLTFMaterial gl_mat = new GLTFMaterial();
float opacity = ONEINTVALUE - (float)node.Transparency;
- gl_mat.name = material.Name;
- gl_mat.UniqueId = node.MaterialId.ToString();
+ material.name = revitMaterial.Name;
+ MaterialProperties.SetProperties(node, opacity, ref material);
- GLTFPBR pbr = new GLTFPBR();
- MaterialProperties.SetProperties(node, opacity, ref pbr, ref gl_mat);
+ (Autodesk.Revit.DB.Color, Autodesk.Revit.DB.Color) baseNTintColour = (null, null);
- if (material != null && preferences.materials == MaterialsEnum.textures)
+ if (revitMaterial != null && preferences.materials == MaterialsEnum.textures)
{
- MaterialTextures.SetMaterialTextures(material, gl_mat, doc, opacity);
+ baseNTintColour = MaterialTextures.SetMaterialTextures(revitMaterial, material, doc, opacity, textures, images);
+ material.baseColorFactor = MaterialProperties.GetDefaultColour(opacity);
}
- MaterialProperties.SetMaterialColour(node, opacity, ref pbr, ref gl_mat);
-
+ if (material.hasTexture)
+ {
+ material.baseColorFactor = MaterialProperties.GetDefaultColour(opacity);
+ }
+ else
+ {
+ material.baseColorFactor = MaterialProperties.SetMaterialColour(node, opacity, baseNTintColour.Item1, baseNTintColour.Item2);
+ }
- return gl_mat;
+ return material;
}
}
}
diff --git a/Common_glTF_Exporter/Model/GeometryDataObject.cs b/Common_glTF_Exporter/Model/GeometryDataObject.cs
deleted file mode 100644
index 2d0158a..0000000
--- a/Common_glTF_Exporter/Model/GeometryDataObject.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-namespace Common_glTF_Exporter.Model
-{
- using Autodesk.Revit.DB;
- using System.Collections.Generic;
-
- ///
- /// Intermediate data format for converting between Revit Polymesh and glTF buffers.
- ///
- public class GeometryDataObject
- {
- public List Vertices { get; set; } = new List();
-
- public List Normals { get; set; } = new List();
-
- public List Uvs { get; set; } = new List();
-
- public List Faces { get; set; } = new List();
-
- }
-}
diff --git a/Common_glTF_Exporter/Utils/GLTFBinaryDataUtils.cs b/Common_glTF_Exporter/Utils/GLTFBinaryDataUtils.cs
index 93bab77..f6b283a 100644
--- a/Common_glTF_Exporter/Utils/GLTFBinaryDataUtils.cs
+++ b/Common_glTF_Exporter/Utils/GLTFBinaryDataUtils.cs
@@ -1,275 +1,345 @@
-using System.Drawing.Imaging;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Common_glTF_Exporter.Core;
+using Common_glTF_Exporter.Core;
using Common_glTF_Exporter.Model;
+using glTF.Manipulator.GenericSchema;
+using glTF.Manipulator.Schema;
using Revit_glTF_Exporter;
-using Common_glTF_Exporter.Materials;
+using System.Collections.Generic;
+using System.Linq;
namespace Common_glTF_Exporter.Utils
{
public class GLTFBinaryDataUtils
{
- const string SCALAR_STR = "SCALAR";
- const string FACE_STR = "FACE";
- const string BATCH_ID_STR = "BATCH_ID";
-
- public static int ExportFaces(int bufferIdx, int byteOffset, GeometryDataObject geomData, GLTFBinaryData bufferData, List bufferViews, List accessors)
+ public static int ExportFaces(
+ GeometryDataObject geomData,
+ GLTFBinaryData bufferData,
+ List bufferViews,
+ List accessors)
{
- foreach (var index in geomData.Faces)
- {
- bufferData.indexBuffer.Add(index);
- }
-
- // Get max and min for index data
- int[] faceMinMax = Util.GetScalarMinMax(bufferData.indexBuffer);
-
- // Add a faces / indexes buffer view
- int elementsPerIndex = 1;
- int bytesPerIndexElement = 4;
- int bytesPerIndex = elementsPerIndex * bytesPerIndexElement;
- int numIndexes = geomData.Faces.Count;
- int sizeOfIndexView = numIndexes * bytesPerIndex;
- GLTFBufferView facesView = new GLTFBufferView(bufferIdx, byteOffset, sizeOfIndexView, Targets.ELEMENT_ARRAY_BUFFER, string.Empty);
- bufferViews.Add(facesView);
- int facesViewIdx = bufferViews.Count - 1;
-
- // add a face accessor
- var count = geomData.Faces.Count / elementsPerIndex;
- var max = new List(1) { faceMinMax[1] };
- var min = new List(1) { faceMinMax[0] };
- GLTFAccessor faceAccessor = new GLTFAccessor(facesViewIdx, 0, ComponentType.UNSIGNED_INT, count, SCALAR_STR, max, min, FACE_STR);
- accessors.Add(faceAccessor);
- bufferData.indexAccessorIndex = accessors.Count - 1;
- return byteOffset + facesView.byteLength;
+ const string SCALAR_STR = "SCALAR";
+ const string FACE_STR = "FACE";
+
+ int indexCount = geomData.Faces.Count;
+ if (indexCount == 0)
+ return -1;
+
+ int[] indices = geomData.Faces.ToArray();
+
+ List listIndicess = new List(indices);
+ int[] minMax = Util.GetScalarMinMax(listIndicess);
+
+ var max = new List { minMax[1] };
+ var min = new List { minMax[0] };
+
+ int byteOffset = bufferData.AppendIntArray(indices);
+ int byteLength = indices.Length * sizeof(int);
+
+ BufferView view = new BufferView(
+ buffer: 0,
+ byteOffset: byteOffset,
+ byteLength: byteLength,
+ Targets.ELEMENT_ARRAY_BUFFER,
+ name: ""
+ );
+
+ bufferViews.Add(view);
+ int viewIdx = bufferViews.Count - 1;
+
+ Accessor accessor = new Accessor(
+ bufferView: viewIdx,
+ byteOffset: 0,
+ componentType: ComponentType.UNSIGNED_INT, // 5125
+ count: indexCount,
+ type: SCALAR_STR,
+ max: max,
+ min: min,
+ name: FACE_STR
+ );
+
+ accessors.Add(accessor);
+ int accessorIdx = accessors.Count - 1;
+
+ return accessorIdx;
}
+
const string VEC3_STR = "VEC3";
const string POSITION_STR = "POSITION";
- public static int ExportVertices(int bufferIdx, int byteOffset, GeometryDataObject geomData, GLTFBinaryData bufferData, List bufferViews, List accessors, out int sizeOfVec3View, out int elementsPerVertex)
+ public static int ExportVertices(
+ GeometryDataObject geomData,
+ GLTFBinaryData bufferData,
+ List bufferViews,
+ List accessors,
+ MeshPrimitive primitive)
{
+ const string VEC3_STR = "VEC3";
+ const string POSITION_STR = "POSITION";
- for (int i = 0; i < geomData.Vertices.Count; i++)
- {
- bufferData.vertexBuffer.Add(Convert.ToSingle(geomData.Vertices[i]));
- }
+ int vertexCount = geomData.Vertices.Count / 3;
+ if (vertexCount == 0)
+ return -1;
- // Get max and min for vertex data
- float[] vertexMinMax = Util.GetVec3MinMax(bufferData.vertexBuffer);
-
- // Add a vec3 buffer view
- elementsPerVertex = 3;
- int bytesPerElement = 4;
- int bytesPerVertex = elementsPerVertex * bytesPerElement;
- int numVec3 = geomData.Vertices.Count / elementsPerVertex;
- sizeOfVec3View = numVec3 * bytesPerVertex;
-
- GLTFBufferView vec3View = new GLTFBufferView(bufferIdx, byteOffset, sizeOfVec3View, Targets.ARRAY_BUFFER, string.Empty);
- bufferViews.Add(vec3View);
- int vec3ViewIdx = bufferViews.Count - 1;
-
- // add a position accessor
- int count = geomData.Vertices.Count / elementsPerVertex;
- var max = new List(3) { vertexMinMax[1], vertexMinMax[3], vertexMinMax[5] };
- var min = new List(3) { vertexMinMax[0], vertexMinMax[2], vertexMinMax[4] };
-
- GLTFAccessor positionAccessor = new GLTFAccessor(vec3ViewIdx, 0, ComponentType.FLOAT, count, VEC3_STR, max, min, POSITION_STR);
- accessors.Add(positionAccessor);
- bufferData.vertexAccessorIndex = accessors.Count - 1;
- return byteOffset + vec3View.byteLength;
+ // Convert to float array
+ float[] vertexFloats = new float[geomData.Vertices.Count];
+ for (int i = 0; i < geomData.Vertices.Count; i++)
+ vertexFloats[i] = (float)geomData.Vertices[i];
+
+ // Compute min/max
+ float[] minMax = Util.GetVec3MinMax(vertexFloats);
+ var max = new List { minMax[1], minMax[3], minMax[5] };
+ var min = new List { minMax[0], minMax[2], minMax[4] };
+
+ // Write to buffer (correct padding applied)
+ int byteOffset = bufferData.AppendFloatArray(vertexFloats);
+ int byteLength = vertexFloats.Length * sizeof(float);
+
+ // Create bufferView
+ var view = new BufferView(
+ buffer: 0,
+ byteOffset: byteOffset,
+ byteLength: byteLength,
+ Targets.ARRAY_BUFFER,
+ name: ""
+ );
+
+ bufferViews.Add(view);
+ int bufferViewIndex = bufferViews.Count - 1;
+
+ // Create accessor
+ var accessor = new Accessor(
+ bufferView: bufferViewIndex,
+ byteOffset: 0,
+ componentType: ComponentType.FLOAT,
+ count: vertexCount,
+ type: VEC3_STR,
+ max: max,
+ min: min,
+ name: POSITION_STR
+ );
+
+ accessors.Add(accessor);
+ int accessorIndex = accessors.Count - 1;
+
+ // Assign accessor to primitive
+ primitive.attributes.POSITION = accessorIndex;
+
+ return accessorIndex;
}
+
+
const string NORMAL_STR = "NORMALS";
- public static int ExportNormals(int bufferIdx, int byteOffset, GeometryDataObject geomData, GLTFBinaryData bufferData, List bufferViews, List accessors)
+ public static int ExportNormals(
+ GeometryDataObject geomData,
+ GLTFBinaryData bufferData,
+ List bufferViews,
+ List accessors,
+ MeshPrimitive primitive)
{
- for (int i = 0; i < geomData.Normals.Count; i++)
- {
- bufferData.normalBuffer.Add(Convert.ToSingle(geomData.Normals[i]));
- }
-
- // Get max and min for normal data
- float[] normalMinMax = Util.GetVec3MinMax(bufferData.normalBuffer);
-
- // Add a normals (vec3) buffer view
- int elementsPerNormal = 3;
- int bytesPerNormalElement = 4;
- int bytesPerNormal = elementsPerNormal * bytesPerNormalElement;
- var normalsCount = geomData.Normals.Count;
- int numVec3Normals = normalsCount / elementsPerNormal;
- int sizeOfVec3ViewNormals = numVec3Normals * bytesPerNormal;
- GLTFBufferView vec3ViewNormals = new GLTFBufferView(bufferIdx, byteOffset, sizeOfVec3ViewNormals, Targets.ARRAY_BUFFER, string.Empty);
- bufferViews.Add(vec3ViewNormals);
- int vec3ViewNormalsIdx = bufferViews.Count - 1;
-
- // add a normals accessor
- var count = normalsCount / elementsPerNormal;
- var max = new List(3) { normalMinMax[1], normalMinMax[3], normalMinMax[5] };
- var min = new List(3) { normalMinMax[0], normalMinMax[2], normalMinMax[4] };
-
- GLTFAccessor normalsAccessor = new GLTFAccessor(vec3ViewNormalsIdx, 0, ComponentType.FLOAT, count, VEC3_STR, max, min, NORMAL_STR);
- accessors.Add(normalsAccessor);
- bufferData.normalsAccessorIndex = accessors.Count - 1;
- return byteOffset + vec3ViewNormals.byteLength;
+ const string VEC3_STR = "VEC3";
+ const string NORMAL_STR = "NORMAL";
+
+ int normalCount = geomData.Normals.Count;
+ if (normalCount == 0)
+ return -1;
+
+ // Convert normals to float[]
+ float[] normals = geomData.Normals
+ .Select(n => (float)n)
+ .ToArray();
+
+ // Min/Max SOLO para estas normales
+ float[] minMax = Util.GetVec3MinMax(normals);
+
+ var max = new List { minMax[1], minMax[3], minMax[5] };
+ var min = new List { minMax[0], minMax[2], minMax[4] };
+
+ // Append normals al buffer global (float32)
+ int byteOffset = bufferData.AppendFloatArray(normals);
+ int byteLength = normals.Length * sizeof(float);
+
+ // Crear bufferView
+ BufferView view = new BufferView(
+ buffer: 0,
+ byteOffset: byteOffset,
+ byteLength: byteLength,
+ Targets.ARRAY_BUFFER,
+ name: ""
+ );
+
+ bufferViews.Add(view);
+ int viewIdx = bufferViews.Count - 1;
+
+ // Crear accessor
+ int count = normalCount / 3;
+
+ Accessor accessor = new Accessor(
+ bufferView: viewIdx,
+ byteOffset: 0,
+ componentType: ComponentType.FLOAT,
+ count: count,
+ type: VEC3_STR,
+ max: max,
+ min: min,
+ name: NORMAL_STR
+ );
+
+ accessors.Add(accessor);
+ int accessorIdx = accessors.Count - 1;
+
+ // Asignar al primitive
+ primitive.attributes.NORMAL = accessorIdx;
+
+ return accessorIdx;
}
- public static int ExportBatchId(int bufferIdx, int byteOffset, int sizeOfVec3View, int elementsPerVertex, long elementId, GeometryDataObject geomData, GLTFBinaryData bufferData, List bufferViews, List accessors)
+ public static int ExportBatchId(
+ long elementId,
+ GeometryDataObject geomData,
+ GLTFBinaryData bufferData,
+ List bufferViews,
+ List accessors,
+ MeshPrimitive primitive)
{
- for (int i = 0; i < geomData.Vertices.Count; i++)
- {
- bufferData.batchIdBuffer.Add(elementId);
- }
-
- // Get max and min for batchId data
- float[] batchIdMinMax = Util.GetVec3MinMax(bufferData.batchIdBuffer);
-
- // Add a batchId buffer view
- GLTFBufferView batchIdsView = new GLTFBufferView(bufferIdx, byteOffset, sizeOfVec3View, Targets.ARRAY_BUFFER, string.Empty);
- bufferViews.Add(batchIdsView);
- int batchIdsViewIdx = bufferViews.Count - 1;
-
- // add a batchId accessor
- var count = geomData.Vertices.Count / elementsPerVertex;
- var max = new List(3) { batchIdMinMax[1], batchIdMinMax[3], batchIdMinMax[5] };
- var min = new List(3) { batchIdMinMax[0], batchIdMinMax[2], batchIdMinMax[4] };
- GLTFAccessor batchIdAccessor = new GLTFAccessor(batchIdsViewIdx, 0, ComponentType.FLOAT, count, VEC3_STR, max, min, BATCH_ID_STR);
- accessors.Add(batchIdAccessor);
- bufferData.batchIdAccessorIndex = accessors.Count - 1;
- return byteOffset + batchIdsView.byteLength;
+ const string SCALAR_STR = "SCALAR";
+ const string BATCH_ID_STR = "_BATCHID";
+
+ int vertexCount = geomData.Vertices.Count / 3;
+ if (vertexCount == 0)
+ return -1;
+
+ float idValue = (float)elementId;
+ float[] batchIds = Enumerable.Repeat(idValue, vertexCount).ToArray();
+
+ var min = new List { idValue };
+ var max = new List { idValue };
+
+ int byteOffset = bufferData.AppendFloatArray(batchIds);
+ int byteLength = batchIds.Length * sizeof(float);
+
+ BufferView view = new BufferView(
+ buffer: 0,
+ byteOffset: byteOffset,
+ byteLength: byteLength,
+ Targets.ARRAY_BUFFER,
+ name: ""
+ );
+
+ bufferViews.Add(view);
+ int viewIdx = bufferViews.Count - 1;
+
+ Accessor accessor = new Accessor(
+ bufferView: viewIdx,
+ byteOffset: 0,
+ componentType: ComponentType.FLOAT,
+ count: vertexCount,
+ type: SCALAR_STR,
+ max: max,
+ min: min,
+ name: BATCH_ID_STR
+ );
+
+ accessors.Add(accessor);
+ int accessorIdx = accessors.Count - 1;
+
+ primitive.attributes._BATCHID = accessorIdx;
+
+ return accessorIdx;
}
+
public static int ExportUVs(
- int bufferIdx,
- int byteOffset,
- GeometryDataObject geomData,
- GLTFBinaryData bufferData,
- List bufferViews,
- List accessors)
+ GeometryDataObject geomData,
+ GLTFBinaryData bufferData,
+ List bufferViews,
+ List accessors,
+ MeshPrimitive primitive)
{
const string VEC2_STR = "VEC2";
const string TEXCOORD_STR = "TEXCOORD_0";
int uvCount = geomData.Uvs.Count;
+ if (uvCount == 0)
+ return -1;
+
+ float[] uvFloats = new float[uvCount * 2];
+ int ptr = 0;
- // Convert UVs to float buffer (U, V per entry)
foreach (var uv in geomData.Uvs)
{
- bufferData.uvBuffer.Add((float)uv.U);
- bufferData.uvBuffer.Add((float)uv.V);
+ uvFloats[ptr++] = uv.U;
+ uvFloats[ptr++] = uv.V;
}
- int elementsPerUV = 2;
- int bytesPerUVElement = 4;
- int bytesPerUV = elementsPerUV * bytesPerUVElement;
+ List listUvFloats = new List(uvFloats);
+ float[] uvMinMax = Util.GetVec2MinMax(listUvFloats);
+
+ var max = new List { uvMinMax[1], uvMinMax[3] };
+ var min = new List { uvMinMax[0], uvMinMax[2] };
+
+ int byteOffset = bufferData.AppendFloatArray(uvFloats);
+ int byteLength = uvFloats.Length * sizeof(float);
- int sizeOfUVView = uvCount * bytesPerUV;
+ BufferView uvBufferView = new BufferView(
+ buffer: 0,
+ byteOffset: byteOffset,
+ byteLength: byteLength,
+ Targets.ARRAY_BUFFER,
+ name: ""
+ );
- // Create UV buffer view
- GLTFBufferView uvBufferView = new GLTFBufferView(bufferIdx, byteOffset, sizeOfUVView, Targets.ARRAY_BUFFER, string.Empty);
bufferViews.Add(uvBufferView);
- int uvBufferViewIdx = bufferViews.Count - 1;
+ int viewIdx = bufferViews.Count - 1;
- // Min/max for VEC2 accessors (optional, but good practice)
- float[] uvMinMax = Util.GetVec2MinMax(bufferData.uvBuffer);
- var max = new List { uvMinMax[1], uvMinMax[3] };
- var min = new List { uvMinMax[0], uvMinMax[2] };
+ Accessor accessor = new Accessor(
+ bufferView: viewIdx,
+ byteOffset: 0,
+ componentType: ComponentType.FLOAT,
+ count: uvCount,
+ type: VEC2_STR,
+ max: max,
+ min: min,
+ name: TEXCOORD_STR
+ );
+
+ accessors.Add(accessor);
+ int accessorIdx = accessors.Count - 1;
- // Create UV accessor
- GLTFAccessor uvAccessor = new GLTFAccessor(
- uvBufferViewIdx,
- 0,
- ComponentType.FLOAT,
- uvCount,
- VEC2_STR,
- max,
- min,
- TEXCOORD_STR);
-
- accessors.Add(uvAccessor);
- bufferData.uvAccessorIndex = accessors.Count - 1;
-
- return byteOffset + uvBufferView.byteLength;
+ primitive.attributes.TEXCOORD_0 = accessorIdx;
+
+ return accessorIdx;
}
- public static int ExportImageBuffer(
- int bufferIdx,
- int byteOffset,
- GLTFMaterial material,
- List images,
- List