fix issue with collision resolve and non-uniform scale box colliders (fixes #32)

This commit is contained in:
Lasse Jon Fuglsang Pedersen 2023-03-20 16:38:35 +01:00
Родитель f0b583c61b
Коммит b1de6b28d2
6 изменённых файлов: 43 добавлений и 19 удалений

Просмотреть файл

@ -180,7 +180,7 @@ namespace Unity.DemoTeam.Hair
// capsule | centerA radius centerB __pad
// sphere | center radius __pad __pad
// torus | center radiusA axis radiusB
// cube | __pad __pad __pad __pad
// cube | extent __pad __pad __pad
public Vector3 pA; public float tA;
public Vector3 pB; public float tB;
@ -308,8 +308,7 @@ namespace Unity.DemoTeam.Hair
type = RuntimeShape.Type.Cube,
data = new RuntimeShape.Data
{
pA = Vector3.zero,
pB = Vector3.one * 0.5f,
pA = worldSize * 0.5f,
},
},
};
@ -640,11 +639,11 @@ namespace Unity.DemoTeam.Hair
break;
case RuntimeShape.Type.Cube:
{
var localCenter = data.shape.data.pA;
var localExtent = data.shape.data.pB;
var localCenter = Vector3.zero;
var localExtent = Vector3.one;
{
Gizmos.matrix = data.xform.matrix;
Gizmos.DrawWireCube(localCenter, localExtent * 2.0f);
Gizmos.DrawWireCube(localCenter, localExtent);
}
}
break;

Просмотреть файл

@ -161,7 +161,7 @@ namespace Unity.DemoTeam.Hair
case HairBoundary.RuntimeShape.Type.Capsule: return SdCapsule(p, data.shape.data);
case HairBoundary.RuntimeShape.Type.Sphere: return SdSphere(p, data.shape.data);
case HairBoundary.RuntimeShape.Type.Torus: return SdTorus(p, data.shape.data);
case HairBoundary.RuntimeShape.Type.Cube: return SdCube(p, Matrix4x4.Inverse(data.xform.matrix));
case HairBoundary.RuntimeShape.Type.Cube: return SdCube(p, data.shape.data, Matrix4x4.Inverse(data.xform.matrix.WithoutScale()));
}
}
break;
@ -219,14 +219,15 @@ namespace Unity.DemoTeam.Hair
return length(q) - t.y;
}
public static float SdCube(float3 p, in float4x4 invM)
public static float SdCube(in float3 p, in HairBoundary.RuntimeShape.Data cube, in float4x4 invM) => SdCube(p, cube.pA, invM);
public static float SdCube(float3 p, in float3 extent, in float4x4 invM)
{
p = mul(invM, float4(p, 1.0f)).xyz;
// see: "distance functions" by Inigo Quilez
// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float3 b = float3(0.5f, 0.5f, 0.5f);
float3 b = extent;
float3 q = abs(p) - b;
return length(max(q, 0.0f)) + min(max(q.x, max(q.y, q.z)), 0.0f);

Просмотреть файл

@ -1345,11 +1345,17 @@ namespace Unity.DemoTeam.Hair
cbuffer._BoundaryWorldMargin = volumeSettings.collisionMargin * 0.01f;
// pack boundaries
int writeIndexDiscrete = 0;
int writeIndexCapsule = writeIndexDiscrete + (int)cbuffer._BoundaryCountDiscrete;
int writeIndexSphere = writeIndexCapsule + (int)cbuffer._BoundaryCountCapsule;
int writeIndexTorus = writeIndexSphere + (int)cbuffer._BoundaryCountSphere;
int writeIndexCube = writeIndexTorus + (int)cbuffer._BoundaryCountTorus;
int firstIndexDiscrete = 0;
int firstIndexCapsule = firstIndexDiscrete + (int)cbuffer._BoundaryCountDiscrete;
int firstIndexSphere = firstIndexCapsule + (int)cbuffer._BoundaryCountCapsule;
int firstIndexTorus = firstIndexSphere + (int)cbuffer._BoundaryCountSphere;
int firstIndexCube = firstIndexTorus + (int)cbuffer._BoundaryCountTorus;
int writeIndexDiscrete = firstIndexDiscrete;
int writeIndexCapsule = firstIndexCapsule;
int writeIndexSphere = firstIndexSphere;
int writeIndexTorus = firstIndexTorus;
int writeIndexCube = firstIndexCube;
int writeCount = 0;
if (boundarySDFIndex != -1)
@ -1419,6 +1425,11 @@ namespace Unity.DemoTeam.Hair
{
ptrMatrixInv[i] = boundaryList[boundarySDFIndex].sdf.worldToUVW;
}
// world to prim for cube
else if (i < cbuffer._BoundaryCountCube + firstIndexCube && i >= firstIndexCube)
{
ptrMatrixInv[i] = Matrix4x4.Inverse(ptrMatrix[i].WithoutScale());
}
}
// update previous frame info

Просмотреть файл

@ -53,14 +53,14 @@ float SdTorus(float3 p, const float3 center, const float3 axis, const float radi
return length(q) - t.y;
}
float SdCube(float3 p, const float4x4 invM)
float SdCube(float3 p, const float3 extent, const float4x4 invM)
{
p = mul(invM, float4(p, 1.0)).xyz;
// see: "distance functions" by Inigo Quilez
// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
const float3 b = float3(0.5, 0.5, 0.5);
const float3 b = extent;
const float3 q = abs(p) - b;
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
@ -81,6 +81,11 @@ float SdTorus(const float3 p, const BoundaryShape torus)
return SdTorus(p, torus.pA, torus.pB, torus.tA, torus.tB);
}
float SdCube(const float3 p, const BoundaryShape cube, const float4x4 invM)
{
return SdCube(p, cube.pA, invM);
}
//------------------
// boundary queries
@ -113,7 +118,7 @@ float BoundaryDistance(const float3 p)
for (j += _BoundaryCountCube; i != j; i++)
{
d = min(d, SdCube(p, _BoundaryMatrixInv[i]));
d = min(d, SdCube(p, _BoundaryShape[i], _BoundaryMatrixInv[i]));
}
return d;
@ -152,7 +157,7 @@ uint BoundarySelect(const float3 p, const float d)
for (j += _BoundaryCountCube; i != j; i++)
{
if (d == SdCube(p, _BoundaryMatrixInv[i]))
if (d == SdCube(p, _BoundaryShape[i], _BoundaryMatrixInv[i]))
index = i;
}

Просмотреть файл

@ -122,7 +122,7 @@ struct BoundaryShape
// capsule | centerA radius centerB __pad
// sphere | center radius __pad __pad
// torus | center radiusA axis radiusB
// cube | __pad __pad __pad __pad
// cube | extent __pad __pad __pad
float3 pA; float tA;
float3 pB; float tB;

Просмотреть файл

@ -35,6 +35,14 @@ namespace Unity.DemoTeam.Hair
}
}
public static class Matrix4x4Extensions
{
public static Matrix4x4 WithoutScale(this Matrix4x4 value)
{
return Matrix4x4.TRS(value.GetColumn(3), Quaternion.LookRotation(value.GetColumn(2), value.GetColumn(1)), Vector3.one);
}
}
public static class QuaternionExtensions
{
public static Vector4 ToVector4(this Quaternion value)