So it seems, ihat i have found the real issue now. It was my GJK implementation, which was faulty (probably due to over optimization), so I've rewrote my GJK code from scratch now, with which my Bilateral advancement implementation seems to be working now. And as bonus, my new GJK code seems to be even up to 3x faster in my stress benchmarks.
Hopefully this fact just does not deceive, that it works now, but I will see it in later testing that it actually does always work properly. Keep your fingers crossed for me that it is indeed the case now
But to answer your question anyway:
I do it more or less as in Box2D, ie
GJK-Feature-initialization:
Code: Select all
// c-style pseudo code
// Vertex-vertex
Transform VerticesA[0] and VerticesB[0] into worldspace
Axis = normalize(VerticesB[0] - VerticesA[0]);
Mode = sfmVERTICESinWORLDSPACE;
// Vertex-edge
Transform VerticesA[0] into B local space
Axis = normalize(VerticesB[1] - VerticesB[0]);
LocalPlane.Normal = normalize(cross(cross(Axis, VerticesA[0] - VerticesB[0]), Axis));
LocalPlane.Distance = -dot(Plane.Normal, VerticesB[0]);
SeparationFunctionMode = sfmLOCALSPACEofB;
// Vertex-face
Transform VerticesA[0] and VerticesA[1] into B local space
Axis = normalize(cross(VerticesB[0] - VerticesB[1], VerticesB[2] - VerticesB[1]));
LocalPlane.Normal = (dot(Plane.Normal, VerticesA[0]) < 0.0) ? -Axis : Axis;
LocalPlane.Distance = -dot(Plane.Normal, VerticesB[0]);
SeparationFunctionMode = sfmLOCALSPACEofB;
. . .
// Edge-Edge
Transform VerticesB[0] and VerticesB[1] into A local space
eA = VerticesA[1] - VerticesA[0];
eB = VerticesB[1] - VerticesB[0];
Axis = normalize(cross(eA, eB));
LocalPlane.Normal = (dot(Plane.Normal, eB - eA) < 0.0) ? -Axis : Axis;
LocalPlane.Distance = -dot(Plane.Normal, VerticesB[0]);
SeparationFunctionMode = sfmLOCALSPACEofA;
. . .
FindMinSeparation:
Code: Select all
// real copy&pasted but by hand reformatted object-pascal code, since my personal object-pascal code-formatting-style is dense
function Evaluate : single; forward;
function FindMinSeparation : single;
begin
case SeparationFunctionMode of
sfmVERTICESinWORLDSPACE : begin
WitnessPoints[0] := Shapes[0].GetLocalFeatureSupportVertex(
Shapes[0].GetLocalFeatureSupportIndex(
Vector3TermMatrixMulTransposedBasis(Axis, Transforms[0])));
WitnessPoints[1] := Shapes[1].GetLocalFeatureSupportVertex(
Shapes[1].GetLocalFeatureSupportIndex(
Vector3TermMatrixMulTransposedBasis(Vector3Neg(Axis), Transforms[1])));
end;
sfmLOCALSPACEofA : begin
WitnessPoints[1] := Shapes[1].GetLocalFeatureSupportVertex(
Shapes[1].GetLocalFeatureSupportIndex(
Vector3Neg(
Vector3TermMatrixMulTransposedBasis(
Vector3TermMatrixMulBasis(Axis, Transforms[0]), Transforms[1]))));
end;
sfmLOCALSPACEofB : begin
WitnessPoints[0] := Shapes[0].GetLocalFeatureSupportVertex(
Shapes[0].GetLocalFeatureSupportIndex(
Vector3Neg(
Vector3TermMatrixMulTransposedBasis(
Vector3TermMatrixMulBasis(Axis, Transforms[1]), Transforms[0]))));
end;
end;
result := Evaluate;
end;
Evaluate:
Code: Select all
// also again real copy&pasted but by hand reformatted object-pascal code
function Evaluate : single;
begin
case SeparationFunctionMode of
sfmVERTICESinWORLDSPACE : begin
result := Vector3Dot(Axis,
Vector3Sub(Vector3TermMatrixMul(WitnessPoints[1], Transforms[1]),
Vector3TermMatrixMul(WitnessPoints[0], Transforms[0])));
end;
sfmLOCALSPACEofA : begin
result := PlaneVectorDistance(LocalPlane,
Vector3TermMatrixMulInverted(Vector3TermMatrixMul(WitnessPoints[1],
Transforms[1]), Transforms[0]));
end;
sfmLOCALSPACEofB : begin
result := PlaneVectorDistance(LocalPlane,
Vector3TermMatrixMulInverted(Vector3TermMatrixMul(WitnessPoints[0],
Transforms[0]), Transforms[1]));
end;
else begin
result := 0.0;
Assert(false);
end;
end;
end;