Skip to content

Commit

Permalink
Use System.Numerics.Vector3 instead of custom Point type for built-in…
Browse files Browse the repository at this point in the history
… SIMD operation support.

Further changes:
 - Updated to .NET Standard 2.1 / .NET Framework 4.6 project.
 - Added README to NuGet package.
 - Removed Travis CI.
  • Loading branch information
mcserep committed Apr 11, 2022
1 parent 14d69d2 commit ace84b2
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 466 deletions.
15 changes: 0 additions & 15 deletions .travis.yml

This file was deleted.

6 changes: 3 additions & 3 deletions Octree.sln
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.489
# Visual Studio Version 16
VisualStudioVersion = 16.0.32228.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octree", "Octree\Octree.csproj", "{B6B62BB9-05AF-40AF-81C7-B72355C09C34}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Octree", "Octree\Octree.csproj", "{B6B62BB9-05AF-40AF-81C7-B72355C09C34}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
13 changes: 7 additions & 6 deletions Octree/BoundsOctree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
namespace Octree
{
using System.Collections.Generic;
using System.Numerics;
using NLog;

/// <summary>
/// A Dynamic, Loose Octree for storing any objects that can be described with AABB bounds
/// </summary>
/// <seealso cref="BoundsOctree{T}"/>
/// <seealso cref="PointOctree{T}"/>
/// <remarks>
/// Octree: An octree is a tree data structure which divides 3D space into smaller partitions (nodes)
/// and places objects into the appropriate nodes. This allows fast access to objects
Expand All @@ -31,7 +32,7 @@ namespace Octree
/// they actually give much better performance than using Foreach, even in the compiled build.
/// Using a LINQ expression is worse again than Foreach.
///
/// See also: PointOctree, where objects are stored as single points and some code can be simplified
/// See also: <see cref="PointOctree{T}"/>, where objects are stored as single points and some code can be simplified
/// </remarks>
/// <typeparam name="T">The content of the octree can be anything, since the bounds data is supplied separately.</typeparam>
public partial class BoundsOctree<T>
Expand Down Expand Up @@ -85,7 +86,7 @@ public BoundingBox MaxBounds
/// <param name="initialWorldPos">Position of the center of the initial node.</param>
/// <param name="minNodeSize">Nodes will stop splitting if the new nodes would be smaller than this (metres).</param>
/// <param name="loosenessVal">Clamped between 1 and 2. Values > 1 let nodes overlap.</param>
public BoundsOctree(float initialWorldSize, Point initialWorldPos, float minNodeSize, float loosenessVal)
public BoundsOctree(float initialWorldSize, Vector3 initialWorldPos, float minNodeSize, float loosenessVal)
{
if (minNodeSize > initialWorldSize)
{
Expand Down Expand Up @@ -215,15 +216,15 @@ public void GetColliding(List<T> collidingWith, Ray checkRay, float maxDistance
/// Grow the octree to fit in all objects.
/// </summary>
/// <param name="direction">Direction to grow.</param>
private void Grow(Point direction)
private void Grow(Vector3 direction)
{
int xDirection = direction.X >= 0 ? 1 : -1;
int yDirection = direction.Y >= 0 ? 1 : -1;
int zDirection = direction.Z >= 0 ? 1 : -1;
Node oldRoot = _rootNode;
float half = _rootNode.BaseLength / 2;
float newLength = _rootNode.BaseLength * 2;
Point newCenter = _rootNode.Center + new Point(xDirection * half, yDirection * half, zDirection * half);
Vector3 newCenter = _rootNode.Center + new Vector3(xDirection * half, yDirection * half, zDirection * half);

// Create a new, bigger octree root node
_rootNode = new Node(newLength, _minSize, _looseness, newCenter);
Expand All @@ -248,7 +249,7 @@ private void Grow(Point direction)
oldRoot.BaseLength,
_minSize,
_looseness,
newCenter + new Point(xDirection * half, yDirection * half, zDirection * half));
newCenter + new Vector3(xDirection * half, yDirection * half, zDirection * half));
}
}

Expand Down
45 changes: 23 additions & 22 deletions Octree/BoundsOctreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace Octree
{
using System.Collections.Generic;
using System.Numerics;
using NLog;

public partial class BoundsOctree<T>
Expand All @@ -25,7 +26,7 @@ private class Node
/// <summary>
/// Centre of this node
/// </summary>
public Point Center { get; private set; }
public Vector3 Center { get; private set; }

/// <summary>
/// Length of this node if it has a looseness of 1.0
Expand Down Expand Up @@ -114,7 +115,7 @@ public BoundingBox Bounds
/// <param name="minSizeVal">Minimum size of nodes in this octree.</param>
/// <param name="loosenessVal">Multiplier for baseLengthVal to get the actual size.</param>
/// <param name="centerVal">Centre position of this node.</param>
public Node(float baseLengthVal, float minSizeVal, float loosenessVal, Point centerVal)
public Node(float baseLengthVal, float minSizeVal, float loosenessVal, Vector3 centerVal)
{
SetValues(baseLengthVal, minSizeVal, loosenessVal, centerVal);
}
Expand Down Expand Up @@ -444,7 +445,7 @@ public Node ShrinkIfPossible(float minLength)
/// </summary>
/// <param name="objBoundsCenter">The object's bounds center.</param>
/// <returns>One of the eight child octants.</returns>
public int BestFitChild(Point objBoundsCenter)
public int BestFitChild(Vector3 objBoundsCenter)
{
return (objBoundsCenter.X <= Center.X ? 0 : 1)
+ (objBoundsCenter.Y >= Center.Y ? 0 : 4)
Expand Down Expand Up @@ -479,7 +480,7 @@ public bool HasAnyObjects()
/// <param name="minSizeVal">Minimum size of nodes in this octree.</param>
/// <param name="loosenessVal">Multiplier for baseLengthVal to get the actual size.</param>
/// <param name="centerVal">Center position of this node.</param>
private void SetValues(float baseLengthVal, float minSizeVal, float loosenessVal, Point centerVal)
private void SetValues(float baseLengthVal, float minSizeVal, float loosenessVal, Vector3 centerVal)
{
BaseLength = baseLengthVal;
_minSize = minSizeVal;
Expand All @@ -488,21 +489,21 @@ private void SetValues(float baseLengthVal, float minSizeVal, float loosenessVal
_adjLength = _looseness * baseLengthVal;

// Create the bounding box.
Point size = new Point(_adjLength, _adjLength, _adjLength);
Vector3 size = new Vector3(_adjLength, _adjLength, _adjLength);
_bounds = new BoundingBox(Center, size);

float quarter = BaseLength / 4f;
float childActualLength = (BaseLength / 2) * _looseness;
Point childActualSize = new Point(childActualLength, childActualLength, childActualLength);
Vector3 childActualSize = new Vector3(childActualLength, childActualLength, childActualLength);
_childBounds = new BoundingBox[8];
_childBounds[0] = new BoundingBox(Center + new Point(-quarter, quarter, -quarter), childActualSize);
_childBounds[1] = new BoundingBox(Center + new Point(quarter, quarter, -quarter), childActualSize);
_childBounds[2] = new BoundingBox(Center + new Point(-quarter, quarter, quarter), childActualSize);
_childBounds[3] = new BoundingBox(Center + new Point(quarter, quarter, quarter), childActualSize);
_childBounds[4] = new BoundingBox(Center + new Point(-quarter, -quarter, -quarter), childActualSize);
_childBounds[5] = new BoundingBox(Center + new Point(quarter, -quarter, -quarter), childActualSize);
_childBounds[6] = new BoundingBox(Center + new Point(-quarter, -quarter, quarter), childActualSize);
_childBounds[7] = new BoundingBox(Center + new Point(quarter, -quarter, quarter), childActualSize);
_childBounds[0] = new BoundingBox(Center + new Vector3(-quarter, quarter, -quarter), childActualSize);
_childBounds[1] = new BoundingBox(Center + new Vector3(quarter, quarter, -quarter), childActualSize);
_childBounds[2] = new BoundingBox(Center + new Vector3(-quarter, quarter, quarter), childActualSize);
_childBounds[3] = new BoundingBox(Center + new Vector3(quarter, quarter, quarter), childActualSize);
_childBounds[4] = new BoundingBox(Center + new Vector3(-quarter, -quarter, -quarter), childActualSize);
_childBounds[5] = new BoundingBox(Center + new Vector3(quarter, -quarter, -quarter), childActualSize);
_childBounds[6] = new BoundingBox(Center + new Vector3(-quarter, -quarter, quarter), childActualSize);
_childBounds[7] = new BoundingBox(Center + new Vector3(quarter, -quarter, quarter), childActualSize);
}

/// <summary>
Expand Down Expand Up @@ -617,42 +618,42 @@ private void Split()
newLength,
_minSize,
_looseness,
Center + new Point(-quarter, quarter, -quarter));
Center + new Vector3(-quarter, quarter, -quarter));
_children[1] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(quarter, quarter, -quarter));
Center + new Vector3(quarter, quarter, -quarter));
_children[2] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(-quarter, quarter, quarter));
Center + new Vector3(-quarter, quarter, quarter));
_children[3] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(quarter, quarter, quarter));
Center + new Vector3(quarter, quarter, quarter));
_children[4] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(-quarter, -quarter, -quarter));
Center + new Vector3(-quarter, -quarter, -quarter));
_children[5] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(quarter, -quarter, -quarter));
Center + new Vector3(quarter, -quarter, -quarter));
_children[6] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(-quarter, -quarter, quarter));
Center + new Vector3(-quarter, -quarter, quarter));
_children[7] = new Node(
newLength,
_minSize,
_looseness,
Center + new Point(quarter, -quarter, quarter));
Center + new Vector3(quarter, -quarter, quarter));
}

/// <summary>
Expand Down
27 changes: 14 additions & 13 deletions Octree/Data/BoundingBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace Octree
{
using System;
using System.Numerics;
using System.Runtime.Serialization;

/// <summary>
Expand All @@ -24,18 +25,18 @@ public struct BoundingBox
/// Gets or sets the center of the bounding box.
/// </summary>
[DataMember]
public Point Center { get; set; }
public Vector3 Center { get; set; }

/// <summary>
/// Gets or sets the extents of the bounding box. This is always half of the <see cref="Size"/>.
/// </summary>
[DataMember]
public Point Extents { get; set; }
public Vector3 Extents { get; set; }

/// <summary>
/// Gets or sets the size of the bounding box. This is always twice as large as the <see cref="Extents"/>.
/// </summary>
public Point Size
public Vector3 Size
{
get { return Extents * 2; }
set { Extents = value * 0.5f; }
Expand All @@ -47,7 +48,7 @@ public Point Size
/// <remarks>
/// This is always equal to <c>center-extents</c>.
/// </remarks>
public Point Min
public Vector3 Min
{
get { return Center - Extents; }
set { SetMinMax(value, Max); }
Expand All @@ -59,7 +60,7 @@ public Point Min
/// <remarks>
/// This is always equal to <c>center+extents</c>.
/// </remarks>
public Point Max
public Vector3 Max
{
get { return Center + Extents; }
set { SetMinMax(Min, value); }
Expand All @@ -70,7 +71,7 @@ public Point Max
/// </summary>
/// <param name="center">The center of the box.</param>
/// <param name="size">The size of the box.</param>
public BoundingBox(Point center, Point size)
public BoundingBox(Vector3 center, Vector3 size)
{
Center = center;
Extents = size * 0.5f;
Expand All @@ -81,7 +82,7 @@ public BoundingBox(Point center, Point size)
/// </summary>
/// <param name="min">The minimal point.</param>
/// <param name="max">The maximal point.</param>
public void SetMinMax(Point min, Point max)
public void SetMinMax(Vector3 min, Vector3 max)
{
Extents = (max - min) * 0.5f;
Center = min + Extents;
Expand All @@ -91,9 +92,9 @@ public void SetMinMax(Point min, Point max)
/// Grows the bounding box include the point.
/// </summary>
/// <param name="point">The specified point to include.</param>
public void Encapsulate(Point point)
public void Encapsulate(Vector3 point)
{
SetMinMax(Point.Min(Min, point), Point.Max(Max, point));
SetMinMax(Vector3.Min(Min, point), Vector3.Max(Max, point));
}

/// <summary>
Expand All @@ -113,14 +114,14 @@ public void Encapsulate(BoundingBox box)
public void Expand(float amount)
{
amount *= 0.5f;
Extents += new Point(amount, amount, amount);
Extents += new Vector3(amount, amount, amount);
}

/// <summary>
/// Expands the bounds by increasing its <see cref="Size"/> by <paramref name="amount"/> along each side.
/// </summary>
/// <param name="amount">The expansions for each dimension in order.</param>
public void Expand(Point amount)
public void Expand(Vector3 amount)
{
Extents += amount * 0.5f;
}
Expand All @@ -130,7 +131,7 @@ public void Expand(Point amount)
/// </summary>
/// <param name="point">The point to test.</param>
/// <returns><c>true</c> if the box contains the point; otherwise, <c>false</c>.</returns>
public bool Contains(Point point)
public bool Contains(Vector3 point)
{
return
Min.X <= point.X && Max.X >= point.X &&
Expand Down Expand Up @@ -170,7 +171,7 @@ public bool IntersectRay(Ray ray)
/// <returns><c>true</c> if the box intersects with the ray, <c>false</c> otherwise.</returns>
public bool IntersectRay(Ray ray, out float distance)
{
Point dirFrac = new Point(
Vector3 dirFrac = new Vector3(
1f / ray.Direction.X,
1f / ray.Direction.Y,
1f / ray.Direction.Z
Expand Down
Loading

0 comments on commit ace84b2

Please sign in to comment.