Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ContentRepresentation #1044

Merged
merged 5 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
- `Profile.ThickenedEdgePolygons`
- `Elements.MEP`
- `GeometricElement.RepresentationInstances`
- `ContentRepresentation`

### Fixed

Expand Down
11 changes: 8 additions & 3 deletions Elements/src/CoreModels/ElementRepresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Elements;
using Elements.Geometry;
using glTFLoader.Schema;
using System;
using Elements.Serialization.glTF;

/// <summary>
/// The element's representation
Expand All @@ -13,13 +13,18 @@ public abstract class ElementRepresentation : SharedObject
/// Get graphics buffers and other metadata required to modify a GLB.
/// </summary>
/// <param name="element">The element with this representation.</param>
/// <param name="graphicsBuffers">The list of graphc buffers.</param>
/// <param name="graphicsBuffers">The list of graphic buffers.</param>
/// <param name="id">The buffer id. It will be used as a primitive name.</param>
/// <param name="mode">The gltf primitive mode</param>
/// <returns>
/// True if there is graphicsbuffers data applicable to add, false otherwise.
/// True if there is graphics buffers data applicable to add, false otherwise.
/// Out variables should be ignored if the return value is false.
/// </returns>
public abstract bool TryToGraphicsBuffers(GeometricElement element, out List<GraphicsBuffers> graphicsBuffers,
out string id, out MeshPrimitive.ModeEnum? mode);

internal virtual List<NodeExtension> GetNodeExtensions(GeometricElement element)
{
return new List<NodeExtension>();
}
}
87 changes: 87 additions & 0 deletions Elements/src/Representations/ContentRepresentation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Collections.Generic;
using Elements.Geometry;
using Elements.Geometry.Solids;
using Elements.Serialization.glTF;
using Elements.Utilities;
using glTFLoader.Schema;

namespace Elements
{
/// <summary>
/// Represents an element as a reference to a GLB file location within the content catalog.
/// </summary>
public class ContentRepresentation : ElementRepresentation
{
/// <summary>The URI of the glb for this element.</summary>
public string GlbLocation { get; set; }

/// <summary>The bounding box of the content.</summary>
public BBox3 BoundingBox { get; set; }

/// <summary>
/// Initializes a new instance of ContentRepresentation class
/// </summary>
/// <param name="glbLocation">The URI of the glb for this element.</param>
/// <param name="boundingBox">The bounding box of the content.</param>
public ContentRepresentation(string glbLocation, BBox3 boundingBox)
{
GlbLocation = glbLocation;
BoundingBox = boundingBox;
}

/// <summary>
/// Initializes a new instance of ContentRepresentation class
/// </summary>
/// <param name="glbLocation">The URI of the glb for this element.</param>
public ContentRepresentation(string glbLocation) : this(glbLocation, default) { }

/// <inheritdoc/>
public override bool TryToGraphicsBuffers(GeometricElement element, out List<GraphicsBuffers> graphicsBuffers, out string id, out MeshPrimitive.ModeEnum? mode)
{
id = element.Id + "_mesh";

graphicsBuffers = new List<GraphicsBuffers>();
mode = MeshPrimitive.ModeEnum.TRIANGLES;

if (!BoundingBox.IsValid() || BoundingBox.IsDegenerate())
{
return true;
}

var bottomProfile = new Geometry.Polygon(new List<Vector3>{
new Vector3(BoundingBox.Min.X, BoundingBox.Min.Y, BoundingBox.Min.Z),
new Vector3(BoundingBox.Min.X, BoundingBox.Max.Y, BoundingBox.Min.Z),
new Vector3(BoundingBox.Max.X, BoundingBox.Max.Y, BoundingBox.Min.Z),
new Vector3(BoundingBox.Max.X, BoundingBox.Min.Y, BoundingBox.Min.Z),
});

var height = BoundingBox.Max.Z - BoundingBox.Min.Z;
var boxSolid = new Extrude(bottomProfile, height, Vector3.ZAxis, false);

var csg = SolidOperationUtils.GetFinalCsgFromSolids(new List<SolidOperation>() { boxSolid }, element, false);

if (csg == null)
{
return false;
}

GraphicsBuffers buffers = null;
buffers = csg.Tessellate();

if (buffers.Vertices.Count == 0)
{
return false;
}

graphicsBuffers.Add(buffers);
return true;
}

internal override List<NodeExtension> GetNodeExtensions(GeometricElement element)
{
var extensions = base.GetNodeExtensions(element);
extensions.Add(new NodeExtension("HYPAR_referenced_content", "contentUrl", GlbLocation));
return extensions;
}
}
}
47 changes: 34 additions & 13 deletions Elements/src/Serialization/glTF/GltfExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ internal static Gltf InitializeGlTF(Model model,
errors.Add(new ElementError(e.Id, ex));
}
}
if (allBuffers.Sum(b => b.Count()) + buffer.Count == 0 && lights.Count == 0)
if (allBuffers.Sum(b => b.Count()) + buffer.Count == 0 && lights.Count == 0 && nodes.Count < 1)
{
return null;
}
Expand Down Expand Up @@ -1292,7 +1292,7 @@ private static void GetRenderDataForElement(Element e,
var elementNodeId = NodeUtilities.AddInstanceNode(nodes, element.Transform, element.Id);
foreach (var representation in element.RepresentationInstances)
{
// get the unique id that contains representation Id and opening Ids
// get the unique id that contains representation Id and opening Ids
int combinedId = representation.GetHashCode(element);

if (representationsMap.TryGetValue(combinedId, out var mesh))
Expand All @@ -1302,31 +1302,52 @@ private static void GetRenderDataForElement(Element e,
{
NodeUtilities.SetRepresentationInfo(nodes[index], representation);
NodeUtilities.SetElementInfo(nodes[index], element.Id);
foreach (var nodeExtension in representation.Representation.GetNodeExtensions(element))
{
AddExtension(gltf, nodes[index], nodeExtension.Name, nodeExtension.Attributes);
}
}
}
else if (representation.Representation.TryToGraphicsBuffers(geometricElement, out var graphicsBuffers,
out var bufferId, out var mode))
{
meshId = AddMesh(bufferId,
buffer,
bufferViews,
accessors,
materialIndexMap[representation.Material.Id.ToString()],
graphicsBuffers,
(MeshPrimitive.ModeEnum)mode,
meshes);
var addedNodes = new List<int>();
if (graphicsBuffers.Any())
{
meshId = AddMesh(bufferId,
buffer,
bufferViews,
accessors,
materialIndexMap[representation.Material.Id.ToString()],
graphicsBuffers,
(MeshPrimitive.ModeEnum)mode,
meshes);

if (meshId != -1)
{
var meshIdList = new List<int> { meshId };
representationsMap.Add(combinedId, meshIdList);
addedNodes.AddRange(NodeUtilities.AddNodes(nodes, meshIdList, elementNodeId));
}
}
else
{
meshId = NodeUtilities.AddEmptyNode(nodes, elementNodeId);
addedNodes.Add(meshId);
}

// If the id == -1, the mesh is malformed.
// It may have no geometry.
if (meshId != -1)
{
var meshIdList = new List<int> { meshId };
representationsMap.Add(combinedId, meshIdList);
var addedNodes = NodeUtilities.AddNodes(nodes, meshIdList, elementNodeId);
foreach (var index in addedNodes)
{
NodeUtilities.SetRepresentationInfo(nodes[index], representation);
NodeUtilities.SetElementInfo(nodes[index], element.Id);
foreach (var nodeExtension in representation.Representation.GetNodeExtensions(element))
{
AddExtension(gltf, nodes[index], nodeExtension.Name, nodeExtension.Attributes);
}
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions Elements/src/Serialization/glTF/NodeExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Collections.Generic;

namespace Elements.Serialization.glTF
{
internal class NodeExtension
{
public NodeExtension(string name, Dictionary<string, object> attributes)
{
Name = name;
Attributes = attributes;
}

public NodeExtension(string name)
{
Name = name;
}

public NodeExtension(string name, string attributeName, object attributeValue)
{
Name = name;
Attributes.Add(attributeName, attributeValue);
}

public string Name { get; set; }

public Dictionary<string, object> Attributes { get; } = new Dictionary<string, object>();
}
}
5 changes: 5 additions & 0 deletions Elements/src/Serialization/glTF/NodeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ internal static int AddInstanceNode(List<glTFLoader.Schema.Node> nodes, Transfor
return AddNode(nodes, newNode, 0);
}

internal static int AddEmptyNode(List<glTFLoader.Schema.Node> nodes, int parentId)
{
return AddNode(nodes, new Node(), parentId);
}

internal static int[] AddInstanceNode(
List<glTFLoader.Schema.Node> nodes,
List<int> meshIds,
Expand Down
Loading