Skip to content

Commit

Permalink
Merge pull request #812 from hypar-io/tess-boost
Browse files Browse the repository at this point in the history
16% memory reduction and small speed improvements for glTF creation.
  • Loading branch information
ikeough authored Aug 12, 2022
2 parents f89e275 + acc58a4 commit ea464c6
Show file tree
Hide file tree
Showing 24 changed files with 277 additions and 174 deletions.
12 changes: 7 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
## 1.2.0

### Added
- `Polygon(IList<Vector3> @vertices, bool disableValidation = false)`
- `Polygon(bool disableValidation, params Vector3[] vertices)`
- `Polyline(IList<Vector3> @vertices, bool disableValidation = false)`
- `Polyline(bool disableValidation, params Vector3[] vertices)`
- `Mesh.Intersects(Ray)` (same as `Ray.Intersects(Mesh)`)
- `Ray.NearbyPoints()`
- `PointOctree<T>`
Expand All @@ -21,6 +25,7 @@
- Fixed a bug where `Polyline.Frames` would return inconsistently-oriented transforms.
- `Obstacle.FromBox` works properly with `AdaptiveGrid` transformation.
- `AdaptiveGrid.SubtractObstacle` worked incorrectly in `AdaptiveGrid.Boundary` had elevation.
- #805

## 1.1.0

Expand Down Expand Up @@ -79,11 +84,6 @@
- `ContinuousDimension`
- `Vector3.AreCollinearByAngle(Vector3 a, Vector3 b, Vector3 c, double tolerance)`


### Fixed

- #805

### Fixed

- `Line.IsCollinear(Line line)` would return `false` if lines are close to each other but not collinear
Expand All @@ -92,11 +92,13 @@
- `Line.GetUParameter(Vector 3)` - calculate U parameter for point on line
- `Line.MergeCollinearLine(Line line)` creates new line containing all four collinear vertices
- `Line.Projected(Plane plane)` create new line projected onto plane
- `Profile.Split` would sometimes fail if the profile being split contained voids.

### Changed

- Simplified `IEnumerable<Vector3>.ToGraphicsBuffers()`
- `TryToGraphicsBuffers` is now public
- `Solid SweepFaceAlongCurve` now has an additional parameter, `profileRotation`, which enables the caller to pass a profile rotation into sweep creation.

## 1.0.0

Expand Down
1 change: 1 addition & 0 deletions Elements.Benchmarks/Trace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public void TraceModelCreation()
}

[EventPipeProfiler(EventPipeProfile.CpuSampling)]
[MemoryDiagnoser]
[SimpleJob]
public class TraceGltfSerialization
{
Expand Down
10 changes: 8 additions & 2 deletions Elements/src/Geometry/Bezier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,19 @@ public override BBox3 Bounds()
/// </summary>
/// <param name="startSetback"></param>
/// <param name="endSetback"></param>
/// <returns></returns>
public override Transform[] Frames(double startSetback = 0, double endSetback = 0)
/// <param name="additionalRotation"></param>
public override Transform[] Frames(double startSetback = 0,
double endSetback = 0,
double additionalRotation = 0.0)
{
var transforms = new Transform[_samples + 1];
for (var i = 0; i <= _samples; i++)
{
transforms[i] = TransformAt(i * 1.0 / _samples);
if (additionalRotation != 0.0)
{
transforms[i].RotateAboutPoint(transforms[i].Origin, transforms[i].ZAxis, additionalRotation);
}
}
return transforms;
}
Expand Down
2 changes: 1 addition & 1 deletion Elements/src/Geometry/Circle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Polygon ToPolygon(int divisions = 10)
{
pts[i] = this.PointAt((double)i / (double)divisions);
}
return new Polygon(pts);
return new Polygon(pts, true);
}
}
}
10 changes: 2 additions & 8 deletions Elements/src/Geometry/CsgExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,19 @@ internal static void Tessellate(this Csg.Solid csg, ref Mesh mesh)
/// appropriate for use with gltf.
/// </summary>
internal static GraphicsBuffers Tessellate(this Csg.Solid csg,
bool mergeVertices = false,
Func<(Vector3, Vector3, UV, Color), (Vector3, Vector3, UV, Color)> modifyVertexAttributes = null)
{
return Tessellate(new[] { csg }, mergeVertices, modifyVertexAttributes);
return Tessellate(new[] { csg }, modifyVertexAttributes);
}

/// <summary>
/// Triangulate a collection of CSGs and pack the triangulated data into
/// buffers appropriate for use with gltf.
/// </summary>
internal static GraphicsBuffers Tessellate(this Csg.Solid[] csgs,
bool mergeVertices = false,
Func<(Vector3, Vector3, UV, Color), (Vector3, Vector3, UV, Color)> modifyVertexAttributes = null)
{
var buffers = new GraphicsBuffers();

Tessellation.Tessellation.Tessellate(csgs.Select(csg => new CsgTessellationTargetProvider(csg)),
buffers,
mergeVertices,
var buffers = Tessellation.Tessellation.Tessellate<GraphicsBuffers>(csgs.Select(csg => new CsgTessellationTargetProvider(csg)),
modifyVertexAttributes);
return buffers;
}
Expand Down
9 changes: 8 additions & 1 deletion Elements/src/Geometry/Curve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ public abstract partial class Curve : ICurve, ITransformable<Curve>
/// </summary>
/// <param name="startSetback">The offset parameter from the start of the curve.</param>
/// <param name="endSetback">The offset parameter from the end of the curve.</param>
/// <param name="additionalRotation">An additional rotation of the frame at each point.</param>
/// <returns>A collection of transforms.</returns>
public virtual Transform[] Frames(double startSetback = 0.0, double endSetback = 0.0)
public virtual Transform[] Frames(double startSetback = 0.0,
double endSetback = 0.0,
double additionalRotation = 0.0)
{
var parameters = GetSampleParameters(startSetback, endSetback);
var transforms = new Transform[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
transforms[i] = TransformAt(parameters[i]);
if (additionalRotation != 0.0)
{
transforms[i].RotateAboutPoint(transforms[i].Origin, transforms[i].ZAxis, additionalRotation);
}
}
return transforms;
}
Expand Down
119 changes: 54 additions & 65 deletions Elements/src/Geometry/GraphicsBuffers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,101 +4,81 @@
namespace Elements.Geometry
{
/// <summary>
/// A generic container for graphics data. This is broken out primarily to facilitate
/// simpler testing of graphics buffers.
/// A container for graphics data.
/// The buffers used in this class align with webgl requirements.
/// </summary>
internal interface IGraphicsBuffers
public class GraphicsBuffers : IGraphicsBuffers
{
/// <summary>
/// Add a vertex to the graphics buffers.
/// </summary>
/// <param name="position">The position of the vertex.</param>
/// <param name="normal">The normal of the vertex.</param>
/// <param name="uv">The UV of the vertex.</param>
/// <param name="color">The vertex color.</param>
void AddVertex(Vector3 position, Vector3 normal, UV uv, Color? color = null);

/// <summary>
/// Add a vertex to the graphics buffers.
/// The number of vertices represented by the buffer.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="z"></param>
/// <param name="nx"></param>
/// <param name="ny"></param>
/// <param name="nz"></param>
/// <param name="u"></param>
/// <param name="v"></param>
/// <param name="color"></param>
void AddVertex(double x, double y, double z, double nx, double ny, double nz, double u, double v, Color? color = null);
public int VertexCount
{
get { return this.Vertices.Count / sizeof(float) / 3; }
}

/// <summary>
/// Add an index to the graphics buffers.
/// The number of facets represeted by the buffer.
/// </summary>
/// <param name="index">The index to add.</param>
void AddIndex(ushort index);
}
public int FacetCount
{
get { return this.Indices.Count / sizeof(ushort) / 3; }
}

/// <summary>
/// A container for graphics data.
/// The buffers used in this class align with webgl requirements.
/// </summary>
public class GraphicsBuffers : IGraphicsBuffers
{
/// <summary>
/// A collection of vertex positions stored as sequential bytes.
/// </summary>
public List<byte> Vertices { get; }
public List<byte> Vertices { get; private set; }

/// <summary>
/// A collection of indices stored as sequential bytes.
/// </summary>
public List<byte> Indices { get; }
public List<byte> Indices { get; private set; }

/// <summary>
/// A collection of sequential normal values stored as sequential bytes.
/// </summary>
public List<byte> Normals { get; }
public List<byte> Normals { get; private set; }

/// <summary>
/// A collection of sequential color values stored as sequential bytes.
/// </summary>
public List<byte> Colors { get; }
public List<byte> Colors { get; private set; }

/// <summary>
/// A collection of UV values stored as sequential bytes.
/// </summary>
public List<byte> UVs { get; }
public List<byte> UVs { get; private set; }

/// <summary>
/// The maximum of the axis-aligned bounding box of the data as [x,y,z].
/// </summary>
public double[] VMax { get; }
public double[] VMax { get; private set; }

/// <summary>
/// The minimum of the axis-aligned bounding box of the data as [x,y,z].
/// </summary>
public double[] VMin { get; }
public double[] VMin { get; private set; }

/// <summary>
/// The minimum normal of the data as [x,y,z].
/// </summary>
public double[] NMin { get; }
public double[] NMin { get; private set; }

/// <summary>
/// The maximum normal of the data as [x,y,z].
/// </summary>
public double[] NMax { get; }
public double[] NMax { get; private set; }

/// <summary>
/// The minimum color value as [r,g,b].
/// </summary>
public double[] CMin { get; }
public double[] CMin { get; private set; }

/// <summary>
/// The maximum color value as [r,g,b].
/// </summary>
public double[] CMax { get; }
public double[] CMax { get; private set; }

/// <summary>
/// The maximum index value.
Expand All @@ -113,36 +93,19 @@ public class GraphicsBuffers : IGraphicsBuffers
/// <summary>
/// The maximum UV value as [u,v].
/// </summary>
public double[] UVMin { get; }
public double[] UVMin { get; private set; }

/// <summary>
/// The maximum UV value as [u,v].
/// </summary>
public double[] UVMax { get; }
public double[] UVMax { get; private set; }

/// <summary>
/// Construct an empty graphics buffers object.
/// </summary>
public GraphicsBuffers()
{
// Initialize everything
this.Vertices = new List<byte>();
this.Normals = new List<byte>();
this.Indices = new List<byte>();
this.UVs = new List<byte>();
this.Colors = new List<byte>();

this.CMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };
this.CMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };

this.VMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };
this.VMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };

this.NMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };
this.NMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };

this.UVMin = new double[2] { double.MaxValue, double.MaxValue };
this.UVMax = new double[2] { double.MinValue, double.MinValue };
Initialize();
}

/// <summary>
Expand Down Expand Up @@ -201,7 +164,7 @@ public void AddVertex(double x, double y, double z, double nx, double ny, double
this.UVMin[0] = Math.Min(this.UVMin[0], u);
this.UVMin[1] = Math.Min(this.UVMin[1], v);

if (color.HasValue && color.Value != default(Color))
if (color.HasValue && color.Value != default)
{
this.CMax[0] = Math.Max(this.CMax[0], color.Value.Red);
this.CMax[1] = Math.Max(this.CMax[1], color.Value.Green);
Expand All @@ -227,5 +190,31 @@ public void AddIndex(ushort index)
this.IMin = Math.Min(this.IMin, index);
}

/// <summary>
/// Initialize the graphics buffer to a known size.
/// </summary>
/// <param name="vertexCount">The number of vertices.</param>
/// <param name="indexCount">The number of indices.</param>
public void Initialize(int vertexCount = 0, int indexCount = 0)
{
// Initialize everything
this.Vertices = new List<byte>(sizeof(float) * 3 * vertexCount);
this.Normals = new List<byte>(sizeof(float) * 3 * vertexCount);
this.Indices = new List<byte>(sizeof(ushort) * indexCount);
this.UVs = new List<byte>(sizeof(float) * 2 * vertexCount);
this.Colors = new List<byte>(sizeof(float) * 3 * vertexCount);

this.CMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };
this.CMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };

this.VMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };
this.VMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };

this.NMin = new double[3] { double.MaxValue, double.MaxValue, double.MaxValue };
this.NMax = new double[3] { double.MinValue, double.MinValue, double.MinValue };

this.UVMin = new double[2] { double.MaxValue, double.MaxValue };
this.UVMax = new double[2] { double.MinValue, double.MinValue };
}
}
}
47 changes: 47 additions & 0 deletions Elements/src/Geometry/IGraphicsBuffers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Elements.Geometry;

namespace Elements
{
/// <summary>
/// A generic container for graphics data. This is broken out primarily to facilitate
/// simpler testing of graphics buffers.
/// </summary>
internal interface IGraphicsBuffers
{
/// <summary>
/// Initialize a graphics buffer to a sepcific vertex size.
/// </summary>
/// <param name="vertexCount">The number of vertices.</param>
/// <param name="indexCount">The number of indices.</param>
void Initialize(int vertexCount, int indexCount);

/// <summary>
/// Add a vertex to the graphics buffers.
/// </summary>
/// <param name="position">The position of the vertex.</param>
/// <param name="normal">The normal of the vertex.</param>
/// <param name="uv">The UV of the vertex.</param>
/// <param name="color">The vertex color.</param>
void AddVertex(Vector3 position, Vector3 normal, UV uv, Color? color = null);

/// <summary>
/// Add a vertex to the graphics buffers.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="z"></param>
/// <param name="nx"></param>
/// <param name="ny"></param>
/// <param name="nz"></param>
/// <param name="u"></param>
/// <param name="v"></param>
/// <param name="color"></param>
void AddVertex(double x, double y, double z, double nx, double ny, double nz, double u, double v, Color? color = null);

/// <summary>
/// Add an index to the graphics buffers.
/// </summary>
/// <param name="index">The index to add.</param>
void AddIndex(ushort index);
}
}
Loading

0 comments on commit ea464c6

Please sign in to comment.