So over the past week I've been scratching my head over SAT (Separating Axis Theorem). I know how it works, but can't seem to get the C# code right. There's always one face or edge that's letting my player through an obstacle.
So I wanted to know if maybe I'm taking the hard way around, and I don't need SAT for what I want to achieve.
My Game Involves:
- 3D Cubes which will sometimes be on an angle (not a multiple of 90)
- Not too many cubes (so I don't need my Collision Detection to be too inexpensive)
- OBB collisions
So what is the best option for me collision-wise? If SAT is my go to option, what would it look like in C#?
EDIT
My Sat code:
var n1 = (bb1.BCK_TOP_LFTCorner - bb1.BCK_BTM_LFTCorner).Normalized();
var n2 = (bb1.BCK_BTM_LFTCorner - bb1.BCK_BTM_RGTCorner).Normalized();
var n3 = (bb1.FRT_BTM_LFTCorner - bb1.BCK_BTM_LFTCorner).Normalized();
var n4 = (bb2.BCK_TOP_LFTCorner - bb2.BCK_BTM_LFTCorner).Normalized();
var n5 = (bb2.BCK_BTM_LFTCorner - bb2.BCK_BTM_RGTCorner).Normalized();
var n6 = (bb2.FRT_BTM_LFTCorner - bb2.BCK_BTM_LFTCorner).Normalized();
var norms = new List<Vector3>() {
new Vector3(-n1.X, n1.Y,n1.Z),
new Vector3(n2.X, -n2.Y,n2.Z),
new Vector3(n3.X, n3.Y,-n3.Z),
new Vector3(-n4.X, n4.Y,n4.Z),
new Vector3(n5.X, -n5.Y,n5.Z),
new Vector3(n6.X, n6.Y,-n6.Z),
};
norms = bb2.Normals;
float max1 = 0;
float min1 = 0;
float max2 = 0;
float min2 = 0;
for (int a = 0; a < norms.Count; ++a)
{
//Global.Min/Global.Max are simply Math.Min/Math.Max for an array of parameters
max1 = Global.Max(Vector3.Dot(bb1.Corners[0], norms[a]),
Vector3.Dot(bb1.Corners[1], norms[a]),
Vector3.Dot(bb1.Corners[2], norms[a]),
Vector3.Dot(bb1.Corners[3], norms[a]),
Vector3.Dot(bb1.Corners[4], norms[a]),
Vector3.Dot(bb1.Corners[5], norms[a]));
min1 = Global.Min(Vector3.Dot(bb1.Corners[0], norms[a]),
Vector3.Dot(bb1.Corners[1], norms[a]),
Vector3.Dot(bb1.Corners[2], norms[a]),
Vector3.Dot(bb1.Corners[3], norms[a]),
Vector3.Dot(bb1.Corners[4], norms[a]),
Vector3.Dot(bb1.Corners[5], norms[a]));
max2 = Global.Max(Vector3.Dot(bb2.Corners[0], norms[a]),
Vector3.Dot(bb2.Corners[1], norms[a]),
Vector3.Dot(bb2.Corners[2], norms[a]),
Vector3.Dot(bb2.Corners[3], norms[a]),
Vector3.Dot(bb2.Corners[4], norms[a]),
Vector3.Dot(bb2.Corners[5], norms[a]));
min2 = Global.Min(Vector3.Dot(bb2.Corners[0], norms[a]),
Vector3.Dot(bb2.Corners[1], norms[a]),
Vector3.Dot(bb2.Corners[2], norms[a]),
Vector3.Dot(bb2.Corners[3], norms[a]),
Vector3.Dot(bb2.Corners[4], norms[a]),
Vector3.Dot(bb2.Corners[5], norms[a]));
}
if (max1 < min2)
return Vector3.Zero;
// Get nearest face normal to player so that we can add it to player's velocity.
var rl = new List<Vector3>() {bb2.Front,
bb2.Back,
bb2.Top,
bb2.Bottom,
bb2.Left,
bb2.Right };
var r = rl.IndexOf(rl.OrderBy(c => c.Distance(bb1.Center)).First());
var returnval = bb2.Normals[r];
return returnval;