添加插件

This commit is contained in:
2025-11-10 00:08:26 +08:00
parent 4059c207c0
commit 76f80db694
2814 changed files with 436400 additions and 178 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 645b177bec2c444aaa188661f611418a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6951f2457b77d4daf9f257e128b6dfb2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using System;
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:
#pragma warning disable 0414
private int pad0;
private int pad1;
private int pad2;
#pragma warning restore 0414
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 769e6e9ced39347bc96146f1858ab648
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4b6d58d9b0a8a4f7ea09067526d713cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System;
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 FromTransform3D(Transform source, ObiRigidbody rb)
{
if (rb != null && rb.unityRigidbody != null)
{
translation = source.position - rb.unityRigidbody.transform.position + rb.position;
rotation = (source.rotation * Quaternion.Inverse(rb.unityRigidbody.transform.rotation)) * rb.rotation;
}
else
{
translation = source.position;
rotation = source.rotation;
}
scale = source.lossyScale;
}
public void FromTransform2D(Transform source, ObiRigidbody2D rb)
{
if (rb != null && rb.unityRigidbody != null)
{
translation = source.position - rb.unityRigidbody.transform.position + (Vector3)rb.position;
rotation = (source.rotation * Quaternion.Inverse(rb.unityRigidbody.transform.rotation)) * Quaternion.AngleAxis(rb.rotation, Vector3.forward);
}
else
{
translation = source.position;
rotation = source.rotation;
}
scale = source.lossyScale;
translation[2] = 0;
}
public AffineTransform Inverse()
{
var conj = Quaternion.Inverse(rotation);
var invScale = new Vector3(1 / scale.x, 1 / scale.y, 1 / scale.z);
return new AffineTransform(conj * Vector3.Scale(translation , -invScale),
conj,
invScale);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c8eff617709c457a85387e2f72187aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d141c0731e7c43e8be29d786670298c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d1727eb52e8f4619a5dc1084db72db0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 128610647c5e64bc284f13abefda3a58
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using System;
using UnityEngine;
namespace Obi
{
public interface IBounded
{
Aabb GetBounds();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 44a65f44be3e24beca5faaa7d2c28480
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 786fc387d096a4921bd52253d3f51b02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
public int constraintCount;
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 + (rb.unityRigidbody.useGravity ? Physics.gravity * Time.fixedDeltaTime : Vector3.zero);
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2273ddd528c3a44af9ef3f985a620e24
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
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 forceZoneIndex; // index of the associated force zone in the collision world.
public int filter; // bitwise category/mask.
public int flags; // first bit whether the collider is 2D (1) or 3D (0), second bit whether it's a trigger (1) or regular collider (0),
// third bit (sign) determines whether shape is inverted or not.
public bool is2D
{
get => (flags & 1) != 0;
set => flags |= value ? 1 : 0;
}
public bool isTrigger
{
get => ((flags & 1 << 1) != 0) || forceZoneIndex >= 0;
set => flags |= value ? 1 << 1 : 0;
}
public float sign
{
get => (flags & 1 << 2) != 0 ? -1 : 1;
}
public void SetSign(bool inverted)
{
if (inverted) flags |= 1 << 2;
else flags &= ~(1 << 2);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38d82eae8f8744bdc9f0795c1fd3b317
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
namespace Obi
{
[StructLayout(LayoutKind.Sequential)]
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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed8262093b9b44e8abb2557ed2624c4d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Mathematics;
#endif
namespace Obi
{
public struct ContactEffectiveMasses
{
public float normalInvMassA;
public float tangentInvMassA;
public float bitangentInvMassA;
public float normalInvMassB;
public float tangentInvMassB;
public float bitangentInvMassB;
public float TotalNormalInvMass => normalInvMassA + normalInvMassB;
public float TotalTangentInvMass => tangentInvMassA + tangentInvMassB;
public float TotalBitangentInvMass => bitangentInvMassA + bitangentInvMassB;
public void ClearContactMassesA()
{
normalInvMassA = tangentInvMassA = bitangentInvMassA = 0;
}
public void ClearContactMassesB()
{
normalInvMassB = tangentInvMassB = bitangentInvMassB = 0;
}
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
public void CalculateContactMassesA(float invMass,
float4 inverseInertiaTensor,
float4 position,
quaternion orientation,
float4 contactPoint,
float4 normal,
float4 tangent,
float4 bitangent,
bool rollingContacts)
{
// initialize inverse linear masses:
normalInvMassA = tangentInvMassA = bitangentInvMassA = invMass;
if (rollingContacts)
{
float4 rA = contactPoint - position;
float4x4 solverInertiaA = BurstMath.TransformInertiaTensor(inverseInertiaTensor, orientation);
normalInvMassA += BurstMath.RotationalInvMass(solverInertiaA, rA, normal);
tangentInvMassA += BurstMath.RotationalInvMass(solverInertiaA, rA, tangent);
bitangentInvMassA += BurstMath.RotationalInvMass(solverInertiaA, rA, bitangent);
}
}
public void CalculateContactMassesB(float invMass,
float4 inverseInertiaTensor,
float4 position,
quaternion orientation,
float4 contactPoint,
float4 normal,
float4 tangent,
float4 bitangent,
bool rollingContacts)
{
// initialize inverse linear masses:
normalInvMassB = tangentInvMassB = bitangentInvMassB = invMass;
if (rollingContacts)
{
float4 rB = contactPoint - position;
float4x4 solverInertiaB = BurstMath.TransformInertiaTensor(inverseInertiaTensor, orientation);
normalInvMassB += BurstMath.RotationalInvMass(solverInertiaB, rB, normal);
tangentInvMassB += BurstMath.RotationalInvMass(solverInertiaB, rB, tangent);
bitangentInvMassB += BurstMath.RotationalInvMass(solverInertiaB, rB, bitangent);
}
}
public void CalculateContactMassesB(in BurstRigidbody rigidbody, in BurstAffineTransform solver2World, float4 pointB, float4 normal, float4 tangent, float4 bitangent)
{
float4 rB = solver2World.TransformPoint(pointB) - rigidbody.com;
// initialize inverse linear masses:
normalInvMassB = tangentInvMassB = bitangentInvMassB = rigidbody.inverseMass;
normalInvMassB += BurstMath.RotationalInvMass(rigidbody.inverseInertiaTensor, rB, normal);
tangentInvMassB += BurstMath.RotationalInvMass(rigidbody.inverseInertiaTensor, rB, tangent);
bitangentInvMassB += BurstMath.RotationalInvMass(rigidbody.inverseInertiaTensor, rB, bitangent);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b11c7db3414246668eb72ef55dd737f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using UnityEngine;
using System;
namespace Obi
{
[Serializable]
public struct EmitPoint
{
public Vector4 position;
public Vector4 direction;
public Vector4 velocity;
public Color color;
public EmitPoint(Vector3 position, Vector3 direction)
{
this.position = position;
this.direction = direction;
this.velocity = Vector4.zero;
this.color = Color.white;
}
public EmitPoint(Vector3 position, Vector3 direction, Color color)
{
this.position = position;
this.direction = direction;
this.velocity = Vector4.zero;
this.color = color;
}
public EmitPoint GetTransformed(Matrix4x4 transform, Matrix4x4 prevTransform, Color multiplyColor, float deltaTime)
{
var ep = new EmitPoint(transform.MultiplyPoint3x4(position),
transform.MultiplyVector(direction),
color * multiplyColor);
ep.velocity = deltaTime > 0 ? ((Vector3)ep.position - prevTransform.MultiplyPoint3x4(position)) / deltaTime : Vector3.zero;
return ep;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0c9d9016e8744477adde7f1afe28798
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using UnityEngine;
namespace Obi
{
public struct EmittedParticleData
{
public Vector4 fluidMaterial;
public Vector4 fluidMaterial2;
public Vector4 fluidInterface;
public Vector4 userData;
public int phase;
public float invMass;
public float radius;
public float volume;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 032673eb10713468fb72d04ad5cc6b26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using UnityEngine;
using System;
namespace Obi
{
[Serializable]
public struct ForceZone
{
public enum ForceMode
{
Force,
Acceleration,
Wind,
}
public enum ZoneType
{
Directional,
Radial,
Vortex,
Void
}
public enum DampingDirection
{
All, // damps motion in all directions
ForceDirection, // damps motion in the direction of force.
SurfaceDirection // damps motion toward/away from the surface of the zone.
}
public Color color;
public ZoneType type;
public ForceMode mode;
public DampingDirection dampingDir;
public float intensity;
public float minDistance;
public float maxDistance;
public float falloffPower;
public float damping;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c189f8dc8ade4e14a960f3b6eb11f14
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using UnityEngine;
namespace Obi
{
public struct InertialFrame
{
public AffineTransform frame;
public AffineTransform prevFrame;
public Vector4 velocity;
public Vector4 angularVelocity;
public Vector4 acceleration;
public Vector4 angularAcceleration;
public InertialFrame(Vector4 position, Vector4 scale, Quaternion rotation)
{
this.frame = new AffineTransform(position, rotation, scale);
this.prevFrame = frame;
velocity = Vector4.zero;
angularVelocity = Vector4.zero;
acceleration = Vector4.zero;
angularAcceleration = Vector4.zero;
}
public InertialFrame(AffineTransform frame)
{
this.frame = frame;
this.prevFrame = frame;
velocity = Vector4.zero;
angularVelocity = Vector4.zero;
acceleration = Vector4.zero;
angularAcceleration = Vector4.zero;
}
public void Update(Vector4 position, Vector4 scale, Quaternion rotation, float dt)
{
prevFrame = frame;
Vector4 prevVelocity = velocity;
Vector4 prevAngularVelocity = angularVelocity;
frame.translation = position;
frame.rotation = rotation;
frame.scale = scale;
velocity = ObiIntegration.DifferentiateLinear(frame.translation, prevFrame.translation, dt);
angularVelocity = ObiIntegration.DifferentiateAngular(frame.rotation, prevFrame.rotation, dt);
acceleration = ObiIntegration.DifferentiateLinear(velocity, prevVelocity, dt);
angularAcceleration = ObiIntegration.DifferentiateLinear(angularVelocity, prevAngularVelocity, dt);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7420f38eb63f04112a965d884f75d176
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2f5d490805c6e4ee6b39c067e26e490c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96e807cda064c47c1aed643600660143
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f741a9b23bfd4f55979eb1a18146388
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c960e0992a4cf4d7195a513c5fd5f550
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50b49a1cc8de340ebb8d6a89fb044c1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aefb86b129c07425fa244ada261f4184
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53a29ecfe0ecb4db3a344781b333776d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45031e9a1b74143c4a6df44e2b999373
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6d32cd2f844a48cab0508f798fc1ff4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f377d76dadb3945b39cfac818a54d1be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
using UnityEngine;
namespace Obi
{
[Serializable]
public class ObiNativeContactList : ObiNativeList<Oni.Contact>
{
public ObiNativeContactList() { }
public ObiNativeContactList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = new Oni.Contact();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa58238d45b934704aede27415ce4242
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17462646d532945749479c75ba3cd0d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e18334e185814395aac025a1d4afe70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d602b9fba6fc4e78a78b8dee0acd309
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 474a95d0d9d37494f9ac5201e262b8a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
using UnityEngine;
namespace Obi
{
[Serializable]
public class ObiNativeEffectiveMassesList : ObiNativeList<ContactEffectiveMasses>
{
public ObiNativeEffectiveMassesList() { }
public ObiNativeEffectiveMassesList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = new ContactEffectiveMasses();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc8b00cd716564eff82fc19de0c458a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
namespace Obi
{
[Serializable]
public class ObiNativeEmitPointList : ObiNativeList<EmitPoint>
{
public ObiNativeEmitPointList() { }
public ObiNativeEmitPointList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = new EmitPoint();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3cbd83091221b46c9a724f3275281d2e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7cf0e80d841ca4425a99bc2d4beb3547
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System;
using UnityEngine;
namespace Obi
{
[Serializable]
public class ObiNativeForceZoneList : ObiNativeList<ForceZone>
{
public ObiNativeForceZoneList() { }
public ObiNativeForceZoneList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = new ForceZone();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2815feee105f648149e0f5b1b22954bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61e8d2ecda37e442aa8f24756395f12a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using System;
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18f572cdc044a4caabe29c40944c0987
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f8a8fd8447dc458bab16dea3dfd5580
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6201c3f1582cd43deaaf41286f802126
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,708 @@
using System;
using System.Text;
using System.Collections.Generic;
using UnityEngine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System.Collections;
using UnityEngine.Rendering;
using System.Linq;
namespace Obi
{
public unsafe 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 GraphicsBuffer.Target m_ComputeBufferType;
protected GraphicsBuffer m_ComputeBuffer;
protected GraphicsBuffer m_CountBuffer; // used to hold the counter value in case m_ComputeBufferType is Counter.
protected bool computeBufferDirty = false;
protected AsyncGPUReadbackRequest m_AsyncRequest;
protected AsyncGPUReadbackRequest m_CounterAsyncRequest;
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);
if (m_ComputeBuffer != null && m_ComputeBuffer.IsValid() && m_ComputeBufferType == GraphicsBuffer.Target.Counter)
m_ComputeBuffer.SetCounterValue((uint)m_Count);
}
}
get { return m_Count; }
}
public int capacity
{
get { return m_Capacity; }
}
public int stride
{
get { return m_Stride; }
}
public bool isCreated
{
get { return m_AlignedPtr != null; }
}
public bool noReadbackInFlight
{
get { return m_AsyncRequest.done && (m_ComputeBufferType != GraphicsBuffer.Target.Counter || m_CounterAsyncRequest.done); }
}
// Returns the current compute buffer representation of this list. Will return null if AsComputeBuffer() hasn't been called yet,
// or if the list has been disposed of.
public GraphicsBuffer computeBuffer
{
get { return m_ComputeBuffer; }
}
public T this[int index]
{
get
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (index < 0 || index >= m_Capacity)
{
throw new IndexOutOfRangeException($"Reading from index {index} is out of range of '{m_Capacity}' Capacity.");
}
#endif
return UnsafeUtility.ReadArrayElementWithStride<T>(m_AlignedPtr, index, m_Stride);
}
set
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (index < 0 || index >= m_Capacity)
{
throw new IndexOutOfRangeException($"Writing to index {index} is out of range of '{m_Capacity}' Capacity.");
}
#endif
UnsafeUtility.WriteArrayElementWithStride<T>(m_AlignedPtr, index, m_Stride, value);
computeBufferDirty = true;
}
}
// Declare parameterless constructor, called by Unity upon deserialization.
protected ObiNativeList()
{
m_Stride = UnsafeUtility.SizeOf<T>();
#if ENABLE_UNITY_COLLECTIONS_CHECKS
m_SafetyHandle = AtomicSafetyHandle.Create();
#endif
}
public ObiNativeList(int capacity = 8, int alignment = 16)
{
m_Stride = UnsafeUtility.SizeOf<T>();
#if ENABLE_UNITY_COLLECTIONS_CHECKS
m_SafetyHandle = AtomicSafetyHandle.Create();
#endif
m_AlignBytes = alignment;
ChangeCapacity(capacity);
}
~ObiNativeList()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
DisposeOfComputeBuffer();
if (isCreated)
{
// free unmanaged memory buffer:
UnsafeUtility.Free(m_AlignedPtr, Allocator.Persistent);
m_AlignedPtr = null;
m_Count = m_Capacity = 0;
#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 DisposeOfComputeBuffer()
{
// dispose of compute buffer representation:
if (m_ComputeBuffer != null)
{
// if there's any pending async readback, finalize it.
// otherwise we pull the rug from under the readbacks' feet and that's no good.
WaitForReadback();
m_ComputeBuffer.Dispose();
m_ComputeBuffer = null;
}
if (m_CountBuffer != null)
{
m_CountBuffer.Dispose();
m_CountBuffer = null;
}
}
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);
}
public NativeArray<T> AsNativeArray()
{
return AsNativeArray<T>(m_Count);
}
// Reinterprets the data in the list as a native array of the given length, up to the list's capacity.
public NativeArray<U> AsNativeArray<U>(int arrayLength) where U : struct
{
unsafe
{
NativeArray<U> array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<U>(m_AlignedPtr, Mathf.Min(arrayLength, m_Capacity), Allocator.None);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, m_SafetyHandle);
#endif
// assume the NativeArray will write new data, so we'll need to update the computeBuffer upon Upload().
computeBufferDirty = true;
return array;
}
}
// Reinterprets the data in the list as a compute buffer, in case of an empty list it returns a buffer of size 1 with uninitialized content.
public GraphicsBuffer SafeAsComputeBuffer<U>(GraphicsBuffer.Target bufferType = GraphicsBuffer.Target.Structured) where U : struct
{
return AsComputeBuffer<U>(Mathf.Max(1,m_Count), bufferType);
}
// Reinterprets the data in the list as a compute buffer.
public GraphicsBuffer AsComputeBuffer<U>(GraphicsBuffer.Target bufferType = GraphicsBuffer.Target.Structured) where U : struct
{
return AsComputeBuffer<U>(m_Count, bufferType);
}
// Reinterprets the data in the list as a compute buffer of the given length. Returns null if the list is empty.
public GraphicsBuffer AsComputeBuffer<U>(int arrayLength, GraphicsBuffer.Target bufferType = GraphicsBuffer.Target.Structured) where U : struct
{
DisposeOfComputeBuffer();
if (arrayLength > 0)
{
m_ComputeBufferType = bufferType;
m_ComputeBuffer = new GraphicsBuffer(bufferType, arrayLength, UnsafeUtility.SizeOf<U>());
m_ComputeBuffer.SetData(AsNativeArray<U>(arrayLength));
if (bufferType == GraphicsBuffer.Target.Counter)
{
// initialize count to zero, since counter buffers always start empty:
m_Count = 0;
m_ComputeBuffer.SetCounterValue((uint)m_Count);
m_CountBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, 4);
GraphicsBuffer.CopyCount(m_ComputeBuffer, m_CountBuffer, 0);
}
return m_ComputeBuffer;
}
return null;
}
// Kicks a GPU readback request, to bring compute buffer data to this list.
public void Readback<U>(int readcount, bool async) where U : struct
{
if (m_ComputeBuffer != null && m_ComputeBuffer.IsValid() && noReadbackInFlight)
{
var nativeArray = AsNativeArray<U>(readcount);
// When using SafeAsComputeBuffer, we'll get a compute buffer of size 1 even if the list (and the NativeArray) is empty.
// Guard against trying to readback into a smaller NativeArray. Also guard against requesting zero items.
if (nativeArray.Length >= readcount && readcount > 0)
m_AsyncRequest = AsyncGPUReadback.RequestIntoNativeArray(ref nativeArray, m_ComputeBuffer, readcount * UnsafeUtility.SizeOf<U>(), 0);
// For counter buffers, request the counter value too:
if (m_ComputeBufferType == GraphicsBuffer.Target.Counter)
{
GraphicsBuffer.CopyCount(m_ComputeBuffer, m_CountBuffer, 0);
m_CounterAsyncRequest = AsyncGPUReadback.Request(m_CountBuffer, m_CountBuffer.stride, 0, (AsyncGPUReadbackRequest request)=>
{
if (!request.hasError)
m_Count = Mathf.Min(m_Capacity, request.GetData<int>()[0]);
});
}
if (!async)
WaitForReadback();
}
}
public void Readback(bool async = true)
{
// On counter buffers, we shouldn't read data up to m_Count and then update m_Count with the compute buffer's counter value *afterwards*.
// This would lead to reading back less data than we should, so we need to request the entire compute buffer.
if (m_ComputeBuffer != null)
Readback<T>(m_ComputeBuffer.count, async);
}
public void Readback(int readcount ,bool async = true)
{
Readback<T>(readcount, async);
}
// Makes sure any pending changes by the CPU are sent to the GPU.
// If the list data has been changed on the CPU since the last time Unmap() was called and there's a compute buffer associated to it,
// will write the current contents of the list to the compute buffer.
public void Upload<U>(int length, bool force = false) where U : struct
{
if ((computeBufferDirty || force) && m_ComputeBuffer != null && m_ComputeBuffer.IsValid())
m_ComputeBuffer.SetData(AsNativeArray<U>(length));
computeBufferDirty = false;
}
public void Upload(bool force = false)
{
Upload<T>(m_Count,force);
}
public void UploadFullCapacity()
{
Upload<T>(m_Capacity, true);
}
// Waits for the last readback request to be complete, this brings back data from the GPU to the CPU:
public void WaitForReadback()
{
if (isCreated)
{
m_AsyncRequest.WaitForCompletion();
m_CounterAsyncRequest.WaitForCompletion();
}
}
protected void ChangeCapacity(int newCapacity)
{
// invalidate compute buffer:
DisposeOfComputeBuffer();
// allocate a new buffer:
m_Stride = UnsafeUtility.SizeOf<T>();
var newAlignedPtr = UnsafeUtility.Malloc(newCapacity * m_Stride, m_AlignBytes, 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 CopyFrom<U>(NativeArray<U> source, int sourceIndex, int destIndex, int length) where U : struct
{
if (!isCreated || !source.IsCreated || UnsafeUtility.SizeOf<U>() != m_Stride)
throw new ArgumentNullException();
if (length <= 0 || source.Length == 0)
return;
if (sourceIndex >= source.Length || sourceIndex < 0 || destIndex >= m_Count || destIndex < 0 ||
sourceIndex + length > source.Length || destIndex + length > m_Count)
throw new ArgumentOutOfRangeException();
void* sourceAddress = (byte*)source.GetUnsafePtr() + sourceIndex * m_Stride;
void* destAddress = AddressOfElement(destIndex);
UnsafeUtility.MemCpy(destAddress, sourceAddress, length * m_Stride);
}
public void CopyFrom(T[] source, int sourceIndex, int destIndex, int length)
{
if (source == null || !isCreated)
throw new ArgumentNullException();
if (length <= 0 || source.Length == 0)
return;
if (sourceIndex < 0 || destIndex < 0 ||
sourceIndex + length > source.Length || destIndex + length > m_Count)
throw new ArgumentOutOfRangeException();
// pin the managed array and get its address:
ulong sourceHandle;
void* sourceAddress = UnsafeUtility.PinGCArrayAndGetDataAddress(source, out sourceHandle);
void* destAddress = UnsafeUtility.AddressOf(ref UnsafeUtility.ArrayElementAsRef<T>(m_AlignedPtr, destIndex));
UnsafeUtility.MemCpy(destAddress, sourceAddress, length * m_Stride);
// unpin the managed array:
UnsafeUtility.ReleaseGCObject(sourceHandle);
}
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);
computeBufferDirty = true;
this[m_Count++] = item;
}
public void AddReplicate(T value, int times)
{
int appendAt = m_Count;
ResizeUninitialized(m_Count + times);
CopyReplicate(value, appendAt, times);
}
public void AddRange(T[] array)
{
AddRange(array, array.Length);
}
public void AddRange(T[] array, int length)
{
AddRange(array, 0, length);
}
public void AddRange(T[] array, int start, int length)
{
int appendAt = m_Count;
ResizeUninitialized(m_Count + length);
CopyFrom(array, start, appendAt, length);
}
public void AddRange(ObiNativeList<T> array, int length)
{
int appendAt = m_Count;
ResizeUninitialized(m_Count + length);
CopyFrom(array, 0, appendAt, length);
}
public void AddRange(ObiNativeList<T> array, int start, int length)
{
int appendAt = m_Count;
ResizeUninitialized(m_Count + length);
CopyFrom(array, start, appendAt, length);
}
public void AddRange(ObiNativeList<T> array)
{
AddRange(array, array.count);
}
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);
computeBufferDirty = true;
}
}
}
public void WipeToValue(T value)
{
unsafe
{
if (isCreated)
{
void* sourceAddress = UnsafeUtility.AddressOf(ref value);
UnsafeUtility.MemCpyReplicate(m_AlignedPtr, sourceAddress, m_Stride, count);
computeBufferDirty = true;
}
}
}
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)
{
return (void*) ((byte*)m_AlignedPtr + m_Stride * index);
}
public NativeReference<int> GetCountReference(Allocator alloc)
{
return new NativeReference<int>(m_Count, alloc);
}
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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be1183504e86c409d97f706fcfcb0b3f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using System;
using UnityEngine;
namespace Obi
{
[Serializable]
public class ObiNativeMatrix4x4List : ObiNativeList<Matrix4x4>
{
public ObiNativeMatrix4x4List() { } // TODO: WTF???? why does this prevent a crash?
public ObiNativeMatrix4x4List(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = Matrix4x4.identity;
}
public ObiNativeMatrix4x4List(int capacity, int alignment, Matrix4x4 defaultValue) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = defaultValue;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57e079b439b8f4d71966919ca4fa4838
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bad311b87fb6408793370e029c1d625
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 415658bfe3b0f45c285a26d383086a70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a1b44ba5a49564f81bc8eeebbee71cf3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28ae021335a854c3eb91c500cd4c77b6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0eda4a24fce5949d284395fe3a782477
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b7289725194bb4368a4ac8e6cd9a7062
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System;
using UnityEngine;
namespace Obi
{
[Serializable]
public class ObiNativeUIntList : ObiNativeList<uint>
{
public ObiNativeUIntList(int capacity = 8, int alignment = 16) : base(capacity, alignment)
{
for (int i = 0; i < capacity; ++i)
this[i] = 0;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cee276900c5ce412aafe4e23112537eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 097972b931df946398eb40913011ada0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

Some files were not shown because too many files have changed in this diff Show More