Skip to content

Commit

Permalink
Merge pull request #1044 from hypar-io/content_representation
Browse files Browse the repository at this point in the history
Added ContentRepresentation
  • Loading branch information
katehryhorenko authored Oct 30, 2023
2 parents 82071df + 0796541 commit eb7aef0
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 16 deletions.
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

0 comments on commit eb7aef0

Please sign in to comment.