Might as well keep doing these little journal updates, keeps me off the streets.
I've added in support for a [font=tahoma]Capsule [/font]shape to the physics system now and got the character controller just doing simple collide and separate with the level geometry. I've also set up ray casting support in the physics object and am currently using this to draw a line between the character and the floor.
Its a shame I can't figure out how the algorithm to ray cast using shape support functions works. Gino's paper on it is just too mathy for me and I don't understand. I would be in the same position with GJK if it wasn't for Casey's excellent talk on the algorithm, but I find Gino's whitepaper on GJK raycasting impenetrable.
Unfortunately, therefore, ray casting is done using ray-triangle intersections (ultimately calls [font=tahoma]D3DXRayIntersectTri [/font]under the hood) which means I have a mismatch and also that I currently only support ray casts against [font=tahoma]Polyhedron[/font]. My [font=tahoma]Shape [/font]has a [font=tahoma]virtual RayResult rayQuery(const Ray&, const Matrix&) const[/font] method that [font=tahoma]Capsule [/font]just returns an invalid [font=tahoma]RayResult [/font]for so its not quite right really.
Also the GJK intersection tests use a small margin value, whereas the ray casting doesn't, so there is a bit of a mismatch here. Something I'd like to address in the future, so if anyone can explain in English how you use support functions to ray test against a convex shape, I'd be very glad to listen.
[font=tahoma]Shape[/font]s have no position in my setup - they represent a shape in its own local co-ordinate space so to do anything useful with them, you have to pass a transform matrix into the relevant methods. For example:
[font=tahoma]Vec3 Shape::support(const Vec3 &dir, const Matrix &transform, float margin) const;[/font]
So, under the physics system, we have a [font=tahoma]Body [/font]that represents a shape with a position, orientation, velocity and so on, and it passes its world matrix into the methods that it calls on its polymorphic shape.
Internally the [font=tahoma]Capsule [/font]and [font=tahoma]Polyhedron [/font]can use an inverse of the incoming transform to convert the direction vector into local space too, which simplifies greatly the calculation of the support point for the [font=tahoma]Capsule[/font]. It means if you can figure out the support function in local space, you can apply it in any world space context, which is nice.
Vec3 Capsule::support(const Vec3 &normal, const Matrix &transform, float margin) const{ Vec3 n = transformNormal(normal, inverseMatrix(transform)); Vec3 v = n * (r + margin); v.y += (n.y < 0 ? -o : n.y > 0 ? o : 0); return transformCoord(v, transform);}Vec3 Polyhedron::support(const Vec3 &normal, const Matrix &transform, float margin) const{ Vec3 result(0, 0, 0); float max = -FLT_MAX; Vec3 n = transformNormal(normal, inverseMatrix(transform)); for(auto &v: vs) { Vec3 m = v + (n * margin); float dot = dotVectors(m, n); if(dot > max) { max = dot; result = m; } } return transformCoord(result, transform);}
But its a shame that I don't have ray casting using the same system. Ideally my [font=tahoma]Shape [/font]would present an interface for getting support points and nothing else, but will do for now anyway.