What are the requirements for a collision to be usable as box collision? For example…
- Must it be 6 equally large sides?
- Does the box have to be straight e.g. no rotated faces?
And what happens if the box isn’t usable as a box collision? Will the Engine let me know or will it simply be converted to e.g. a convex collision?
You can read the code here, responsible for the checks:
/**
* Function for adding a box collision primitive to the supplied collision geometry based on the mesh of the box.
*
* We keep a list of triangle normals found so far. For each normal direction,
* we should have 2 distances from the origin (2 parallel box faces). If the
* mesh is a box, we should have 3 distinct normal directions, and 2 distances
* found for each. The difference between these distances should be the box
* dimensions. The 3 directions give us the key axes, and therefore the
* box transformation matrix. This shouldn't rely on any vertex-ordering on
* the triangles (normals are compared +ve & -ve). It also shouldn't matter
* about how many triangles make up each side (but it will take longer).
* We get the centre of the box from the centre of its AABB.
*/
void AddBoxGeomFromTris( const TArray<FPoly>& Tris, FKAggregateGeom* AggGeom, const TCHAR* ObjName )
{
TArray<FPlaneInfo> Planes;
for(int32 i=0; i<Tris.Num(); i++)
{
bool bFoundPlane = false;
for(int32 j=0; j<Planes.Num() && !bFoundPlane; j++)
{
// if this triangle plane is already known...
if( AreParallel( Tris[i].Normal, Planes[j].Normal ) )
{
// Always use the same normal when comparing distances, to ensure consistent sign.
float Dist = Tris[i].Vertices[0] | Planes[j].Normal;
// we only have one distance, and its not that one, add it.
if( Planes[j].DistCount == 1 && !AreEqual(Dist, Planes[j].PlaneDist[0]) )
{
Planes[j].PlaneDist[1] = Dist;
Planes[j].DistCount = 2;
}
// if we have a second distance, and its not that either, something is wrong.
else if( Planes[j].DistCount == 2 && !AreEqual(Dist, Planes[j].PlaneDist[1]) )
{
UE_LOG(LogStaticMeshEdit, Log, TEXT("AddBoxGeomFromTris (%s): Found more than 2 planes with different distances."), ObjName);
return;
}
bFoundPlane = true;
}
}
// If this triangle does not match an existing plane, add to list.
if(!bFoundPlane)
{
check( Planes.Num() < Tris.Num() );
FPlaneInfo NewPlane;
NewPlane.Normal = Tris[i].Normal;
NewPlane.DistCount = 1;
NewPlane.PlaneDist[0] = Tris[i].Vertices[0] | NewPlane.Normal;
Planes.Add(NewPlane);
}
}
// Now we have our candidate planes, see if there are any problems
// Wrong number of planes.
if(Planes.Num() != 3)
{
UE_LOG(LogStaticMeshEdit, Log, TEXT("AddBoxGeomFromTris (%s): Not very box-like (need 3 sets of planes)."), ObjName);
return;
}
// If we don't have 3 pairs, we can't carry on.
if((Planes[0].DistCount != 2) || (Planes[1].DistCount != 2) || (Planes[2].DistCount != 2))
{
UE_LOG(LogStaticMeshEdit, Log, TEXT("AddBoxGeomFromTris (%s): Incomplete set of planes (need 2 per axis)."), ObjName);
return;
}
FMatrix BoxTM = FMatrix::Identity;
BoxTM.SetAxis(0, Planes[0].Normal);
BoxTM.SetAxis(1, Planes[1].Normal);
// ensure valid TM by cross-product
FVector ZAxis = Planes[0].Normal ^ Planes[1].Normal;
if( !AreParallel(ZAxis, Planes[2].Normal) )
{
UE_LOG(LogStaticMeshEdit, Log, TEXT("AddBoxGeomFromTris (%s): Box axes are not perpendicular."), ObjName);
return;
}
BoxTM.SetAxis(2, ZAxis);
// OBB centre == AABB centre.
FBox Box(0);
for(int32 i=0; i<Tris.Num(); i++)
{
Box += Tris[i].Vertices[0];
Box += Tris[i].Vertices[1];
Box += Tris[i].Vertices[2];
}
BoxTM.SetOrigin( Box.GetCenter() );
// Allocate box in array
FKBoxElem BoxElem;
BoxElem.SetTransform( FTransform( BoxTM ) );
// distance between parallel planes is box edge lengths.
BoxElem.X = FMath::Abs(Planes[0].PlaneDist[0] - Planes[0].PlaneDist[1]);
BoxElem.Y = FMath::Abs(Planes[1].PlaneDist[0] - Planes[1].PlaneDist[1]);
BoxElem.Z = FMath::Abs(Planes[2].PlaneDist[0] - Planes[2].PlaneDist[1]);
AggGeom->BoxElems.Add(BoxElem);
}
To summarize:
- You need 3 sets of 2 planes, no more no less;
- Each plane must have an associated plane with normals pointing the same (or inversed) way (parallel normals)