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 textures, - GLTFBinaryData bufferData, - List bufferViews) + public static void ExportImageBuffer( + List images, + List bufferViews, + GLTFBinaryData bufferData) { - if (material.EmbeddedTexturePath == null) - { - return byteOffset; - } - - if (material.pbrMetallicRoughness.baseColorTexture.index == -1) - { - (string, ImageFormat) mimeType = BitmapsUtils.GetMimeType(material.EmbeddedTexturePath); - byte[] imageBytes = BitmapsUtils.CleanGamma(material.EmbeddedTexturePath, mimeType.Item2); - - byte[] blendedBytes = BitmapsUtils.BlendImageWithColor(imageBytes, material.Fadevalue, - material.BaseColor, mimeType.Item2, material.TintColour); - - if (blendedBytes != null) - { - if (bufferData.byteData == null) - { - bufferData.byteData = blendedBytes; - } - else - { - byte[] combined = new byte[bufferData.byteData.Length + blendedBytes.Length]; - Buffer.BlockCopy(bufferData.byteData, 0, combined, 0, bufferData.byteData.Length); - Buffer.BlockCopy(blendedBytes, 0, combined, bufferData.byteData.Length, blendedBytes.Length); - bufferData.byteData = combined; - } - } - - int currentLenght = blendedBytes.Length; - int alignment = 4; - int padding = (alignment - (currentLenght % alignment)) % alignment; - - if (padding != 0) - { - currentLenght = currentLenght + padding; - - byte[] newArray = bufferData.byteData.Concat(new byte[padding]).ToArray(); - bufferData.byteData = newArray; - } - - GLTFBufferView ImageBufferView = new GLTFBufferView(bufferIdx, byteOffset, currentLenght, Targets.NONE, string.Empty); - - bufferViews.Add(ImageBufferView); - int bufferViewIndex = bufferViews.Count - 1; - - var image = new GLTFImage - { - bufferView = bufferViewIndex, - mimeType = mimeType.Item1 - }; - - images.Add(image); - int imageIndex = images.Count - 1; - - var texture = new GLTFTexture - { - source = imageIndex - }; - textures.Add(texture); - int textureIndex = textures.Count - 1; - material.pbrMetallicRoughness.baseColorTexture.index = textureIndex; - return byteOffset + ImageBufferView.byteLength; - } - else + foreach (var baseImage in images) { - return byteOffset; + byte[] imgBytes = baseImage.imageData; + if (imgBytes == null || imgBytes.Length == 0) + continue; + + int byteOffset = bufferData.GetCurrentByteOffset(); + int byteLength = bufferData.Append(imgBytes); + + BufferView imgView = new BufferView( + buffer: 0, + byteOffset: byteOffset, + byteLength: byteLength, + Targets.NONE, + name: "" + ); + + bufferViews.Add(imgView); + int viewIdx = bufferViews.Count - 1; + + baseImage.bufferView = viewIdx; + baseImage.uri = null; } } } diff --git a/Common_glTF_Exporter/Utils/MaterialUtils.cs b/Common_glTF_Exporter/Utils/MaterialUtils.cs index 0a8e60a..f9c6a45 100644 --- a/Common_glTF_Exporter/Utils/MaterialUtils.cs +++ b/Common_glTF_Exporter/Utils/MaterialUtils.cs @@ -2,19 +2,22 @@ { using Autodesk.Revit.DB; using Common_glTF_Exporter.Core; + using Common_glTF_Exporter.Model; using Common_glTF_Exporter.Windows.MainWindow; + using glTF.Manipulator.GenericSchema; + using glTF.Manipulator.Schema; using Revit_glTF_Exporter; using System.Collections.Generic; public class MaterialUtils { - public static Material GetMeshMaterial(Document doc, Mesh mesh) + public static Autodesk.Revit.DB.Material GetMeshMaterial(Document doc, Autodesk.Revit.DB.Mesh mesh) { ElementId materialId = mesh.MaterialElementId; if (materialId != null) { - return doc.GetElement(materialId) as Material; + return doc.GetElement(materialId) as Autodesk.Revit.DB.Material; } else { @@ -22,29 +25,27 @@ public static Material GetMeshMaterial(Document doc, Mesh mesh) } } - public static GLTFMaterial GetGltfMeshMaterial(Document doc, Preferences preferences, Mesh mesh, IndexedDictionary materials, bool doubleSided) + public static BaseMaterial GetGltfMeshMaterial(Document doc, Preferences preferences, Autodesk.Revit.DB.Mesh mesh, IndexedDictionary materials, bool doubleSided) { - GLTFMaterial gl_mat = new GLTFMaterial(); + BaseMaterial gl_mat = new BaseMaterial(); - Material material = GetMeshMaterial(doc, mesh); + Autodesk.Revit.DB.Material material = GetMeshMaterial(doc, mesh); if (preferences.materials == MaterialsEnum.materials || preferences.materials == MaterialsEnum.textures) { if (material == null) { - gl_mat = GLTFExportUtils.GetGLTFMaterial(materials, 1, doubleSided); + gl_mat = GLTFExportUtils.GetGLTFMaterial(materials); } else { gl_mat.doubleSided = doubleSided; float opacity = 1 - (float)material.Transparency; gl_mat.name = material.Name; - GLTFPBR pbr = new GLTFPBR(); - pbr.baseColorFactor = new List(4) { material.Color.Red / 255f, material.Color.Green / 255f, material.Color.Blue / 255f, opacity }; - pbr.metallicFactor = 0f; - pbr.roughnessFactor = 1f; - gl_mat.pbrMetallicRoughness = pbr; - gl_mat.UniqueId = material.UniqueId; + + gl_mat.baseColorFactor = new List(4) { material.Color.Red / 255f, material.Color.Green / 255f, material.Color.Blue / 255f, opacity }; + gl_mat.metallicFactor = 0f; + gl_mat.roughnessFactor = 1f; } } diff --git a/Common_glTF_Exporter/Utils/glTFExportUtils.cs b/Common_glTF_Exporter/Utils/glTFExportUtils.cs index 476bcf8..6aabbd0 100644 --- a/Common_glTF_Exporter/Utils/glTFExportUtils.cs +++ b/Common_glTF_Exporter/Utils/glTFExportUtils.cs @@ -1,47 +1,39 @@ - namespace Common_glTF_Exporter.Utils - { - using System; - using System.Collections.Generic; - using System.Linq; - using Autodesk.Revit.DB; - using Common_glTF_Exporter.Core; - using Common_glTF_Exporter.Model; - using Common_glTF_Exporter.Windows.MainWindow; - using Revit_glTF_Exporter; - - public class GLTFExportUtils +namespace Common_glTF_Exporter.Utils +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Autodesk.Revit.DB; + using Common_glTF_Exporter.Core; + using Common_glTF_Exporter.Model; + using Common_glTF_Exporter.Windows.MainWindow; + using glTF.Manipulator.GenericSchema; + using glTF.Manipulator.Schema; + using Revit_glTF_Exporter; + using Buffer = glTF.Manipulator.Schema.Buffer; + public class GLTFExportUtils { const int DEF_COLOR = 250; const string DEF_MATERIAL_NAME = "default"; - const string DEF_UNIQUEL_ID = "8a3c94b3-d9e2-4e57-9189-f9bb6a9a54a4"; + public const string DEF_UNIQUEL_ID = "8a3c94b3-d9e2-4e57-9189-f9bb6a9a54a4"; - public static GLTFMaterial GetGLTFMaterial(IndexedDictionary gltfMaterials, double opacity, bool doubleSided) + public static BaseMaterial GetGLTFMaterial(IndexedDictionary Materials) { - - if (gltfMaterials.Dict.ContainsKey(DEF_UNIQUEL_ID)) - { - return gltfMaterials.GetElement(DEF_UNIQUEL_ID); - } - else - { - return (CreateDefaultGLTFMaterial((int)opacity, doubleSided)); - } + return Materials.GetElement(DEF_UNIQUEL_ID); } - public static GLTFMaterial CreateDefaultGLTFMaterial(int materialOpacity, bool doubleSided) + public static BaseMaterial CreateDefaultGLTFMaterial(int materialOpacity, bool doubleSided) { - GLTFMaterial gl_mat = new GLTFMaterial(); - gl_mat.doubleSided = doubleSided; + BaseMaterial baseMaterial = new BaseMaterial(); + baseMaterial.doubleSided = doubleSided; float opacity = 1 - (float)materialOpacity; - gl_mat.name = DEF_MATERIAL_NAME; - GLTFPBR pbr = new GLTFPBR(); - pbr.baseColorFactor = new List(4) { 1f, 1f, 1f, opacity }; - pbr.metallicFactor = 0f; - pbr.roughnessFactor = 1f; - gl_mat.pbrMetallicRoughness = pbr; - gl_mat.UniqueId = DEF_UNIQUEL_ID; - - return gl_mat; + baseMaterial.name = DEF_MATERIAL_NAME; + baseMaterial.baseColorFactor = new List(4) { 1f, 1f, 1f, opacity }; + baseMaterial.metallicFactor = 0f; + baseMaterial.roughnessFactor = 1f; + baseMaterial.uuid = DEF_UNIQUEL_ID; + + return baseMaterial; } public static void AddVerticesAndFaces( @@ -63,12 +55,14 @@ public static void AddOrUpdateCurrentItem( Element element, IndexedDictionary geomDataObj, IndexedDictionary vertexIntObj, - GLTFMaterial material) + BaseMaterial material) { - - // Add new "_current" entries if vertex_key is unique - string vertex_key = string.Concat(element.UniqueId, UNDERSCORE, material.UniqueId); + string vertex_key = element.Id.ToString() + "_" + material.uuid; geomDataObj.AddOrUpdateCurrent(vertex_key, new GeometryDataObject()); + geomDataObj.CurrentItem.MaterialInfo = new MaterialInfo + { + uuid = material.uuid + }; vertexIntObj.AddOrUpdateCurrent(vertex_key, new VertexLookupIntObject()); } @@ -84,72 +78,6 @@ public static void AddRPCNormals(Preferences preferences, MeshTriangle triangle, } } - const string BIN = ".bin"; - - /// - /// Takes the intermediate geometry data and performs the calculations - /// to convert that into glTF buffers, views, and accessors. - /// - /// buffers. - /// accessors. - /// bufferViews. - /// geomData. - /// Unique name for the .bin file that will be produced. - /// Revit element's Element ID that will be used as the batchId value. - /// exportBatchId. - /// exportNormals. - /// Returns the GLTFBinaryData object. - public static GLTFBinaryData AddGeometryMeta( - List buffers, - List accessors, - List bufferViews, - GeometryDataObject geomData, - string name, - long elementId, - Preferences preferences, - GLTFMaterial material, - List images, - List textures) - { - - int byteOffset = 0; - - // add a buffer - GLTFBuffer buffer = new GLTFBuffer(); - buffer.uri = string.Concat(name, BIN); - buffers.Add(buffer); - int bufferIdx = buffers.Count - 1; - GLTFBinaryData bufferData = new GLTFBinaryData(); - bufferData.name = buffer.uri; - - - byteOffset = GLTFBinaryDataUtils.ExportVertices(bufferIdx, byteOffset, geomData, bufferData, bufferViews, accessors, out int sizeOfVec3View, out int elementsPerVertex); - - if (preferences.normals) - { - byteOffset = GLTFBinaryDataUtils.ExportNormals(bufferIdx, byteOffset, geomData, bufferData, bufferViews, accessors); - } - - if (preferences.materials == MaterialsEnum.textures && - material.pbrMetallicRoughness?.baseColorTexture != null && geomData.Uvs.Count != 0) - { - byteOffset = GLTFBinaryDataUtils.ExportImageBuffer(bufferIdx, byteOffset, material, images, textures, bufferData, bufferViews); - byteOffset = GLTFBinaryDataUtils.ExportUVs(bufferIdx, byteOffset, geomData, bufferData, bufferViews, accessors); - - } - - if (preferences.batchId) - { - byteOffset = GLTFBinaryDataUtils.ExportBatchId(bufferIdx, byteOffset, sizeOfVec3View, elementsPerVertex, elementId, geomData, bufferData, bufferViews, accessors); - } - - byteOffset = GLTFBinaryDataUtils.ExportFaces(bufferIdx, byteOffset, geomData, bufferData, bufferViews, accessors); - - buffers[bufferIdx].byteLength = byteOffset; - - return bufferData; - } - public static void AddNormals(Transform transform, PolymeshTopology polymesh, List normals) { diff --git a/Common_glTF_Exporter/Version/LatestVersion.cs b/Common_glTF_Exporter/Version/LatestVersion.cs index 2267dfb..0e075d8 100644 --- a/Common_glTF_Exporter/Version/LatestVersion.cs +++ b/Common_glTF_Exporter/Version/LatestVersion.cs @@ -1,9 +1,8 @@ -using Autodesk.Revit.UI; -using Common_glTF_Exporter.Model; +using Common_glTF_Exporter.Model; using Common_glTF_Exporter.Utils; -using Revit_glTF_Exporter; using System; using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; @@ -29,7 +28,12 @@ public static async Task Get() HttpContent content = result.Content; string myContent = await content.ReadAsStringAsync(); - Payload payload = Newtonsoft.Json.JsonConvert.DeserializeObject(myContent); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + Payload payload = JsonSerializer.Deserialize(myContent, options); if (!payload.Update) { diff --git a/Common_glTF_Exporter/ViewModel/ProgressBarWindowViewModel.cs b/Common_glTF_Exporter/ViewModel/ProgressBarWindowViewModel.cs index 8e9795f..00d33f1 100644 --- a/Common_glTF_Exporter/ViewModel/ProgressBarWindowViewModel.cs +++ b/Common_glTF_Exporter/ViewModel/ProgressBarWindowViewModel.cs @@ -60,9 +60,17 @@ public double ProgressBarValue } this.progressBarValue = value; - ProgressBarPercentage = (value / ProgressBarMax) * 100; - if (ProgressBarPercentage > 100) + + double percentageProgress = (value / ProgressBarMax) * 100; + if (percentageProgress > 99) + { ProgressBarPercentage = 100; + } + else + { + ProgressBarPercentage = (value / ProgressBarMax) * 100; + } + this.OnPropertyChanged(); } } diff --git a/Common_glTF_Exporter/Windows/MainWindow.xaml.cs b/Common_glTF_Exporter/Windows/MainWindow.xaml.cs index 58203a0..c47d3df 100644 --- a/Common_glTF_Exporter/Windows/MainWindow.xaml.cs +++ b/Common_glTF_Exporter/Windows/MainWindow.xaml.cs @@ -91,9 +91,10 @@ private void OnExportView(object sender, RoutedEventArgs e) int incrementRun = numberRuns + 1; SettingsConfig.SetValue("runs", incrementRun.ToString()); - ExportLog.Write($"{elementsInView.Count} elements will be exported"); + int elemInView = elementsInView.Count; + ExportLog.Write($"{elemInView} elements will be exported"); ProgressBarWindow progressBar = - ProgressBarWindow.Create(elementsInView.Count + 1, 0, "Converting elements...", this); + ProgressBarWindow.Create(elemInView + 1, 0, "Converting elements...", this); // Use our custom implementation of IExportContext as the exporter context. GLTFExportContext ctx = new GLTFExportContext(doc); @@ -110,8 +111,8 @@ private void OnExportView(object sender, RoutedEventArgs e) Analytics.Send("exported", SettingsConfig.GetValue("format")).GetAwaiter(); Thread.Sleep(500); - ProgressBarWindow.ViewModel.ProgressBarValue = elementsInView.Count + 1; - ProgressBarWindow.ViewModel.ProgressBarPercentage = 100; + + ProgressBarWindow.ViewModel.ProgressBarValue = elemInView; ProgressBarWindow.ViewModel.Message = "Export completed!"; ExportLog.EndLog(); ProgressBarWindow.ViewModel.Action = "Accept"; diff --git a/Common_glTF_Exporter/Windows/ProgressBarWindow.xaml.cs b/Common_glTF_Exporter/Windows/ProgressBarWindow.xaml.cs index 0752852..36634af 100644 --- a/Common_glTF_Exporter/Windows/ProgressBarWindow.xaml.cs +++ b/Common_glTF_Exporter/Windows/ProgressBarWindow.xaml.cs @@ -31,11 +31,12 @@ public static ProgressBarWindow Create(double maxValue, double currentValue, { mainWin = mainWindow; var progressBar = new ProgressBarWindow(); - ProgressBarWindow.ViewModel.ProgressBarGraphicValue = maxValue * 0.07; + double maxValueDuplicated = maxValue; + ProgressBarWindow.ViewModel.ProgressBarGraphicValue = maxValueDuplicated * 0.07; ProgressBarWindow.ViewModel.ProgressBarValue = currentValue; ProgressBarWindow.ViewModel.Message = message; ProgressBarWindow.ViewModel.Action = "Cancel"; - ProgressBarWindow.ViewModel.ProgressBarMax = maxValue; + ProgressBarWindow.ViewModel.ProgressBarMax = maxValueDuplicated; ProgressBarWindow.ViewModel.ProgressBarPercentage = 0; progressBar.Show(); ProgressBarWindow.MainView.Topmost = true; diff --git a/GltfInstaller/Program.cs b/GltfInstaller/Program.cs index 050259c..26ecd91 100644 --- a/GltfInstaller/Program.cs +++ b/GltfInstaller/Program.cs @@ -33,7 +33,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2019\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2019\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2019\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2020", @@ -44,7 +44,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2020\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2020\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2020\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2021", @@ -55,7 +55,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2021\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2021\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2021\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2022", @@ -66,7 +66,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2022\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2022\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2022\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2023", @@ -77,7 +77,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2023\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2023\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2023\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2024", @@ -88,7 +88,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2024\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2024\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2024\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)) ), new Dir(@"2025", @@ -99,7 +99,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2025\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2025\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2025\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2025\bin\Release\Leia_glTF_Exporter.deps.json", new FilePermission("Everyone", GenericPermission.All)) @@ -112,7 +112,7 @@ static void Main() new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2026\bin\Release\MeshOpt.dll", new FilePermission("Everyone", GenericPermission.All)), - new File(@"..\Revit_glTF_Exporter_2026\bin\Release\Newtonsoft.Json.dll", + new File(@"..\Revit_glTF_Exporter_2026\bin\Release\glTF.Manipulator.dll", new FilePermission("Everyone", GenericPermission.All)), new File(@"..\Revit_glTF_Exporter_2026\bin\Release\Leia_glTF_Exporter.deps.json", new FilePermission("Everyone", GenericPermission.All)) diff --git a/Revit_glTF_Exporter_2019/Revit_glTF_Exporter_2019.csproj b/Revit_glTF_Exporter_2019/Revit_glTF_Exporter_2019.csproj index 1ee545d..37b8cd0 100644 --- a/Revit_glTF_Exporter_2019/Revit_glTF_Exporter_2019.csproj +++ b/Revit_glTF_Exporter_2019/Revit_glTF_Exporter_2019.csproj @@ -73,10 +73,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - 2019.0.1 all diff --git a/Revit_glTF_Exporter_2020/Revit_glTF_Exporter_2020.csproj b/Revit_glTF_Exporter_2020/Revit_glTF_Exporter_2020.csproj index f0cfe3d..984daa8 100644 --- a/Revit_glTF_Exporter_2020/Revit_glTF_Exporter_2020.csproj +++ b/Revit_glTF_Exporter_2020/Revit_glTF_Exporter_2020.csproj @@ -123,10 +123,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - 2020.0.1 all diff --git a/Revit_glTF_Exporter_2021/Revit_glTF_Exporter_2021.csproj b/Revit_glTF_Exporter_2021/Revit_glTF_Exporter_2021.csproj index bee217d..d8f6f6d 100644 --- a/Revit_glTF_Exporter_2021/Revit_glTF_Exporter_2021.csproj +++ b/Revit_glTF_Exporter_2021/Revit_glTF_Exporter_2021.csproj @@ -73,10 +73,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - 2021.1.4 all diff --git a/Revit_glTF_Exporter_2022/Revit_glTF_Exporter_2022.csproj b/Revit_glTF_Exporter_2022/Revit_glTF_Exporter_2022.csproj index 95e2227..4b78e21 100644 --- a/Revit_glTF_Exporter_2022/Revit_glTF_Exporter_2022.csproj +++ b/Revit_glTF_Exporter_2022/Revit_glTF_Exporter_2022.csproj @@ -73,10 +73,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - 2022.1.0 all diff --git a/Revit_glTF_Exporter_2023/Revit_glTF_Exporter_2023.csproj b/Revit_glTF_Exporter_2023/Revit_glTF_Exporter_2023.csproj index 594a8a8..f3cc80e 100644 --- a/Revit_glTF_Exporter_2023/Revit_glTF_Exporter_2023.csproj +++ b/Revit_glTF_Exporter_2023/Revit_glTF_Exporter_2023.csproj @@ -75,12 +75,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - - 13.0.1 - 2023.0.0 all diff --git a/Revit_glTF_Exporter_2024/Revit_glTF_Exporter_2024.csproj b/Revit_glTF_Exporter_2024/Revit_glTF_Exporter_2024.csproj index 4a2d88c..f2855b9 100644 --- a/Revit_glTF_Exporter_2024/Revit_glTF_Exporter_2024.csproj +++ b/Revit_glTF_Exporter_2024/Revit_glTF_Exporter_2024.csproj @@ -66,12 +66,12 @@ 3.3.4 + + 2025.11.24.2122 + 1.1.0 - - 13.0.1 - 2024.0.0 all diff --git a/Revit_glTF_Exporter_2025/Revit_glTF_Exporter_2025.csproj b/Revit_glTF_Exporter_2025/Revit_glTF_Exporter_2025.csproj index fcc2f82..36d1bc4 100644 --- a/Revit_glTF_Exporter_2025/Revit_glTF_Exporter_2025.csproj +++ b/Revit_glTF_Exporter_2025/Revit_glTF_Exporter_2025.csproj @@ -75,9 +75,9 @@ 4 + - diff --git a/Revit_glTF_Exporter_2026/Revit_glTF_Exporter_2026.csproj b/Revit_glTF_Exporter_2026/Revit_glTF_Exporter_2026.csproj index f175fe1..f85c047 100644 --- a/Revit_glTF_Exporter_2026/Revit_glTF_Exporter_2026.csproj +++ b/Revit_glTF_Exporter_2026/Revit_glTF_Exporter_2026.csproj @@ -75,9 +75,9 @@ 4 + -