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 triangle adapter. #2

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
67 changes: 67 additions & 0 deletions Adapters/BVHTriangleAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using UnityEngine;
using System;
using System.Collections.Generic;


namespace DataStructures {
public interface Triangle {
Vector3 a { get; set; }
Vector3 b { get; set; }
Vector3 c { get; set; }
}

public class BVHRayHitTest {
public BVHRayHitTest(Ray _ray) {
ray = _ray;
}
public bool NodeTraversalTest(Bounds box) => box.IntersectRay(ray);
public Ray ray { get; set; }
}

public class BVHTriangleAdapter : IBVHNodeAdapter<Triangle> {
private BVH<Triangle> _bvh;
private Dictionary<Triangle, BVHNode<Triangle>> triangeToLeafMap = new Dictionary<Triangle, BVHNode<Triangle>>();


BVH<Triangle> IBVHNodeAdapter<Triangle>.BVH { get => _bvh; set { _bvh = value; }}

public void CheckMap(Triangle triangle) {
if (!triangeToLeafMap.ContainsKey(triangle)) {
throw new Exception("missing map for shuffled child!");
}
}

public BVHNode<Triangle> GetLeaf(Triangle triangle) => triangeToLeafMap[triangle];
public Vector3 GetObjectPos(Triangle triangle) {
float x = (triangle.a.x + triangle.b.x + triangle.c.x) / 3.0f;
float y = (triangle.a.y + triangle.b.y + triangle.c.y) / 3.0f;
float z = (triangle.a.z + triangle.b.z + triangle.c.z) / 3.0f;
return new Vector3(x, y, z);
}

public float GetRadius(Triangle triangle) {
Vector3 centroid = new Vector3(
(triangle.a.x + triangle.b.x + triangle.c.x) / 3.0f,
(triangle.a.y + triangle.b.y + triangle.c.y) / 3.0f,
(triangle.a.z + triangle.b.z + triangle.c.z) / 3.0f
);
return Mathf.Max(
Mathf.Max(Vector3.Distance(centroid, triangle.a), Vector3.Distance(centroid, triangle.b),
Vector3.Distance(centroid, triangle.c)));
}

public void MapObjectToBVHLeaf(Triangle triangle, BVHNode<Triangle> node) {
triangeToLeafMap[triangle] = node;
}

public void OnPositionOrSizeChanged(Triangle changed)
{
// the SSObject has changed, so notify the BVH leaf to refit for the object
triangeToLeafMap[changed].RefitObjectChanged(this, changed);
}

public void UnmapObject(Triangle triangle) {
triangeToLeafMap.Remove(triangle);
}
}
}
11 changes: 11 additions & 0 deletions Adapters/BVHTriangleAdapter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 61 additions & 1 deletion BVH.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class BVH<T>
public BVHNode<T> rootBVH;
public IBVHNodeAdapter<T> nAda;
public readonly int LEAF_OBJ_MAX;
public readonly float MIN_NODE_VOLUME;
public int nodeCount = 0;
public int maxDepth = 0;

Expand All @@ -79,6 +80,38 @@ public List<BVHNode<T>> Traverse(NodeTraversalTest hitTest)
return hits;
}

public SortedList<float, BVHNode<T>> SortedTraverse(NodeTraversalTest hitTest) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please double check the curly braces are following the same convention across the project
As far as I know they should be on a newline

SortedList<float, BVHNode<T>> sortedHit = new SortedList<float, BVHNode<T>>();
void traverse(BVHNode<T> node, NodeTraversalTest hitTest, SortedList<float, BVHNode<T>> hitList) {
if (node == null) return;
if (hitTest(node.Box)) {
hitList[Vector3.Magnitude(node.Box.size)] = node;
traverse(node.Left, hitTest, hitList);
traverse(node.Right, hitTest, hitList);
}
}
traverse(rootBVH, hitTest, sortedHit);
return sortedHit;
}

public bool IntersectRay(Ray ray, out BVHNode<T> nodeHit) {
BVHNode<T> _hit = null;
void traverse(BVHNode<T> node) {
if (node == null) return;
if (node.Box.IntersectRay(ray)) {
if (node.IsLeaf) {
_hit = node;
return;
}
traverse(node.Left);
traverse(node.Right);
}
}
traverse(rootBVH);
nodeHit = _hit;
return nodeHit != null && nodeHit.IsLeaf;
}

/*
public List<BVHNode<T> Traverse(Ray ray)
{
Expand Down Expand Up @@ -159,9 +192,10 @@ public int CountBVHNodes()
/// <param name="nodeAdaptor"></param>
/// <param name="objects"></param>
/// <param name="LEAF_OBJ_MAX">WARNING! currently this must be 1 to use dynamic BVH updates</param>
public BVH(IBVHNodeAdapter<T> nodeAdaptor, List<T> objects, int LEAF_OBJ_MAX = 1)
public BVH(IBVHNodeAdapter<T> nodeAdaptor, List<T> objects, int LEAF_OBJ_MAX = 1, float MIN_NODE_VOLUME = 0.7f)
{
this.LEAF_OBJ_MAX = LEAF_OBJ_MAX;
this.MIN_NODE_VOLUME = MIN_NODE_VOLUME;
nodeAdaptor.BVH = this;
this.nAda = nodeAdaptor;

Expand Down Expand Up @@ -202,6 +236,26 @@ public void GetAllNodeMatriciesRecursive(BVHNode<T> n, ref List<Matrix4x4> matri
if (n.Left != null) GetAllNodeMatriciesRecursive(n.Left, ref matricies, depth + 1);
}

public Matrix4x4 GetNodeMatrix(BVHNode<T> node) => Matrix4x4.Translate(node.Box.center) * Matrix4x4.Scale(node.Box.size);


public void RenderNode(BVHNode<T> node) {
Matrix4x4 mat = GetNodeMatrix(node);
List<Matrix4x4> matrices = new List<Matrix4x4>();
matrices.Add(mat);
Mesh mesh = new Mesh();
mesh.SetVertices(vertices);
mesh.SetIndices(indices, MeshTopology.Lines, 0);
if(_debugRenderMaterial == null)
{
_debugRenderMaterial = new Material(Shader.Find("Standard"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this compatible with SRP?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will test this to make sure it is and will come back to you :)

{
enableInstancing = true
};
}
Graphics.DrawMeshInstanced(mesh, 0, _debugRenderMaterial, matrices);
}

public void RenderDebug()
{
if (!SystemInfo.supportsInstancing)
Expand All @@ -225,6 +279,12 @@ public void RenderDebug()
enableInstancing = true
};
}

int iterations = (int)Mathf.Floor((float)matricies.Count / 1023.0f);
for (int i = 0; i < iterations; i++) {
Graphics.DrawMeshInstanced(mesh, 0, _debugRenderMaterial, matricies.GetRange(0, 1023));
matricies.RemoveRange(0, 1023);
}
Graphics.DrawMeshInstanced(mesh, 0, _debugRenderMaterial, matricies);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be removed after adding the split draw or are both calls necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both calls would be necessary as the for-loop should only execute when the limit is exceeded, which often occurs when each triangle in a scene has its own AABB.

}
}
Expand Down
7 changes: 4 additions & 3 deletions BVHNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -903,10 +903,11 @@ private BVHNode(BVH<T> bvh, BVHNode<T> lparent, List<T> gobjectlist, Axis lastSp
// if we have more than (bvh.LEAF_OBJECT_COUNT) objects, then compute the volume and split
GObjects = gobjectlist;
ComputeVolume(nAda);
SplitNode(nAda);
ChildRefit(nAda, propagate: false);
if (Box.size.magnitude > bvh.MIN_NODE_VOLUME) {
SplitNode(nAda);
ChildRefit(nAda, propagate: false);
}
}
}

}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Unity Bounding Volume Heirachy
# Unity Bounding Volume Hierachy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄 Whoops


![BVH GIF](https://media.giphy.com/media/ZaomLtyboZSp9zl6WY/giphy.gif)

Expand Down