去掉obi,使用自写绳索

This commit is contained in:
2026-02-23 20:51:03 +08:00
parent cb636f862d
commit 91e2309eeb
2011 changed files with 2593 additions and 190578 deletions

View File

@@ -1,98 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Collections;
using Unity.Mathematics;
namespace Obi
{
public struct BurstBoxQuery : BurstLocalOptimization.IDistanceFunction
{
public BurstQueryShape shape;
public BurstAffineTransform colliderToSolver;
public void Evaluate(float4 point, float4 radii, quaternion orientation, ref BurstLocalOptimization.SurfacePoint projectedPoint)
{
float4 center = shape.center * colliderToSolver.scale;
float4 size = shape.size * colliderToSolver.scale * 0.5f;
// clamp the point to the surface of the box:
point = colliderToSolver.InverseTransformPointUnscaled(point) - center;
/*if (shape.is2D != 0)
point[2] = 0;*/
// get minimum distance for each axis:
float4 distances = size - math.abs(point);
if (distances.x >= 0 && distances.y >= 0 && distances.z >= 0)
{
// find minimum distance in all three axes and the axis index:
float min = float.MaxValue;
int axis = 0;
for (int i = 0; i < 3; ++i)
{
if (distances[i] < min)
{
min = distances[i];
axis = i;
}
}
projectedPoint.normal = float4.zero;
projectedPoint.point = point;
projectedPoint.normal[axis] = point[axis] > 0 ? 1 : -1;
projectedPoint.point[axis] = size[axis] * projectedPoint.normal[axis];
}
else
{
projectedPoint.point = math.clamp(point, -size, size);
projectedPoint.normal = math.normalizesafe(point - projectedPoint.point);
}
projectedPoint.point = colliderToSolver.TransformPointUnscaled(projectedPoint.point + center + projectedPoint.normal * shape.contactOffset);
projectedPoint.normal = colliderToSolver.TransformDirection(projectedPoint.normal);
}
public void Query(int shapeIndex,
NativeArray<float4> positions,
NativeArray<quaternion> orientations,
NativeArray<float4> radii,
NativeArray<int> simplices,
int simplexIndex,
int simplexStart,
int simplexSize,
NativeQueue<BurstQueryResult>.ParallelWriter results,
int optimizationIterations,
float optimizationTolerance)
{
var co = new BurstQueryResult { simplexIndex = simplexIndex, queryIndex = shapeIndex };
float4 simplexBary = BurstMath.BarycenterForSimplexOfSize(simplexSize);
var colliderPoint = BurstLocalOptimization.Optimize(ref this, positions, orientations, radii, simplices, simplexStart, simplexSize,
ref simplexBary, out float4 convexPoint, optimizationIterations, optimizationTolerance);
float4 simplexPrevPosition = float4.zero;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
simplexPrevPosition += positions[particleIndex] * simplexBary[j];
simplexRadius += BurstMath.EllipsoidRadius(colliderPoint.normal, orientations[particleIndex], radii[particleIndex].xyz) * simplexBary[j];
}
co.queryPoint = colliderPoint.point;
co.normal = colliderPoint.normal;
co.simplexBary = simplexBary;
co.distance = math.dot(simplexPrevPosition - colliderPoint.point, colliderPoint.normal) - simplexRadius;
if (co.distance <= shape.maxDistance)
results.Enqueue(co);
}
}
}
#endif

View File

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

View File

@@ -1,92 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
namespace Obi
{
public struct BurstRay : BurstLocalOptimization.IDistanceFunction
{
public BurstQueryShape shape;
public BurstAffineTransform colliderToSolver;
public void Evaluate(float4 point, float4 radii, quaternion orientation, ref BurstLocalOptimization.SurfacePoint projectedPoint)
{
float4x4 simplexToSolver = float4x4.TRS(point.xyz, orientation, radii.xyz);
float4x4 solverToSimplex = math.inverse(simplexToSolver);
float4x4 colliderToSimplex = math.mul(solverToSimplex, float4x4.TRS(colliderToSolver.translation.xyz, colliderToSolver.rotation, colliderToSolver.scale.xyz));
// express ray in simplex space (ellipsoid == scaled sphere)
float4 rayOrigin = math.mul(colliderToSimplex, new float4(shape.center.xyz,1));
float4 rayDirection = math.normalizesafe(math.mul(colliderToSimplex, new float4(shape.size.xyz,0)));
float rayDistance = ObiUtils.RaySphereIntersection(rayOrigin.xyz, rayDirection.xyz, float3.zero, 1);
if (rayDistance < 0)
{
point = colliderToSolver.InverseTransformPointUnscaled(point);
float4 centerLine = BurstMath.NearestPointOnEdge(shape.center * colliderToSolver.scale, (shape.center + shape.size) * colliderToSolver.scale, point, out float mu);
float4 centerToPoint = point - centerLine;
float distanceToCenter = math.length(centerToPoint);
float4 normal = centerToPoint / (distanceToCenter + BurstMath.epsilon);
projectedPoint.point = colliderToSolver.TransformPointUnscaled(centerLine + normal * shape.contactOffset);
projectedPoint.normal = colliderToSolver.TransformDirection(normal);
}
else
{
float4 rayPoint = math.mul(simplexToSolver, new float4((rayOrigin + rayDirection * rayDistance).xyz,1));
float4 normal = math.normalizesafe(new float4((point - rayPoint).xyz,0));
projectedPoint.point = rayPoint + normal * shape.contactOffset;
projectedPoint.normal = normal;
}
}
public void Query(int shapeIndex,
NativeArray<float4> positions,
NativeArray<quaternion> orientations,
NativeArray<float4> radii,
NativeArray<int> simplices,
int simplexIndex,
int simplexStart,
int simplexSize,
NativeQueue<BurstQueryResult>.ParallelWriter results,
int optimizationIterations,
float optimizationTolerance)
{
var co = new BurstQueryResult { simplexIndex = simplexIndex, queryIndex = shapeIndex };
float4 simplexBary = BurstMath.BarycenterForSimplexOfSize(simplexSize);
var colliderPoint = BurstLocalOptimization.Optimize(ref this, positions, orientations, radii, simplices, simplexStart, simplexSize,
ref simplexBary, out float4 convexPoint, optimizationIterations, optimizationTolerance);
float4 simplexPrevPosition = float4.zero;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
simplexPrevPosition += positions[particleIndex] * simplexBary[j];
simplexRadius += BurstMath.EllipsoidRadius(colliderPoint.normal, orientations[particleIndex], radii[particleIndex].xyz) * simplexBary[j];
}
co.queryPoint = colliderPoint.point;
co.normal = colliderPoint.normal;
co.simplexBary = simplexBary;
co.distance = math.dot(simplexPrevPosition - colliderPoint.point, colliderPoint.normal) - simplexRadius;
if (co.distance <= shape.maxDistance)
{
float4 pointOnRay = colliderPoint.point + colliderPoint.normal * co.distance;
co.distanceAlongRay = math.dot(pointOnRay.xyz - shape.center.xyz, math.normalizesafe(shape.size.xyz));
results.Enqueue(co);
}
}
}
}
#endif

View File

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

View File

@@ -1,69 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Collections;
using Unity.Mathematics;
namespace Obi
{
public struct BurstSphereQuery : BurstLocalOptimization.IDistanceFunction
{
public BurstQueryShape shape;
public BurstAffineTransform colliderToSolver;
public void Evaluate(float4 point, float4 radii, quaternion orientation, ref BurstLocalOptimization.SurfacePoint projectedPoint)
{
float4 center = shape.center * colliderToSolver.scale;
point = colliderToSolver.InverseTransformPointUnscaled(point) - center;
/*if (shape.is2D != 0)
point[2] = 0;*/
float radius = shape.size.x * math.cmax(colliderToSolver.scale.xyz);
float distanceToCenter = math.length(point);
float4 normal = point / (distanceToCenter + BurstMath.epsilon);
projectedPoint.point = colliderToSolver.TransformPointUnscaled(center + normal * (radius + shape.contactOffset));
projectedPoint.normal = colliderToSolver.TransformDirection(normal);
}
public void Query(int shapeIndex,
NativeArray<float4> positions,
NativeArray<quaternion> orientations,
NativeArray<float4> radii,
NativeArray<int> simplices,
int simplexIndex,
int simplexStart,
int simplexSize,
NativeQueue<BurstQueryResult>.ParallelWriter results,
int optimizationIterations,
float optimizationTolerance)
{
var co = new BurstQueryResult { simplexIndex = simplexIndex, queryIndex = shapeIndex };
float4 simplexBary = BurstMath.BarycenterForSimplexOfSize(simplexSize);
var colliderPoint = BurstLocalOptimization.Optimize(ref this, positions, orientations, radii, simplices, simplexStart, simplexSize,
ref simplexBary, out float4 convexPoint, optimizationIterations, optimizationTolerance);
float4 simplexPrevPosition = float4.zero;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
simplexPrevPosition += positions[particleIndex] * simplexBary[j];
simplexRadius += BurstMath.EllipsoidRadius(colliderPoint.normal, orientations[particleIndex], radii[particleIndex].xyz) * simplexBary[j];
}
co.queryPoint = colliderPoint.point;
co.normal = colliderPoint.normal;
co.simplexBary = simplexBary;
co.distance = math.dot(simplexPrevPosition - colliderPoint.point, colliderPoint.normal) - simplexRadius;
if (co.distance <= shape.maxDistance)
results.Enqueue(co);
}
}
}
#endif

View File

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

View File

@@ -1,129 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Jobs;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Burst;
namespace Obi
{
[BurstCompile]
unsafe struct SpatialQueryJob : IJobParallelFor
{
//collider grid:
[ReadOnly] public NativeMultilevelGrid<int> grid;
// particle arrays:
[ReadOnly] public NativeArray<float4> positions;
[ReadOnly] public NativeArray<quaternion> orientations;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<int> filters;
// simplex arrays:
[ReadOnly] public NativeArray<int> simplices;
[ReadOnly] public SimplexCounts simplexCounts;
// query arrays:
[ReadOnly] public NativeArray<BurstQueryShape> shapes;
[ReadOnly] public NativeArray<BurstAffineTransform> transforms;
// output contacts queue:
[WriteOnly]
[NativeDisableParallelForRestriction]
public NativeQueue<BurstQueryResult>.ParallelWriter results;
// auxiliar data:
[ReadOnly] public BurstAffineTransform worldToSolver;
[ReadOnly] public Oni.SolverParameters parameters;
// execute for each query shape:
public void Execute(int i)
{
var shapeToSolver = worldToSolver * transforms[i];
// calculate solver-space aabb of query shape:
BurstAabb queryBoundsSS = CalculateShapeAABB(shapes[i]).Transformed(shapeToSolver);
var shapeCategory = shapes[i].filter & ObiUtils.FilterCategoryBitmask;
var shapeMask = (shapes[i].filter & ObiUtils.FilterMaskBitmask) >> 16;
bool is2D = parameters.mode == Oni.SolverParameters.Mode.Mode2D;
// iterate over all occupied cells:
for (int c = 0; c < grid.usedCells.Length; ++c)
{
var cell = grid.usedCells[c];
// calculate thickened grid bounds:
float size = NativeMultilevelGrid<int>.CellSizeOfLevel(cell.Coords.w);
float4 cellPos = (float4)cell.Coords * size;
BurstAabb cellBounds = new BurstAabb(cellPos - new float4(size), cellPos + new float4(2 * size));
// if cell and query bounds intersect:
if (cellBounds.IntersectsAabb(in queryBoundsSS, is2D))
{
// iterate over cell contents:
for (int k = 0; k < cell.Length; ++k)
{
int simplexStart = simplexCounts.GetSimplexStartAndSize(cell[k], out int simplexSize);
// check if any simplex particle and the query shape should collide:
bool shouldCollide = false;
for (int j = 0; j < simplexSize; ++j)
{
var simplexCategory = filters[simplices[simplexStart + j]] & ObiUtils.FilterCategoryBitmask;
var simplexMask = (filters[simplices[simplexStart + j]] & ObiUtils.FilterMaskBitmask) >> 16;
shouldCollide |= (simplexCategory & shapeMask) != 0 && (simplexMask & shapeCategory) != 0;
}
if (shouldCollide)
Query(shapes[i], shapeToSolver, i, cell[k], simplexStart, simplexSize);
}
}
}
}
private BurstAabb CalculateShapeAABB(in BurstQueryShape shape)
{
float offset = shape.contactOffset + shape.maxDistance;
switch (shape.type)
{
case QueryShape.QueryType.Sphere:
return new BurstAabb(shape.center, shape.center, shape.size.x + offset);
case QueryShape.QueryType.Box:
return new BurstAabb(shape.center - shape.size*0.5f - offset, shape.center + shape.size * 0.5f + offset);
case QueryShape.QueryType.Ray:
return new BurstAabb(shape.center, shape.center + shape.size, offset);
}
return new BurstAabb();
}
private void Query(in BurstQueryShape shape,
in BurstAffineTransform shapeToSolver,
int shapeIndex,
int simplexIndex,
int simplexStart,
int simplexSize)
{
switch (shape.type)
{
case QueryShape.QueryType.Sphere:
BurstSphereQuery sphereShape = new BurstSphereQuery { colliderToSolver = shapeToSolver, shape = shape};
sphereShape.Query(shapeIndex, positions, orientations, radii, simplices,
simplexIndex, simplexStart, simplexSize, results, parameters.surfaceCollisionIterations, parameters.surfaceCollisionTolerance);
break;
case QueryShape.QueryType.Box:
BurstBoxQuery boxShape = new BurstBoxQuery { colliderToSolver = shapeToSolver, shape = shape};
boxShape.Query(shapeIndex, positions, orientations, radii, simplices,
simplexIndex, simplexStart, simplexSize, results, parameters.surfaceCollisionIterations, parameters.surfaceCollisionTolerance);
break;
case QueryShape.QueryType.Ray:
BurstRay rayShape = new BurstRay { colliderToSolver = shapeToSolver, shape = shape };
rayShape.Query(shapeIndex, positions, orientations, radii, simplices,
simplexIndex, simplexStart, simplexSize, results, parameters.surfaceCollisionIterations, parameters.surfaceCollisionTolerance);
break;
}
}
}
}
#endif

View File

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