重新导入obi
This commit is contained in:
8
Assets/Obi/Scripts/Common/DataStructures/ASDF.meta
Normal file
8
Assets/Obi/Scripts/Common/DataStructures/ASDF.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 645b177bec2c444aaa188661f611418a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
187
Assets/Obi/Scripts/Common/DataStructures/ASDF/ASDF.cs
Normal file
187
Assets/Obi/Scripts/Common/DataStructures/ASDF/ASDF.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ASDF
|
||||
{
|
||||
static readonly Vector4[] corners =
|
||||
{
|
||||
new Vector4(-1,-1,-1,-1),
|
||||
new Vector4(-1,-1,1,-1),
|
||||
new Vector4(-1,1,-1,-1),
|
||||
new Vector4(-1,1,1,-1),
|
||||
|
||||
new Vector4(1,-1,-1,-1),
|
||||
new Vector4(1,-1,1,-1),
|
||||
new Vector4(1,1,-1,-1),
|
||||
new Vector4(1,1,1,-1)
|
||||
};
|
||||
|
||||
static readonly Vector4[] samples =
|
||||
{
|
||||
new Vector4(0,0,0,0),
|
||||
new Vector4(1,0,0,0),
|
||||
new Vector4(-1,0,0,0),
|
||||
new Vector4(0,1,0,0),
|
||||
new Vector4(0,-1,0,0),
|
||||
new Vector4(0,0,1,0),
|
||||
new Vector4(0,0,-1,0),
|
||||
|
||||
new Vector4(0,-1,-1,0),
|
||||
new Vector4(0,-1,1,0),
|
||||
new Vector4(0,1,-1,0),
|
||||
new Vector4(0,1,1,0),
|
||||
|
||||
new Vector4(-1,0,-1,0),
|
||||
new Vector4(-1,0,1,0),
|
||||
new Vector4(1,0,-1,0),
|
||||
new Vector4(1,0,1,0),
|
||||
|
||||
new Vector4(-1,-1,0,0),
|
||||
new Vector4(-1,1,0,0),
|
||||
new Vector4(1,-1,0,0),
|
||||
new Vector4(1,1,0,0)
|
||||
};
|
||||
|
||||
const float sqrt3 = 1.73205f;
|
||||
|
||||
public static IEnumerator Build(float maxError, int maxDepth, Vector3[] vertexPositions, int[] triangleIndices, List<DFNode> nodes, int yieldAfterNodeCount = 32)
|
||||
{
|
||||
// Empty vertex or triangle lists, return.
|
||||
if (maxDepth <= 0 ||
|
||||
nodes == null ||
|
||||
vertexPositions == null || vertexPositions.Length == 0 ||
|
||||
triangleIndices == null || triangleIndices.Length == 0)
|
||||
yield break;
|
||||
|
||||
// Build a bounding interval hierarchy from the triangles, to speed up distance queries:
|
||||
IBounded[] t = new IBounded[triangleIndices.Length / 3];
|
||||
for (int i = 0; i < t.Length; ++i)
|
||||
{
|
||||
int t1 = triangleIndices[i * 3];
|
||||
int t2 = triangleIndices[i * 3 + 1];
|
||||
int t3 = triangleIndices[i * 3 + 2];
|
||||
t[i] = new Triangle(t1, t2, t3, vertexPositions[t1], vertexPositions[t2], vertexPositions[t3]);
|
||||
}
|
||||
var bih = BIH.Build(ref t);
|
||||
|
||||
// Copy reordered triangles over to a new array:
|
||||
Triangle[] tris = Array.ConvertAll(t, x => (Triangle)x);
|
||||
|
||||
// Build angle weighted normals, used to determine the sign of the distance field.
|
||||
Vector3[] angleNormals = ObiUtils.CalculateAngleWeightedNormals(vertexPositions,triangleIndices);
|
||||
|
||||
// Calculate bounding box of the mesh:
|
||||
Bounds bounds = new Bounds(vertexPositions[0], Vector3.zero);
|
||||
for (int i = 1; i < vertexPositions.Length; ++i)
|
||||
bounds.Encapsulate(vertexPositions[i]);
|
||||
|
||||
bounds.Expand(0.2f);
|
||||
|
||||
// Auxiliar variables to keep track of current tree depth:
|
||||
int depth = 0;
|
||||
int nodesToNextLevel = 1;
|
||||
|
||||
// Initialize node list:
|
||||
Vector4 center = bounds.center;
|
||||
Vector3 boundsExtents = bounds.extents;
|
||||
center[3] = Mathf.Max(boundsExtents[0], Math.Max(boundsExtents[1], boundsExtents[2]));
|
||||
nodes.Clear();
|
||||
nodes.Add(new DFNode(center));
|
||||
|
||||
|
||||
var queue = new Queue<int>();
|
||||
queue.Enqueue(0);
|
||||
|
||||
int processedNodeCount = 0;
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
// get current node:
|
||||
int index = queue.Dequeue();
|
||||
var node = nodes[index];
|
||||
|
||||
// measure distance at the 8 node corners:
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
Vector4 point = node.center + corners[i] * node.center[3];
|
||||
point[3] = 0;
|
||||
float distance = BIH.DistanceToSurface(bih, tris, vertexPositions,angleNormals,point);
|
||||
|
||||
if (i < 4)
|
||||
node.distancesA[i] = distance;
|
||||
else
|
||||
node.distancesB[i - 4] = distance;
|
||||
}
|
||||
|
||||
// only subdivide those nodes intersecting the surface:
|
||||
if (depth < maxDepth && Mathf.Abs(BIH.DistanceToSurface(bih, tris, vertexPositions, angleNormals, node.center)) < node.center[3] * sqrt3)
|
||||
{
|
||||
|
||||
// calculate mean squared error between measured distances and interpolated ones:
|
||||
float mse = 0;
|
||||
for (int i = 0; i < samples.Length; ++i)
|
||||
{
|
||||
Vector4 point = node.center + samples[i] * node.center[3];
|
||||
float groundTruth = BIH.DistanceToSurface(bih, tris, vertexPositions, angleNormals, point);
|
||||
float estimation = node.Sample(point);
|
||||
float d = groundTruth - estimation;
|
||||
mse += d * d;
|
||||
}
|
||||
mse /= (float)samples.Length;
|
||||
|
||||
// if error > threshold, subdivide the node:
|
||||
if (mse > maxError)
|
||||
{
|
||||
node.firstChild = nodes.Count;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
queue.Enqueue(nodes.Count);
|
||||
nodes.Add(new DFNode(node.center + corners[i] * node.center[3] * 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
// keep track of current depth:
|
||||
if (--nodesToNextLevel == 0)
|
||||
{
|
||||
depth++;
|
||||
nodesToNextLevel = queue.Count;
|
||||
}
|
||||
}
|
||||
|
||||
// feed the modified node back:
|
||||
nodes[index] = node;
|
||||
|
||||
// if we've processed enough nodes, yield.
|
||||
if (nodes.Count - processedNodeCount >= yieldAfterNodeCount)
|
||||
{
|
||||
processedNodeCount = nodes.Count;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float Sample(List<DFNode> nodes, Vector3 position)
|
||||
{
|
||||
if (nodes != null && nodes.Count > 0)
|
||||
{
|
||||
var queue = new Queue<int>();
|
||||
queue.Enqueue(0);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
// get current node:
|
||||
var node = nodes[queue.Dequeue()];
|
||||
|
||||
if (node.firstChild > -1)
|
||||
queue.Enqueue(node.firstChild + node.GetOctant(position));
|
||||
else
|
||||
return node.Sample(position);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/ASDF/ASDF.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/ASDF/ASDF.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6951f2457b77d4daf9f257e128b6dfb2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
65
Assets/Obi/Scripts/Common/DataStructures/ASDF/DFNode.cs
Normal file
65
Assets/Obi/Scripts/Common/DataStructures/ASDF/DFNode.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public struct DFNode
|
||||
{
|
||||
public Vector4 distancesA;
|
||||
public Vector4 distancesB;
|
||||
public Vector4 center;
|
||||
public int firstChild;
|
||||
|
||||
// add 12 bytes of padding to ensure correct memory alignment:
|
||||
private int pad0;
|
||||
private int pad1;
|
||||
private int pad2;
|
||||
|
||||
public DFNode(Vector4 center)
|
||||
{
|
||||
this.distancesA = Vector4.zero;
|
||||
this.distancesB = Vector4.zero;
|
||||
this.center = center;
|
||||
this.firstChild = -1;
|
||||
this.pad0 = 0;
|
||||
this.pad1 = 0;
|
||||
this.pad2 = 0;
|
||||
}
|
||||
|
||||
public float Sample(Vector3 position)
|
||||
{
|
||||
Vector3 nPos = GetNormalizedPos(position);
|
||||
|
||||
// trilinear interpolation: interpolate along x axis
|
||||
Vector4 x = distancesA + (distancesB - distancesA) * nPos[0];
|
||||
|
||||
// interpolate along y axis
|
||||
float y0 = x[0] + (x[2] - x[0]) * nPos[1];
|
||||
float y1 = x[1] + (x[3] - x[1]) * nPos[1];
|
||||
|
||||
// interpolate along z axis.
|
||||
return y0 + (y1 - y0) * nPos[2];
|
||||
}
|
||||
|
||||
public Vector3 GetNormalizedPos(Vector3 position)
|
||||
{
|
||||
float size = center[3] * 2;
|
||||
return new Vector3(
|
||||
(position[0] - (center[0] - center[3])) / size,
|
||||
(position[1] - (center[1] - center[3])) / size,
|
||||
(position[2] - (center[2] - center[3])) / size
|
||||
);
|
||||
}
|
||||
|
||||
public int GetOctant(Vector3 position)
|
||||
{
|
||||
int index = 0;
|
||||
if (position[0] > center[0]) index |= 4;
|
||||
if (position[1] > center[1]) index |= 2;
|
||||
if (position[2] > center[2]) index |= 1;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/ASDF/DFNode.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/ASDF/DFNode.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 769e6e9ced39347bc96146f1858ab648
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
53
Assets/Obi/Scripts/Common/DataStructures/Aabb.cs
Normal file
53
Assets/Obi/Scripts/Common/DataStructures/Aabb.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct Aabb
|
||||
{
|
||||
public Vector4 min;
|
||||
public Vector4 max;
|
||||
|
||||
public Vector4 center
|
||||
{
|
||||
get { return min + (max - min) * 0.5f; }
|
||||
}
|
||||
|
||||
public Vector4 size
|
||||
{
|
||||
get { return max - min; }
|
||||
}
|
||||
|
||||
public Aabb(Vector4 min, Vector4 max)
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public Aabb(Vector4 point)
|
||||
{
|
||||
this.min = point;
|
||||
this.max = point;
|
||||
}
|
||||
|
||||
public void Encapsulate(Vector4 point)
|
||||
{
|
||||
min = Vector4.Min(min, point);
|
||||
max = Vector4.Max(max, point);
|
||||
}
|
||||
|
||||
public void Encapsulate(Aabb other)
|
||||
{
|
||||
min = Vector4.Min(min, other.min);
|
||||
max = Vector4.Max(max, other.max);
|
||||
}
|
||||
|
||||
public void FromBounds(Bounds bounds, float thickness, bool is2D = false)
|
||||
{
|
||||
Vector3 s = Vector3.one * thickness;
|
||||
min = bounds.min - s;
|
||||
max = bounds.max + s;
|
||||
if (is2D)
|
||||
max[2] = min[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/Aabb.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/Aabb.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b6d58d9b0a8a4f7ea09067526d713cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/Obi/Scripts/Common/DataStructures/AffineTransform.cs
Normal file
34
Assets/Obi/Scripts/Common/DataStructures/AffineTransform.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct AffineTransform
|
||||
{
|
||||
public Vector4 translation;
|
||||
public Vector4 scale;
|
||||
public Quaternion rotation;
|
||||
|
||||
public AffineTransform(Vector4 translation, Quaternion rotation, Vector4 scale)
|
||||
{
|
||||
// make sure there are good values in the 4th component:
|
||||
translation[3] = 0;
|
||||
scale[3] = 1;
|
||||
|
||||
this.translation = translation;
|
||||
this.rotation = rotation;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public void FromTransform(Transform source, bool is2D = false)
|
||||
{
|
||||
translation = source.position;
|
||||
rotation = source.rotation;
|
||||
scale = source.lossyScale;
|
||||
|
||||
if (is2D)
|
||||
{
|
||||
translation[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c8eff617709c457a85387e2f72187aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Obi/Scripts/Common/DataStructures/BVH.meta
Normal file
8
Assets/Obi/Scripts/Common/DataStructures/BVH.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d141c0731e7c43e8be29d786670298c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
262
Assets/Obi/Scripts/Common/DataStructures/BVH/BIH.cs
Normal file
262
Assets/Obi/Scripts/Common/DataStructures/BVH/BIH.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class BIH
|
||||
{
|
||||
public static BIHNode[] Build(ref IBounded[] elements, int maxDepth = 10, float maxOverlap = 0.7f)
|
||||
{
|
||||
List<BIHNode> nodes = new List<BIHNode>{ new BIHNode(0, elements.Length) };
|
||||
|
||||
// auxiliar variables to keep track of current tree depth:
|
||||
int depth = 0;
|
||||
int nodesToNextLevel = 1;
|
||||
|
||||
var queue = new Queue<int>();
|
||||
queue.Enqueue(0);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
// get current node:
|
||||
int index = queue.Dequeue();
|
||||
var node = nodes[index];
|
||||
|
||||
// if this node contains enough elements, split it:
|
||||
if (node.count > 2)
|
||||
{
|
||||
int start = node.start;
|
||||
int end = start + (node.count - 1);
|
||||
|
||||
// calculate bounding box of all elements:
|
||||
Aabb b = elements[start].GetBounds();
|
||||
for (int k = start + 1; k <= end; ++k)
|
||||
b.Encapsulate(elements[k].GetBounds());
|
||||
|
||||
// determine split axis (longest one):
|
||||
Vector3 size = b.size;
|
||||
int axis = node.axis = (size.x > size.y) ?
|
||||
(size.x > size.z ? 0 : 2) :
|
||||
(size.y > size.z ? 1 : 2);
|
||||
|
||||
// place split plane at half the longest axis:
|
||||
float pivot = b.min[axis] + size[axis] * 0.5f;
|
||||
|
||||
// partition elements according to which side of the split plane they're at:
|
||||
int j = HoarePartition(elements, start, end, pivot, ref node, axis);
|
||||
|
||||
// create two child nodes:
|
||||
var minChild = new BIHNode(start, j - start + 1);
|
||||
var maxChild = new BIHNode(j + 1, end - j);
|
||||
|
||||
// calculate child overlap:
|
||||
float overlap = size[axis] > 0 ? Mathf.Max(node.min - node.max, 0) / size[axis] : 1;
|
||||
|
||||
// guard against cases where all elements are on one side of the split plane,
|
||||
// due to all having the same or very similar bounds as the entire group.
|
||||
if (overlap <= maxOverlap && minChild.count > 0 && maxChild.count > 0)
|
||||
{
|
||||
node.firstChild = nodes.Count;
|
||||
nodes[index] = node;
|
||||
|
||||
queue.Enqueue(nodes.Count);
|
||||
queue.Enqueue(nodes.Count + 1);
|
||||
|
||||
// append child nodes to list:
|
||||
nodes.Add(minChild);
|
||||
nodes.Add(maxChild);
|
||||
}
|
||||
|
||||
// keep track of current depth:
|
||||
if (--nodesToNextLevel == 0)
|
||||
{
|
||||
depth++;
|
||||
if (depth >= maxDepth)
|
||||
return nodes.ToArray();
|
||||
nodesToNextLevel = queue.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes.ToArray();
|
||||
}
|
||||
|
||||
public static int HoarePartition(IBounded[] elements, int start, int end, float pivot, ref BIHNode node, int axis)
|
||||
{
|
||||
int i = start;
|
||||
int j = end;
|
||||
|
||||
while (i <= j)
|
||||
{
|
||||
while (i < end && elements[i].GetBounds().center[axis] < pivot)
|
||||
node.min = Mathf.Max(node.min, elements[i++].GetBounds().max[axis]);
|
||||
|
||||
while (j > start && elements[j].GetBounds().center[axis] > pivot)
|
||||
node.max = Mathf.Min(node.max, elements[j--].GetBounds().min[axis]);
|
||||
|
||||
if (i <= j)
|
||||
{
|
||||
node.min = Mathf.Max(node.min, elements[j].GetBounds().max[axis]);
|
||||
node.max = Mathf.Min(node.max, elements[i].GetBounds().min[axis]);
|
||||
ObiUtils.Swap(ref elements[i++], ref elements[j--]);
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
public static float DistanceToSurface(Triangle[] triangles,
|
||||
Vector3[] vertices,
|
||||
Vector3[] normals,
|
||||
in BIHNode node,
|
||||
in Vector3 point)
|
||||
{
|
||||
float minDistance = float.MaxValue;
|
||||
int sign = 1;
|
||||
|
||||
Vector3 pointOnTri;
|
||||
Vector3 interpolatedNormal;
|
||||
|
||||
for (int i = node.start; i < node.start + node.count; ++i)
|
||||
{
|
||||
Triangle t = triangles[i];
|
||||
|
||||
|
||||
ObiUtils.NearestPointOnTri(in vertices[t.i1],
|
||||
in vertices[t.i2],
|
||||
in vertices[t.i3],
|
||||
in point,
|
||||
out pointOnTri);
|
||||
|
||||
Vector3 pointToTri = point - pointOnTri;
|
||||
float sqrDistance = pointToTri.sqrMagnitude;
|
||||
|
||||
if (sqrDistance < minDistance)
|
||||
{
|
||||
Vector3 bary = Vector3.zero;
|
||||
ObiUtils.BarycentricCoordinates(in vertices[t.i1], in vertices[t.i2], in vertices[t.i3], in pointOnTri, ref bary);
|
||||
ObiUtils.BarycentricInterpolation(in normals[t.i1],
|
||||
in normals[t.i2],
|
||||
in normals[t.i3],
|
||||
in bary,
|
||||
out interpolatedNormal);
|
||||
|
||||
sign = ObiUtils.PureSign(pointToTri.x * interpolatedNormal.x +
|
||||
pointToTri.y * interpolatedNormal.y +
|
||||
pointToTri.z * interpolatedNormal.z);
|
||||
|
||||
minDistance = sqrDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return Mathf.Sqrt(minDistance) * sign;
|
||||
}
|
||||
|
||||
public static float DistanceToSurface(BIHNode[] nodes,
|
||||
Triangle[] triangles,
|
||||
Vector3[] vertices,
|
||||
Vector3[] normals,
|
||||
in Vector3 point)
|
||||
{
|
||||
|
||||
if (nodes.Length > 0)
|
||||
return DistanceToSurface(nodes, triangles, vertices, normals, in nodes[0], in point);
|
||||
|
||||
return float.MaxValue;
|
||||
}
|
||||
|
||||
public static float DistanceToSurface(BIHNode[] nodes,
|
||||
Triangle[] triangles,
|
||||
Vector3[] vertices,
|
||||
Vector3[] normals,
|
||||
in BIHNode node,
|
||||
in Vector3 point)
|
||||
{
|
||||
|
||||
float MinSignedDistance(float d1, float d2)
|
||||
{
|
||||
return (Mathf.Abs(d1) < Mathf.Abs(d2)) ? d1 : d2;
|
||||
}
|
||||
|
||||
if (node.firstChild >= 0)
|
||||
{
|
||||
/**
|
||||
* If the current node is not a leaf, figure out which side of the split plane that contains the query point, and recurse down that side.
|
||||
* You will get the index and distance to the closest triangle in that subtree.
|
||||
* Then, check if the distance to the nearest triangle is closer to the query point than the distance between the query point and the split plane.
|
||||
* If it is closer, there is no need to recurse down the other side of the KD tree and you can just return.
|
||||
* Otherwise, you will need to recurse down the other way too, and return whichever result is closer.
|
||||
*/
|
||||
|
||||
float si = float.MaxValue;
|
||||
float p = point[node.axis];
|
||||
|
||||
// child nodes overlap:
|
||||
if (node.min > node.max)
|
||||
{
|
||||
// CASE 1: we are in the overlapping zone: recurse down both.
|
||||
if (p <= node.min && p >= node.max)
|
||||
{
|
||||
si = MinSignedDistance(DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild], in point),
|
||||
DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point));
|
||||
}
|
||||
// CASE 2: to the right of left pivot, that is: in the right child only.
|
||||
else if (p > node.min)
|
||||
{
|
||||
si = DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point);
|
||||
|
||||
// only recurse down left child if nearest surface in right child is furthest than left pivot.
|
||||
if (Mathf.Abs(si) > Mathf.Abs(p - node.min))
|
||||
si = MinSignedDistance(si, DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild], in point));
|
||||
}
|
||||
// CASE 3: to the left of right pivot, that is: in the left child only.
|
||||
else
|
||||
{
|
||||
si = DistanceToSurface(nodes, triangles, vertices, normals, nodes[node.firstChild], point);
|
||||
|
||||
// only recurse down left child if nearest surface in right child is furthest than left pivot.
|
||||
if (Mathf.Abs(si) > Mathf.Abs(node.max - p))
|
||||
si = MinSignedDistance(si, DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point));
|
||||
}
|
||||
}
|
||||
// child nodes do not overlap
|
||||
else
|
||||
{
|
||||
// CASE 4: we are in the middle. just pick up one child (I chose right), get minimum, and if the other child pivot is nearer, recurse down it too.
|
||||
// Just like case 2.
|
||||
if (p > node.min && p < node.max)
|
||||
{
|
||||
si = DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point);
|
||||
|
||||
// only recurse down left child if nearest surface in right child is furthest than left pivot.
|
||||
if (Mathf.Abs(si) > Mathf.Abs(p - node.min))
|
||||
si = MinSignedDistance(si, DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild], in point));
|
||||
}
|
||||
// CASE 5: in the left child. Just like case 3.
|
||||
else if (p <= node.min)
|
||||
{
|
||||
si = DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild], in point);
|
||||
|
||||
// only recurse down left child if nearest surface in right child is furthest than left pivot.
|
||||
if (Mathf.Abs(si) > Mathf.Abs(node.max - p))
|
||||
si = MinSignedDistance(si, DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point));
|
||||
}
|
||||
// CASE 6: in the right child. Just like case 2
|
||||
else if (p >= node.max)
|
||||
{
|
||||
si = DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild + 1], in point);
|
||||
|
||||
// only recurse down left child if nearest surface in right child is furthest than left pivot.
|
||||
if (Mathf.Abs(si) > Mathf.Abs(p - node.min))
|
||||
si = MinSignedDistance(si, DistanceToSurface(nodes, triangles, vertices, normals, in nodes[node.firstChild], in point));
|
||||
}
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
else
|
||||
return DistanceToSurface(triangles, vertices, normals, in node, point);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/BVH/BIH.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/BVH/BIH.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d1727eb52e8f4619a5dc1084db72db0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Assets/Obi/Scripts/Common/DataStructures/BVH/BIHNode.cs
Normal file
25
Assets/Obi/Scripts/Common/DataStructures/BVH/BIHNode.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct BIHNode
|
||||
{
|
||||
public int firstChild; /**< index of the first child node. The second one is right after the first.*/
|
||||
public int start; /**< index of the first element in this node.*/
|
||||
public int count; /**< amount of elements in this node.*/
|
||||
|
||||
public int axis; /**< axis of the split plane (0,1,2 = x,y,z)*/
|
||||
public float min; /**< minimum split plane*/
|
||||
public float max; /**< maximum split plane*/
|
||||
|
||||
public BIHNode(int start, int count)
|
||||
{
|
||||
firstChild = -1;
|
||||
this.start = start;
|
||||
this.count = count;
|
||||
axis = 0;
|
||||
min = float.MinValue;
|
||||
max = float.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/BVH/BIHNode.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/BVH/BIHNode.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 128610647c5e64bc284f13abefda3a58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Obi/Scripts/Common/DataStructures/BVH/IBounded.cs
Normal file
10
Assets/Obi/Scripts/Common/DataStructures/BVH/IBounded.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IBounded
|
||||
{
|
||||
Aabb GetBounds();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44a65f44be3e24beca5faaa7d2c28480
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Assets/Obi/Scripts/Common/DataStructures/CellSpan.cs
Normal file
17
Assets/Obi/Scripts/Common/DataStructures/CellSpan.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct CellSpan
|
||||
{
|
||||
public VInt4 min;
|
||||
public VInt4 max;
|
||||
|
||||
public CellSpan(VInt4 min, VInt4 max)
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/CellSpan.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/CellSpan.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 786fc387d096a4921bd52253d3f51b02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct ColliderRigidbody
|
||||
{
|
||||
public Matrix4x4 inverseInertiaTensor;
|
||||
public Vector4 velocity;
|
||||
public Vector4 angularVelocity;
|
||||
public Vector4 com;
|
||||
public float inverseMass;
|
||||
|
||||
private int pad0;
|
||||
private int pad1;
|
||||
private int pad2;
|
||||
|
||||
public void FromRigidbody(ObiRigidbody rb)
|
||||
{
|
||||
bool kinematic = !Application.isPlaying || rb.unityRigidbody.isKinematic || rb.kinematicForParticles;
|
||||
|
||||
//rotation = source.rotation;
|
||||
velocity = rb.kinematicForParticles ? Vector3.zero : rb.linearVelocity;
|
||||
angularVelocity = rb.kinematicForParticles ? Vector3.zero : rb.angularVelocity;
|
||||
|
||||
// center of mass in unity is affected by local rotation and position, but not scale. We need it expressed in world space:
|
||||
com = rb.unityRigidbody.position + rb.unityRigidbody.rotation * rb.unityRigidbody.centerOfMass;
|
||||
|
||||
Vector3 invTensor = new Vector3((rb.unityRigidbody.constraints & RigidbodyConstraints.FreezeRotationX) != 0 ? 0 : 1 / rb.unityRigidbody.inertiaTensor.x,
|
||||
(rb.unityRigidbody.constraints & RigidbodyConstraints.FreezeRotationY) != 0 ? 0 : 1 / rb.unityRigidbody.inertiaTensor.y,
|
||||
(rb.unityRigidbody.constraints & RigidbodyConstraints.FreezeRotationZ) != 0 ? 0 : 1 / rb.unityRigidbody.inertiaTensor.z);
|
||||
|
||||
// the inertia tensor is a diagonal matrix (Vector3) because it is expressed in the space generated by the principal axes of rotation (inertiaTensorRotation).
|
||||
Vector3 inertiaTensor = kinematic ? Vector3.zero : invTensor;
|
||||
|
||||
// calculate full world space inertia matrix:
|
||||
Matrix4x4 rotation = Matrix4x4.Rotate(rb.unityRigidbody.rotation * rb.unityRigidbody.inertiaTensorRotation);
|
||||
inverseInertiaTensor = rotation * Matrix4x4.Scale(inertiaTensor) * rotation.transpose;
|
||||
|
||||
inverseMass = kinematic ? 0 : 1 / rb.unityRigidbody.mass;
|
||||
|
||||
}
|
||||
|
||||
public void FromRigidbody(ObiRigidbody2D rb)
|
||||
{
|
||||
|
||||
bool kinematic = !Application.isPlaying || rb.unityRigidbody.isKinematic || rb.kinematicForParticles;
|
||||
velocity = rb.linearVelocity;
|
||||
|
||||
// For some weird reason, in 2D angular velocity is measured in *degrees* per second,
|
||||
// instead of radians. Seriously Unity, WTF??
|
||||
angularVelocity = new Vector4(0, 0, rb.angularVelocity * Mathf.Deg2Rad, 0);
|
||||
|
||||
// center of mass in unity is affected by local rotation and poistion, but not scale. We need it expressed in world space:
|
||||
com = rb.transform.position + rb.transform.rotation * rb.unityRigidbody.centerOfMass;
|
||||
|
||||
Vector3 inertiaTensor = kinematic ? Vector3.zero : new Vector3(0, 0, (rb.unityRigidbody.constraints & RigidbodyConstraints2D.FreezeRotation) != 0 ? 0 : 1 / rb.unityRigidbody.inertia);
|
||||
|
||||
Matrix4x4 rotation = Matrix4x4.Rotate(Quaternion.AngleAxis(rb.rotation, Vector3.forward));
|
||||
inverseInertiaTensor = rotation * Matrix4x4.Scale(inertiaTensor) * rotation.transpose;
|
||||
|
||||
inverseMass = kinematic ? 0 : 1 / rb.unityRigidbody.mass;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2273ddd528c3a44af9ef3f985a620e24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/Obi/Scripts/Common/DataStructures/ColliderShape.cs
Normal file
34
Assets/Obi/Scripts/Common/DataStructures/ColliderShape.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct ColliderShape
|
||||
{
|
||||
public enum ShapeType
|
||||
{
|
||||
Sphere = 0,
|
||||
Box = 1,
|
||||
Capsule = 2,
|
||||
Heightmap = 3,
|
||||
TriangleMesh = 4,
|
||||
EdgeMesh = 5,
|
||||
SignedDistanceField = 6
|
||||
}
|
||||
|
||||
public Vector4 center;
|
||||
public Vector4 size; /**< box: size of the box in each axis.
|
||||
sphere: radius of sphere (x,y,z),
|
||||
capsule: radius (x), height(y), direction (z, can be 0, 1 or 2).
|
||||
heightmap: width (x axis), height (y axis) and depth (z axis) in world units.*/
|
||||
public ShapeType type;
|
||||
public float contactOffset;
|
||||
|
||||
public int dataIndex;
|
||||
public int rigidbodyIndex; // index of the associated rigidbody in the collision world.
|
||||
public int materialIndex; // index of the associated material in the collision world.
|
||||
|
||||
public int filter; // bitwise category/mask.
|
||||
public int flags; // for now, only used for trigger (1) or regular collider (0).
|
||||
public int is2D; // whether the collider is 2D (1) or 3D (0).
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38d82eae8f8744bdc9f0795c1fd3b317
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public struct CollisionMaterial
|
||||
{
|
||||
public float dynamicFriction;
|
||||
public float staticFriction;
|
||||
public float rollingFriction;
|
||||
public float stickiness;
|
||||
public float stickDistance;
|
||||
public Oni.MaterialCombineMode frictionCombine;
|
||||
public Oni.MaterialCombineMode stickinessCombine;
|
||||
public int rollingContacts;
|
||||
|
||||
public void FromObiCollisionMaterial(ObiCollisionMaterial material)
|
||||
{
|
||||
if (material != null)
|
||||
{
|
||||
dynamicFriction = material.dynamicFriction;
|
||||
staticFriction = material.staticFriction;
|
||||
stickiness = material.stickiness;
|
||||
stickDistance = material.stickDistance;
|
||||
rollingFriction = material.rollingFriction;
|
||||
frictionCombine = material.frictionCombine;
|
||||
stickinessCombine = material.stickinessCombine;
|
||||
rollingContacts = material.rollingContacts ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed8262093b9b44e8abb2557ed2624c4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Obi/Scripts/Common/DataStructures/NativeList.meta
Normal file
8
Assets/Obi/Scripts/Common/DataStructures/NativeList.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f5d490805c6e4ee6b39c067e26e490c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeAabbList : ObiNativeList<Aabb>
|
||||
{
|
||||
public ObiNativeAabbList() { }
|
||||
public ObiNativeAabbList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new Aabb();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96e807cda064c47c1aed643600660143
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeAffineTransformList : ObiNativeList<AffineTransform>
|
||||
{
|
||||
public ObiNativeAffineTransformList() { }
|
||||
public ObiNativeAffineTransformList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new AffineTransform();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f741a9b23bfd4f55979eb1a18146388
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeBIHNodeList : ObiNativeList<BIHNode>
|
||||
{
|
||||
public ObiNativeBIHNodeList() { }
|
||||
public ObiNativeBIHNodeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new BIHNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c960e0992a4cf4d7195a513c5fd5f550
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeBoneWeightList : ObiNativeList<BoneWeight1>
|
||||
{
|
||||
public ObiNativeBoneWeightList() { }
|
||||
public ObiNativeBoneWeightList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new BoneWeight1();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50b49a1cc8de340ebb8d6a89fb044c1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeByteList : ObiNativeList<byte>
|
||||
{
|
||||
|
||||
public ObiNativeByteList() { }
|
||||
public ObiNativeByteList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aefb86b129c07425fa244ada261f4184
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeCellSpanList : ObiNativeList<CellSpan>
|
||||
{
|
||||
public ObiNativeCellSpanList() { }
|
||||
public ObiNativeCellSpanList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new CellSpan();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53a29ecfe0ecb4db3a344781b333776d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeColliderShapeList : ObiNativeList<ColliderShape>
|
||||
{
|
||||
public ObiNativeColliderShapeList() { }
|
||||
public ObiNativeColliderShapeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new ColliderShape();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45031e9a1b74143c4a6df44e2b999373
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeCollisionMaterialList : ObiNativeList<CollisionMaterial>
|
||||
{
|
||||
public ObiNativeCollisionMaterialList() { }
|
||||
public ObiNativeCollisionMaterialList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new CollisionMaterial();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6d32cd2f844a48cab0508f798fc1ff4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeColorList : ObiNativeList<Color>
|
||||
{
|
||||
public ObiNativeColorList() { }
|
||||
public ObiNativeColorList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Color.white;
|
||||
}
|
||||
public ObiNativeColorList(int capacity, int alignment, Color defaultValue) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 391ffe5ba25364d2393afabc3083daa1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeContactShapeList : ObiNativeList<Oni.Contact>
|
||||
{
|
||||
public ObiNativeContactShapeList() { }
|
||||
public ObiNativeContactShapeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new Oni.Contact();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ac88e1dd7e0249b5b361d60655d8d88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeDFNodeList : ObiNativeList<DFNode>
|
||||
{
|
||||
public ObiNativeDFNodeList() { }
|
||||
public ObiNativeDFNodeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new DFNode();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17462646d532945749479c75ba3cd0d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeDistanceFieldHeaderList : ObiNativeList<DistanceFieldHeader>
|
||||
{
|
||||
public ObiNativeDistanceFieldHeaderList() { }
|
||||
public ObiNativeDistanceFieldHeaderList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new DistanceFieldHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e18334e185814395aac025a1d4afe70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeEdgeList : ObiNativeList<Edge>
|
||||
{
|
||||
public ObiNativeEdgeList() { }
|
||||
public ObiNativeEdgeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new Edge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d602b9fba6fc4e78a78b8dee0acd309
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeEdgeMeshHeaderList : ObiNativeList<EdgeMeshHeader>
|
||||
{
|
||||
public ObiNativeEdgeMeshHeaderList() { }
|
||||
public ObiNativeEdgeMeshHeaderList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new EdgeMeshHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 474a95d0d9d37494f9ac5201e262b8a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeFloatList : ObiNativeList<float>
|
||||
{
|
||||
public ObiNativeFloatList() { }
|
||||
public ObiNativeFloatList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cf0e80d841ca4425a99bc2d4beb3547
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeHeightFieldHeaderList : ObiNativeList<HeightFieldHeader>
|
||||
{
|
||||
public ObiNativeHeightFieldHeaderList() { }
|
||||
public ObiNativeHeightFieldHeaderList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new HeightFieldHeader();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61e8d2ecda37e442aa8f24756395f12a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeInt4List : ObiNativeList<VInt4>
|
||||
{
|
||||
public ObiNativeInt4List() { }
|
||||
public ObiNativeInt4List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new VInt4(0,0,0,0);
|
||||
}
|
||||
|
||||
public ObiNativeInt4List(int capacity, int alignment, VInt4 defaultValue) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18f572cdc044a4caabe29c40944c0987
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeIntList : ObiNativeList<int>
|
||||
{
|
||||
public ObiNativeIntList() { }
|
||||
public ObiNativeIntList(int capacity = 8, int alignment = 16) : base(capacity,alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f8a8fd8447dc458bab16dea3dfd5580
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiNativeIntPtrList : ObiNativeList<IntPtr>
|
||||
{
|
||||
public ObiNativeIntPtrList() { }
|
||||
public ObiNativeIntPtrList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6201c3f1582cd43deaaf41286f802126
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,442 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public unsafe abstract class ObiNativeList<T> : IEnumerable<T>, IDisposable, ISerializationCallbackReceiver where T : struct
|
||||
{
|
||||
public T[] serializedContents;
|
||||
protected void* m_AlignedPtr = null;
|
||||
|
||||
protected int m_Stride;
|
||||
protected int m_Capacity;
|
||||
protected int m_Count;
|
||||
[SerializeField] protected int m_AlignBytes = 16;
|
||||
|
||||
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||||
protected AtomicSafetyHandle m_SafetyHandle;
|
||||
#endif
|
||||
protected ComputeBuffer m_ComputeBuffer;
|
||||
|
||||
public int count
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value != m_Count)
|
||||
{
|
||||
// we should not use ResizeUninitialized as it would destroy all current data.
|
||||
// we first ensure we can hold the previous count, and then set the new one.
|
||||
EnsureCapacity(m_Count);
|
||||
m_Count = Mathf.Min(m_Capacity, value);
|
||||
}
|
||||
}
|
||||
get { return m_Count; }
|
||||
}
|
||||
|
||||
public int capacity
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value != m_Capacity)
|
||||
ChangeCapacity(value);
|
||||
}
|
||||
get { return m_Capacity; }
|
||||
}
|
||||
|
||||
public bool isCreated
|
||||
{
|
||||
get { return m_AlignedPtr != null; }
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return UnsafeUtility.ReadArrayElementWithStride<T>(m_AlignedPtr, index, m_Stride);
|
||||
}
|
||||
set
|
||||
{
|
||||
UnsafeUtility.WriteArrayElementWithStride<T>(m_AlignedPtr, index, m_Stride, value);
|
||||
|
||||
if (m_ComputeBuffer != null)
|
||||
m_ComputeBuffer.SetData(AsNativeArray<T>(), index, index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Declare parameterless constructor, called by Unity upon deserialization.
|
||||
protected ObiNativeList()
|
||||
{
|
||||
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||||
m_SafetyHandle = AtomicSafetyHandle.Create();
|
||||
#endif
|
||||
}
|
||||
|
||||
public ObiNativeList(int capacity = 8, int alignment = 16)
|
||||
{
|
||||
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||||
m_SafetyHandle = AtomicSafetyHandle.Create();
|
||||
#endif
|
||||
m_AlignBytes = alignment;
|
||||
ChangeCapacity(capacity);
|
||||
}
|
||||
|
||||
~ObiNativeList()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (isCreated)
|
||||
{
|
||||
|
||||
// dispose of compuse buffer representation:
|
||||
if (m_ComputeBuffer != null)
|
||||
{
|
||||
m_ComputeBuffer.Dispose();
|
||||
}
|
||||
|
||||
// free unmanaged memory buffer:
|
||||
UnsafeUtility.Free(m_AlignedPtr, Allocator.Persistent);
|
||||
m_AlignedPtr = null;
|
||||
}
|
||||
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||||
// dispose of atomic safety handle:
|
||||
AtomicSafetyHandle.CheckDeallocateAndThrow(m_SafetyHandle);
|
||||
AtomicSafetyHandle.Release(m_SafetyHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
if (isCreated)
|
||||
{
|
||||
// create a new managed array to serialize the data:
|
||||
serializedContents = new T[m_Count];
|
||||
|
||||
// pin the managed array and get its address:
|
||||
ulong serializedContentsHandle;
|
||||
var serializedContentsAddress = UnsafeUtility.PinGCArrayAndGetDataAddress(serializedContents, out serializedContentsHandle);
|
||||
|
||||
// copy data over to the managed array:
|
||||
UnsafeUtility.MemCpy(serializedContentsAddress, m_AlignedPtr, m_Count * m_Stride);
|
||||
|
||||
// unpin the managed array:
|
||||
UnsafeUtility.ReleaseGCObject(serializedContentsHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
if (serializedContents != null)
|
||||
{
|
||||
// resize to receive the serialized data:
|
||||
ResizeUninitialized(serializedContents.Length);
|
||||
|
||||
// pin the managed array and get its address:
|
||||
ulong serializedContentsHandle;
|
||||
var serializedContentsAddress = UnsafeUtility.PinGCArrayAndGetDataAddress(serializedContents, out serializedContentsHandle);
|
||||
|
||||
// copy data from the managed array:
|
||||
UnsafeUtility.MemCpy(m_AlignedPtr, serializedContentsAddress, m_Count * m_Stride);
|
||||
|
||||
// unpin the managed array:
|
||||
UnsafeUtility.ReleaseGCObject(serializedContentsHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Reinterprets the data in the list as a native array.
|
||||
public NativeArray<U> AsNativeArray<U>() where U : struct
|
||||
{
|
||||
return AsNativeArray<U>(m_Count);
|
||||
}
|
||||
|
||||
// Reinterprets the data in the list as a native array.
|
||||
public NativeArray<U> AsNativeArray<U>(int arrayLength) where U : struct
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeArray<U> array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<U>(m_AlignedPtr, arrayLength, Allocator.None);
|
||||
|
||||
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||||
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, m_SafetyHandle);
|
||||
#endif
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
// Reinterprets the data in the list as a compute buffer. Note: This also calls AsNativeArray() internally, to be able to pass the raw pointer to the compute buffer
|
||||
public ComputeBuffer AsComputeBuffer<U>() where U : struct
|
||||
{
|
||||
if (m_ComputeBuffer != null)
|
||||
{
|
||||
m_ComputeBuffer.Dispose();
|
||||
}
|
||||
|
||||
m_ComputeBuffer = new ComputeBuffer(m_Count, m_Stride);
|
||||
m_ComputeBuffer.SetData(AsNativeArray<U>());
|
||||
return m_ComputeBuffer;
|
||||
}
|
||||
|
||||
protected void ChangeCapacity(int newCapacity)
|
||||
{
|
||||
// allocate a new buffer:
|
||||
m_Stride = UnsafeUtility.SizeOf<T>();
|
||||
var newAlignedPtr = UnsafeUtility.Malloc(newCapacity * m_Stride, 16, Allocator.Persistent);
|
||||
|
||||
// if there was a previous allocation:
|
||||
if (isCreated)
|
||||
{
|
||||
// copy contents from previous memory region
|
||||
unsafe
|
||||
{
|
||||
UnsafeUtility.MemCpy(newAlignedPtr, m_AlignedPtr, Mathf.Min(newCapacity, m_Capacity) * m_Stride);
|
||||
}
|
||||
|
||||
// free previous memory region
|
||||
UnsafeUtility.Free(m_AlignedPtr, Allocator.Persistent);
|
||||
}
|
||||
|
||||
// get hold of new pointers/capacity.
|
||||
m_AlignedPtr = newAlignedPtr;
|
||||
m_Capacity = newCapacity;
|
||||
}
|
||||
|
||||
public bool Compare(ObiNativeList<T> other)
|
||||
{
|
||||
if (other == null || !isCreated || !other.isCreated)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (m_Count != other.m_Count)
|
||||
return false;
|
||||
|
||||
return UnsafeUtility.MemCmp(m_AlignedPtr, other.m_AlignedPtr, m_Count * m_Stride) == 0;
|
||||
}
|
||||
|
||||
public void CopyFrom(ObiNativeList<T> source)
|
||||
{
|
||||
if (source == null || !isCreated || !source.isCreated)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (m_Count < source.m_Count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
UnsafeUtility.MemCpy(m_AlignedPtr, source.m_AlignedPtr, source.count * m_Stride);
|
||||
}
|
||||
|
||||
public void CopyFrom(ObiNativeList<T> source, int sourceIndex, int destIndex, int length)
|
||||
{
|
||||
if (source == null || !isCreated || !source.isCreated)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (length <= 0 || source.m_Count == 0)
|
||||
return;
|
||||
|
||||
if (sourceIndex >= source.m_Count || sourceIndex < 0 || destIndex >= m_Count || destIndex < 0 ||
|
||||
sourceIndex + length > source.m_Count || destIndex + length > m_Count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
void* sourceAddress = source.AddressOfElement(sourceIndex);
|
||||
void* destAddress = AddressOfElement(destIndex);
|
||||
UnsafeUtility.MemCpy(destAddress, sourceAddress, length * m_Stride);
|
||||
|
||||
}
|
||||
|
||||
public void CopyReplicate(T value, int destIndex, int length)
|
||||
{
|
||||
if (length <= 0) return;
|
||||
|
||||
if (!isCreated)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (destIndex >= m_Count || destIndex < 0 || destIndex + length > m_Count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
void* sourceAddress = UnsafeUtility.AddressOf(ref value);
|
||||
void* destAddress = AddressOfElement(destIndex);
|
||||
UnsafeUtility.MemCpyReplicate(destAddress, sourceAddress, m_Stride, length);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] dest, int sourceIndex, int length)
|
||||
{
|
||||
if (length <= 0) return;
|
||||
|
||||
if (dest == null || !isCreated)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (sourceIndex < 0 || sourceIndex >= m_Count || sourceIndex + length > m_Count || length > dest.Length)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
ulong destHandle;
|
||||
void* sourceAddress = AddressOfElement(sourceIndex);
|
||||
void* destAddress = UnsafeUtility.PinGCArrayAndGetDataAddress(dest, out destHandle);
|
||||
UnsafeUtility.MemCpy(destAddress, sourceAddress, length * m_Stride);
|
||||
|
||||
UnsafeUtility.ReleaseGCObject(destHandle);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
m_Count = 0;
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
EnsureCapacity(m_Count + 1);
|
||||
this[m_Count++] = item;
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> enumerable)
|
||||
{
|
||||
ICollection<T> collection = enumerable as ICollection<T>;
|
||||
if (collection != null && collection.Count > 0)
|
||||
{
|
||||
EnsureCapacity(m_Count + collection.Count);
|
||||
}
|
||||
|
||||
using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
|
||||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
Add(enumerator.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRange(int index, int count)
|
||||
{
|
||||
if (index < 0 || count < 0 || index + count > m_Count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
for (int i = index; i < m_Count - count; ++i)
|
||||
this[i] = this[i + count];
|
||||
|
||||
m_Count -= count;
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
for (int i = index; i < m_Count - 1; ++i)
|
||||
this[i] = this[i + 1];
|
||||
|
||||
m_Count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a minimal capacity of count elements, then sets the new count. Useful when passing the backing array to C++
|
||||
* for being filled with new data.
|
||||
*/
|
||||
public bool ResizeUninitialized(int newCount)
|
||||
{
|
||||
newCount = Mathf.Max(0, newCount);
|
||||
bool realloc = EnsureCapacity(newCount);
|
||||
m_Count = newCount;
|
||||
return realloc;
|
||||
}
|
||||
|
||||
public bool ResizeInitialized(int newCount, T value = default(T))
|
||||
{
|
||||
newCount = Mathf.Max(0, newCount);
|
||||
|
||||
bool initialize = newCount >= m_Capacity || !isCreated;
|
||||
bool realloc = EnsureCapacity(newCount);
|
||||
|
||||
if (initialize)
|
||||
{
|
||||
void* sourceAddress = UnsafeUtility.AddressOf(ref value);
|
||||
void* destAddress = AddressOfElement(m_Count);
|
||||
UnsafeUtility.MemCpyReplicate(destAddress, sourceAddress, m_Stride, m_Capacity - m_Count);
|
||||
}
|
||||
|
||||
m_Count = newCount;
|
||||
|
||||
return realloc;
|
||||
}
|
||||
|
||||
public bool EnsureCapacity(int min)
|
||||
{
|
||||
if (min >= m_Capacity || !isCreated)
|
||||
{
|
||||
ChangeCapacity(min * 2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void WipeToZero()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
if (isCreated)
|
||||
UnsafeUtility.MemClear(m_AlignedPtr, count * m_Stride);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
|
||||
for (int t = 0; t < m_Count; t++)
|
||||
{
|
||||
sb.Append(this[t].ToString());
|
||||
|
||||
if (t < (m_Count - 1)) sb.Append(',');
|
||||
|
||||
}
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void* AddressOfElement(int index)
|
||||
{
|
||||
// UnsafeUtility.AddressOf(ref UnsafeUtilityEx.ArrayElementAsRef<T>(m_AlignedPtr, m_Count));
|
||||
return (void*) ((byte*)m_AlignedPtr + m_Stride * index);
|
||||
}
|
||||
|
||||
public IntPtr GetIntPtr()
|
||||
{
|
||||
if (isCreated)
|
||||
return new IntPtr(m_AlignedPtr);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public void Swap(int index1, int index2)
|
||||
{
|
||||
// check to avoid out of bounds access:
|
||||
if (index1 >= 0 && index1 < count && index2 >= 0 && index2 < count)
|
||||
{
|
||||
var aux = this[index1];
|
||||
this[index1] = this[index2];
|
||||
this[index2] = aux;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be1183504e86c409d97f706fcfcb0b3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeMatrix4x4List : ObiNativeList<Matrix4x4>
|
||||
{
|
||||
public ObiNativeMatrix4x4List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Matrix4x4.identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6b7295a6ebb4475fb050c4c5b3770cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeQuaternionList : ObiNativeList<Quaternion>
|
||||
{
|
||||
public ObiNativeQuaternionList() { }
|
||||
public ObiNativeQuaternionList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Quaternion.identity;
|
||||
}
|
||||
|
||||
public ObiNativeQuaternionList(int capacity, int alignment, Quaternion defaultValue) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bad311b87fb6408793370e029c1d625
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeQueryResultList : ObiNativeList<QueryResult>
|
||||
{
|
||||
|
||||
public ObiNativeQueryResultList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new QueryResult();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 415658bfe3b0f45c285a26d383086a70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeQueryShapeList : ObiNativeList<QueryShape>
|
||||
{
|
||||
|
||||
public ObiNativeQueryShapeList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new QueryShape();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1b44ba5a49564f81bc8eeebbee71cf3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeRigidbodyList : ObiNativeList<ColliderRigidbody>
|
||||
{
|
||||
public ObiNativeRigidbodyList() { }
|
||||
public ObiNativeRigidbodyList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new ColliderRigidbody();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28ae021335a854c3eb91c500cd4c77b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeTriangleList : ObiNativeList<Triangle>
|
||||
{
|
||||
public ObiNativeTriangleList() { }
|
||||
public ObiNativeTriangleList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new Triangle();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0eda4a24fce5949d284395fe3a782477
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeTriangleMeshHeaderList : ObiNativeList<TriangleMeshHeader>
|
||||
{
|
||||
public ObiNativeTriangleMeshHeaderList() { }
|
||||
public ObiNativeTriangleMeshHeaderList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = new TriangleMeshHeader();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7289725194bb4368a4ac8e6cd9a7062
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeVector2List : ObiNativeList<Vector2>
|
||||
{
|
||||
public ObiNativeVector2List() { }
|
||||
public ObiNativeVector2List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Vector2.zero;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 097972b931df946398eb40913011ada0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeVector3List : ObiNativeList<Vector3>
|
||||
{
|
||||
public ObiNativeVector3List() { }
|
||||
public ObiNativeVector3List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Vector3.zero;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb8db19bcf3ce468786ed448ea6821d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNativeVector4List : ObiNativeList<Vector4>
|
||||
{
|
||||
public ObiNativeVector4List() { }
|
||||
public ObiNativeVector4List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
|
||||
{
|
||||
for (int i = 0; i < capacity; ++i)
|
||||
this[i] = Vector4.zero;
|
||||
}
|
||||
|
||||
|
||||
public Vector3 GetVector3(int index)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
byte* start = (byte*)m_AlignedPtr + index * sizeof(Vector4);
|
||||
return *(Vector3*)start;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVector3(int index, Vector3 value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
byte* start = (byte*)m_AlignedPtr + index * sizeof(Vector4);
|
||||
*(Vector3*)start = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a1016daf70074bd790b5a278c314263
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
165
Assets/Obi/Scripts/Common/DataStructures/ObiList.cs
Normal file
165
Assets/Obi/Scripts/Common/DataStructures/ObiList.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/**
|
||||
* Custom IList implementation that allows access to the underlying raw array, for efficient C++ interop. Also
|
||||
* includes some auxiliar methods that make it easier and faster to send data back and forth between C# and C++, as
|
||||
* well as deal with accesing the contents of the list directly without a copy.
|
||||
*/
|
||||
public class ObiList<T> : IList<T>
|
||||
{
|
||||
private T[] data = new T[16];
|
||||
private int count = 0;
|
||||
|
||||
#region Implementation of IEnumerable
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < count;++i)
|
||||
yield return data[i];
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of ICollection<T>
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
EnsureCapacity(count + 1);
|
||||
data[count++] = item;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
if (data[i].Equals(item))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
if (array.Length-arrayIndex < count)
|
||||
throw new ArgumentException();
|
||||
|
||||
Array.Copy(data,0,array,arrayIndex,count);
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
// Look for the element, and mark it as found.
|
||||
if (!found && data[i].Equals(item))
|
||||
found = true;
|
||||
|
||||
//If we found the element and are not at the last element, displace the element 1 position backwards.
|
||||
if (found && i < count-1)
|
||||
{
|
||||
data[i] = data[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
// If we found and removed the element, reduce the element count by 1.
|
||||
if (found)
|
||||
count--;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return count; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IList<T>
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
return Array.IndexOf(data,item);
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (index < 0 || index > count)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
EnsureCapacity(++count);
|
||||
|
||||
for (int i = count-1; i > index; ++i)
|
||||
{
|
||||
data[i] = data[i-1];
|
||||
}
|
||||
|
||||
data[index] = item;
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
for (int i = index; i < count; ++i)
|
||||
{
|
||||
if (i < count-1)
|
||||
{
|
||||
data[i] = data[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get { return data[index]; }
|
||||
set { data[index] = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Added stuff
|
||||
|
||||
public T[] Data{
|
||||
get{return data;}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a minimal capacity of count elements, then sets the new count. Useful when passing the backing array to C++
|
||||
* for being filled with new data.
|
||||
*/
|
||||
public void SetCount(int count){
|
||||
EnsureCapacity(count);
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void EnsureCapacity(int capacity){
|
||||
if (capacity >= data.Length)
|
||||
Array.Resize(ref data,capacity*2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
12
Assets/Obi/Scripts/Common/DataStructures/ObiList.cs.meta
Normal file
12
Assets/Obi/Scripts/Common/DataStructures/ObiList.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8100b324be8f46cc9578fd52193a876
|
||||
timeCreated: 1513467715
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/Obi/Scripts/Common/DataStructures/ParticlePair.cs
Normal file
24
Assets/Obi/Scripts/Common/DataStructures/ParticlePair.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct ParticlePair
|
||||
{
|
||||
public int first;
|
||||
public int second;
|
||||
|
||||
public ParticlePair(int first, int second)
|
||||
{
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public int this[int index]
|
||||
{
|
||||
get { return index == 0 ? first : second; }
|
||||
set { if (index == 0) first = value; else second = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 248fe94c499654ccf8bee67c72942dde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Obi/Scripts/Common/DataStructures/Queries.meta
Normal file
8
Assets/Obi/Scripts/Common/DataStructures/Queries.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10c69aca53bad420799af0abb9f185ea
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = 64)]
|
||||
public struct QueryResult
|
||||
{
|
||||
public Vector4 simplexBary; /**< Barycentric coords of nearest point in simplex */
|
||||
public Vector4 queryPoint; /**< Nearest point in query shape*/
|
||||
public Vector4 normal; /**< Closest direction between simplex and query shape. */
|
||||
public float distance; /**< Distance between simplex and query shape.*/
|
||||
public int simplexIndex; /**< Index of the simplex in the solver.*/
|
||||
public int queryIndex; /**< Index of the query that spawned this result.*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2effdf7f81654462ac5af1735de92eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct QueryShape
|
||||
{
|
||||
public enum QueryType
|
||||
{
|
||||
Sphere = 0,
|
||||
Box = 1,
|
||||
Ray = 2,
|
||||
}
|
||||
|
||||
public Vector4 center; /**< box: center of the box in solver space.
|
||||
sphere: center of the sphere in solver space,.
|
||||
ray: start of the ray in solver space.*/
|
||||
|
||||
public Vector4 size; /**< box: size of the box in each axis.
|
||||
sphere: radius of sphere (x,y,z),
|
||||
ray: end of the line segment in solver space.*/
|
||||
public QueryType type;
|
||||
public float contactOffset;
|
||||
public float maxDistance; // minimum distance around the shape to look for.
|
||||
public int filter;
|
||||
|
||||
public QueryShape(QueryType type, Vector3 center, Vector3 size, float contactOffset, float distance, int filter)
|
||||
{
|
||||
this.type = type;
|
||||
this.center = center;
|
||||
this.size = size;
|
||||
this.contactOffset = contactOffset;
|
||||
this.maxDistance = distance;
|
||||
this.filter = filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d126422956eb46eaa20e28b8d59122c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
Assets/Obi/Scripts/Common/DataStructures/SimplexCounts.cs
Normal file
47
Assets/Obi/Scripts/Common/DataStructures/SimplexCounts.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct SimplexCounts
|
||||
{
|
||||
public int pointCount;
|
||||
public int edgeCount;
|
||||
public int triangleCount;
|
||||
|
||||
public int simplexCount
|
||||
{
|
||||
get { return pointCount + edgeCount + triangleCount; }
|
||||
}
|
||||
|
||||
public SimplexCounts(int pointCount, int edgeCount, int triangleCount)
|
||||
{
|
||||
this.pointCount = pointCount;
|
||||
this.edgeCount = edgeCount;
|
||||
this.triangleCount = triangleCount;
|
||||
}
|
||||
|
||||
public int GetSimplexStartAndSize(int index, out int size)
|
||||
{
|
||||
if (index < pointCount)
|
||||
{
|
||||
size = 1;
|
||||
return index;
|
||||
}
|
||||
else if (index < pointCount + edgeCount)
|
||||
{
|
||||
size = 2;
|
||||
return pointCount + (index - pointCount) * 2;
|
||||
}
|
||||
else if (index < simplexCount)
|
||||
{
|
||||
size = 3;
|
||||
int triStart = pointCount + edgeCount * 2;
|
||||
return triStart + (index - pointCount - edgeCount) * 3;
|
||||
}
|
||||
size = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a445a209f673411391c60adfe8b4766
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/Obi/Scripts/Common/DataStructures/VInt4.cs
Normal file
33
Assets/Obi/Scripts/Common/DataStructures/VInt4.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct VInt4
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
public int w;
|
||||
|
||||
public VInt4(int x, int y, int z, int w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
public VInt4(int x)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = x;
|
||||
this.z = x;
|
||||
this.w = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/DataStructures/VInt4.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/DataStructures/VInt4.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4509cf294c582479790fe1d6307b218c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfdbb639033814f7c94f5ad7f5bdb809
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,429 @@
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
/**
|
||||
* Helper class that voxelizes a mesh.
|
||||
*/
|
||||
[Serializable]
|
||||
public class MeshVoxelizer
|
||||
{
|
||||
[Flags]
|
||||
public enum Voxel
|
||||
{
|
||||
Empty = 0,
|
||||
Inside = 1 << 0,
|
||||
Boundary = 1 << 1,
|
||||
Outside = 1 << 2,
|
||||
}
|
||||
|
||||
public readonly static Vector3Int[] fullNeighborhood =
|
||||
{
|
||||
// face neighbors:
|
||||
new Vector3Int(-1,0,0),
|
||||
new Vector3Int(1,0,0),
|
||||
new Vector3Int(0,-1,0),
|
||||
new Vector3Int(0,1,0),
|
||||
new Vector3Int(0,0,-1),
|
||||
new Vector3Int(0,0,1),
|
||||
|
||||
// edge neighbors:
|
||||
new Vector3Int(-1,-1,0),
|
||||
new Vector3Int(-1,0,-1),
|
||||
new Vector3Int(-1,0,1),
|
||||
new Vector3Int(-1,1,0),
|
||||
new Vector3Int(0,-1,-1),
|
||||
new Vector3Int(0,-1,1),
|
||||
new Vector3Int(0,1,-1),
|
||||
new Vector3Int(0,1,1),
|
||||
new Vector3Int(1,-1,0),
|
||||
new Vector3Int(1,0,-1),
|
||||
new Vector3Int(1,0,1),
|
||||
new Vector3Int(1,1,0),
|
||||
|
||||
// vertex neighbors:
|
||||
new Vector3Int(-1,-1,-1),
|
||||
new Vector3Int(-1,-1,1),
|
||||
new Vector3Int(-1,1,-1),
|
||||
new Vector3Int(-1,1,1),
|
||||
new Vector3Int(1,-1,-1),
|
||||
new Vector3Int(1,-1,1),
|
||||
new Vector3Int(1,1,-1),
|
||||
new Vector3Int(1,1,1)
|
||||
};
|
||||
|
||||
public readonly static Vector3Int[] edgefaceNeighborhood =
|
||||
{
|
||||
new Vector3Int(-1,-1,0),
|
||||
new Vector3Int(-1,0,-1),
|
||||
new Vector3Int(-1,0,0),
|
||||
new Vector3Int(-1,0,1),
|
||||
new Vector3Int(-1,1,0),
|
||||
new Vector3Int(0,-1,-1),
|
||||
new Vector3Int(0,-1,0),
|
||||
new Vector3Int(0,-1,1),
|
||||
new Vector3Int(0,0,-1),
|
||||
new Vector3Int(0,0,1),
|
||||
new Vector3Int(0,1,-1),
|
||||
new Vector3Int(0,1,0),
|
||||
new Vector3Int(0,1,1),
|
||||
new Vector3Int(1,-1,0),
|
||||
new Vector3Int(1,0,-1),
|
||||
new Vector3Int(1,0,0),
|
||||
new Vector3Int(1,0,1),
|
||||
new Vector3Int(1,1,0)
|
||||
};
|
||||
|
||||
public readonly static Vector3Int[] faceNeighborhood =
|
||||
{
|
||||
new Vector3Int(-1,0,0),
|
||||
new Vector3Int(1,0,0),
|
||||
new Vector3Int(0,-1,0),
|
||||
new Vector3Int(0,1,0),
|
||||
new Vector3Int(0,0,-1),
|
||||
new Vector3Int(0,0,1)
|
||||
};
|
||||
|
||||
public readonly static Vector3Int[] edgeNeighborhood =
|
||||
{
|
||||
new Vector3Int(-1,-1,0),
|
||||
new Vector3Int(-1,0,-1),
|
||||
new Vector3Int(-1,0,1),
|
||||
new Vector3Int(-1,1,0),
|
||||
new Vector3Int(0,-1,-1),
|
||||
new Vector3Int(0,-1,1),
|
||||
new Vector3Int(0,1,-1),
|
||||
new Vector3Int(0,1,1),
|
||||
new Vector3Int(1,-1,0),
|
||||
new Vector3Int(1,0,-1),
|
||||
new Vector3Int(1,0,1),
|
||||
new Vector3Int(1,1,0)
|
||||
};
|
||||
|
||||
public readonly static Vector3Int[] vertexNeighborhood =
|
||||
{
|
||||
new Vector3Int(-1,-1,-1),
|
||||
new Vector3Int(-1,-1,1),
|
||||
new Vector3Int(-1,1,-1),
|
||||
new Vector3Int(-1,1,1),
|
||||
new Vector3Int(1,-1,-1),
|
||||
new Vector3Int(1,-1,1),
|
||||
new Vector3Int(1,1,-1),
|
||||
new Vector3Int(1,1,1)
|
||||
};
|
||||
|
||||
[NonSerialized] public Mesh input;
|
||||
|
||||
[HideInInspector][SerializeField] private Voxel[] voxels;
|
||||
public float voxelSize;
|
||||
public Vector3Int resolution;
|
||||
|
||||
private List<int>[] triangleIndices; // temporary structure to hold triangles overlapping each voxel.
|
||||
private Vector3Int origin;
|
||||
|
||||
public Vector3Int Origin
|
||||
{
|
||||
get { return origin; }
|
||||
}
|
||||
|
||||
public int voxelCount
|
||||
{
|
||||
get { return resolution.x * resolution.y * resolution.z; }
|
||||
}
|
||||
|
||||
public MeshVoxelizer(Mesh input, float voxelSize)
|
||||
{
|
||||
this.input = input;
|
||||
this.voxelSize = voxelSize;
|
||||
}
|
||||
|
||||
public Voxel this[int x, int y, int z]
|
||||
{
|
||||
get { return voxels[GetVoxelIndex(x, y, z)]; }
|
||||
set { voxels[GetVoxelIndex(x, y, z)] = value; }
|
||||
}
|
||||
|
||||
public float GetDistanceToNeighbor(int i)
|
||||
{
|
||||
if (i > 17) return ObiUtils.sqrt3 * voxelSize;
|
||||
if (i > 5) return ObiUtils.sqrt2 * voxelSize;
|
||||
return voxelSize;
|
||||
}
|
||||
|
||||
public int GetVoxelIndex(int x, int y, int z)
|
||||
{
|
||||
return x + resolution.x * (y + resolution.y * z);
|
||||
}
|
||||
|
||||
public Vector3 GetVoxelCenter(in Vector3Int coords)
|
||||
{
|
||||
return new Vector3(Origin.x + coords.x + 0.5f,
|
||||
Origin.y + coords.y + 0.5f,
|
||||
Origin.z + coords.z + 0.5f) * voxelSize;
|
||||
}
|
||||
|
||||
private Bounds GetTriangleBounds(in Vector3 v1, in Vector3 v2, in Vector3 v3)
|
||||
{
|
||||
Bounds b = new Bounds(v1, Vector3.zero);
|
||||
b.Encapsulate(v2);
|
||||
b.Encapsulate(v3);
|
||||
return b;
|
||||
}
|
||||
|
||||
public List<int> GetTrianglesOverlappingVoxel(int voxelIndex)
|
||||
{
|
||||
if (voxelIndex >= 0 && voxelIndex < triangleIndices.Length)
|
||||
return triangleIndices[voxelIndex];
|
||||
return null;
|
||||
}
|
||||
|
||||
public Vector3Int GetPointVoxel(in Vector3 point)
|
||||
{
|
||||
return new Vector3Int(Mathf.FloorToInt(point.x / voxelSize),
|
||||
Mathf.FloorToInt(point.y / voxelSize),
|
||||
Mathf.FloorToInt(point.z / voxelSize));
|
||||
}
|
||||
|
||||
public bool VoxelExists(in Vector3Int coords)
|
||||
{
|
||||
return VoxelExists(coords.x, coords.y, coords.z);
|
||||
}
|
||||
|
||||
public bool VoxelExists(int x, int y, int z)
|
||||
{
|
||||
return x >= 0 && y >= 0 && z >= 0 &&
|
||||
x < resolution.x &&
|
||||
y < resolution.y &&
|
||||
z < resolution.z;
|
||||
}
|
||||
|
||||
private void AppendOverlappingVoxels(in Bounds bounds, in Vector3 v1, in Vector3 v2, in Vector3 v3, int triangleIndex)
|
||||
{
|
||||
|
||||
Vector3Int min = GetPointVoxel(bounds.min);
|
||||
Vector3Int max = GetPointVoxel(bounds.max);
|
||||
|
||||
for (int x = min.x; x <= max.x; ++x)
|
||||
for (int y = min.y; y <= max.y; ++y)
|
||||
for (int z = min.z; z <= max.z; ++z)
|
||||
{
|
||||
Bounds voxel = new Bounds(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f) * voxelSize, Vector3.one * voxelSize);
|
||||
|
||||
if (IsIntersecting(voxel, v1, v2, v3))
|
||||
{
|
||||
int index = GetVoxelIndex(x - origin.x, y - origin.y, z - origin.z);
|
||||
voxels[index] = Voxel.Boundary;
|
||||
|
||||
if (triangleIndices != null)
|
||||
triangleIndices[index].Add(triangleIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IEnumerator Voxelize(Matrix4x4 transform, bool generateTriangleIndices = false)
|
||||
{
|
||||
voxelSize = Mathf.Max(0.0001f, voxelSize);
|
||||
|
||||
var xfBounds = input.bounds.Transform(transform);
|
||||
|
||||
// Calculate min and max voxels, adding a 1-voxel margin.
|
||||
origin = GetPointVoxel(xfBounds.min) - new Vector3Int(1, 1, 1);
|
||||
Vector3Int max = GetPointVoxel(xfBounds.max) + new Vector3Int(1, 1, 1);
|
||||
|
||||
resolution = new Vector3Int(max.x - origin.x + 1, max.y - origin.y + 1, max.z - origin.z + 1);
|
||||
|
||||
// Allocate voxels array, and initialize them to "inside" the mesh:
|
||||
voxels = new Voxel[resolution.x * resolution.y * resolution.z];
|
||||
|
||||
for (int x = 0; x < resolution.x; ++x)
|
||||
for (int y = 0; y < resolution.y; ++y)
|
||||
for (int z = 0; z < resolution.z; ++z)
|
||||
this[x, y, z] = Voxel.Inside;
|
||||
|
||||
// Allocate triangle lists:
|
||||
if (generateTriangleIndices)
|
||||
{
|
||||
triangleIndices = new List<int>[voxels.Length];
|
||||
for (int i = 0; i < triangleIndices.Length; ++i)
|
||||
triangleIndices[i] = new List<int>(4);
|
||||
}
|
||||
else
|
||||
triangleIndices = null;
|
||||
|
||||
// Get input triangles and vertices:
|
||||
int[] triIndices = input.triangles;
|
||||
Vector3[] vertices = input.vertices;
|
||||
|
||||
// Generate surface voxels:
|
||||
for (int i = 0; i < triIndices.Length; i += 3)
|
||||
{
|
||||
Vector3 v1 = transform.MultiplyPoint3x4(vertices[triIndices[i]]);
|
||||
Vector3 v2 = transform.MultiplyPoint3x4(vertices[triIndices[i + 1]]);
|
||||
Vector3 v3 = transform.MultiplyPoint3x4(vertices[triIndices[i + 2]]);
|
||||
|
||||
Bounds triBounds = GetTriangleBounds(v1, v2, v3);
|
||||
|
||||
AppendOverlappingVoxels(triBounds, v1, v2, v3, i/3);
|
||||
|
||||
if (i % 150 == 0)
|
||||
yield return new CoroutineJob.ProgressInfo("Voxelizing mesh...", i / (float)triIndices.Length);
|
||||
}
|
||||
|
||||
// Flood fill outside the mesh. This deals with multiple disjoint regions, and non-watertight models.
|
||||
var fillCoroutine = FloodFill();
|
||||
while (fillCoroutine.MoveNext())
|
||||
yield return fillCoroutine.Current;
|
||||
}
|
||||
|
||||
public void BoundaryThinning()
|
||||
{
|
||||
for (int x = 0; x < resolution.x; ++x)
|
||||
for (int y = 0; y < resolution.y; ++y)
|
||||
for (int z = 0; z < resolution.z; ++z)
|
||||
if (this[x, y, z] == Voxel.Boundary)
|
||||
this[x, y, z] = Voxel.Inside;
|
||||
|
||||
for (int x = 0; x < resolution.x; ++x)
|
||||
for (int y = 0; y < resolution.y; ++y)
|
||||
for (int z = 0; z < resolution.z; ++z)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int j = 0; j < faceNeighborhood.Length; ++j)
|
||||
{
|
||||
var index = faceNeighborhood[j];
|
||||
if (VoxelExists(index.x + x, index.y + y, index.z + z) && this[index.x + x, index.y + y, index.z + z] != Voxel.Outside)
|
||||
{
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
|
||||
if (sum % faceNeighborhood.Length != 0 && this[x, y, z] == Voxel.Inside)
|
||||
this[x, y, z] = Voxel.Boundary;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator FloodFill()
|
||||
{
|
||||
Queue<Vector3Int> queue = new Queue<Vector3Int>();
|
||||
queue.Enqueue(new Vector3Int(0, 0, 0));
|
||||
|
||||
this[0, 0, 0] = Voxel.Outside;
|
||||
|
||||
int i = 0;
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
Vector3Int c = queue.Dequeue();
|
||||
Vector3Int v;
|
||||
|
||||
if (c.x < resolution.x - 1 && this[c.x + 1, c.y, c.z] == Voxel.Inside)
|
||||
{
|
||||
v = new Vector3Int(c.x + 1, c.y, c.z);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
if (c.x > 0 && this[c.x - 1, c.y, c.z] == Voxel.Inside)
|
||||
{
|
||||
v = new Vector3Int(c.x - 1, c.y, c.z);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
if (c.y < resolution.y - 1 && this[c.x, c.y + 1, c.z] == Voxel.Inside)
|
||||
{
|
||||
v = new Vector3Int(c.x, c.y + 1, c.z);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
if (c.y > 0 && this[c.x, c.y - 1, c.z] == Voxel.Inside )
|
||||
{
|
||||
v = new Vector3Int(c.x, c.y - 1, c.z);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
|
||||
if (c.z < resolution.z - 1 && this[c.x, c.y, c.z + 1] == Voxel.Inside)
|
||||
{
|
||||
v = new Vector3Int(c.x, c.y, c.z + 1);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
if (c.z > 0 && this[c.x, c.y, c.z - 1] == Voxel.Inside)
|
||||
{
|
||||
v = new Vector3Int(c.x, c.y, c.z - 1);
|
||||
this[v.x, v.y, v.z] = Voxel.Outside;
|
||||
queue.Enqueue(v);
|
||||
}
|
||||
|
||||
if (++i % 150 == 0)
|
||||
yield return new CoroutineJob.ProgressInfo("Filling mesh...", i / (float)voxels.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsIntersecting(in Bounds box, Vector3 v1, Vector3 v2, Vector3 v3)
|
||||
{
|
||||
v1 -= box.center;
|
||||
v2 -= box.center;
|
||||
v3 -= box.center;
|
||||
|
||||
var ab = v2 - v1;
|
||||
var bc = v3 - v2;
|
||||
var ca = v1 - v3;
|
||||
|
||||
//cross with (1, 0, 0)
|
||||
var a00 = new Vector3(0, -ab.z, ab.y);
|
||||
var a01 = new Vector3(0, -bc.z, bc.y);
|
||||
var a02 = new Vector3(0, -ca.z, ca.y);
|
||||
|
||||
//cross with (0, 1, 0)
|
||||
var a10 = new Vector3(ab.z, 0, -ab.x);
|
||||
var a11 = new Vector3(bc.z, 0, -bc.x);
|
||||
var a12 = new Vector3(ca.z, 0, -ca.x);
|
||||
|
||||
//cross with (0, 0, 1)
|
||||
var a20 = new Vector3(-ab.y, ab.x, 0);
|
||||
var a21 = new Vector3(-bc.y, bc.x, 0);
|
||||
var a22 = new Vector3(-ca.y, ca.x, 0);
|
||||
|
||||
if (
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a00) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a01) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a02) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a10) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a11) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a12) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a20) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a21) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, a22) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, Vector3.right) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, Vector3.up) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, Vector3.forward) ||
|
||||
!TriangleAabbSATTest(v1, v2, v3, box.extents, Vector3.Cross(ab, bc))
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TriangleAabbSATTest(in Vector3 v0, in Vector3 v1, in Vector3 v2, in Vector3 aabbExtents, in Vector3 axis)
|
||||
{
|
||||
float p0 = Vector3.Dot(v0, axis);
|
||||
float p1 = Vector3.Dot(v1, axis);
|
||||
float p2 = Vector3.Dot(v2, axis);
|
||||
|
||||
float r = aabbExtents.x * Mathf.Abs(axis.x) +
|
||||
aabbExtents.y * Mathf.Abs(axis.y) +
|
||||
aabbExtents.z * Mathf.Abs(axis.z);
|
||||
|
||||
float maxP = Mathf.Max(p0, Mathf.Max(p1, p2));
|
||||
float minP = Mathf.Min(p0, Mathf.Min(p1, p2));
|
||||
|
||||
return !(Mathf.Max(-maxP, minP) > r);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user