Alright so, I’m almost done with this now. Really happy with how it’s turned out, all I want to do at this stage is change the draw-order of the items so that I can get the blips to render on top of the grid lines. Not sure if that’s going to be possible without splitting the widget up though, which I’d really rather avoid. Anyway here’s the video, recommend full screen 1080 to see it working.
So I’m doing this using only three instanced meshes and inside one SMeshWidget, but to be honest I could probably have squeezed everything in with two meshes. The base compass is a mesh, drawn in a similar way to how I’ve done it above, but I’ve now got it to use the rectangle as the draw location, which prevents any strange issues with scaling or position on screen. The easiest way to do it is use the ClippingRectangle.
The trickiest part was the blips. I already have a pretty robust spatial hash system and an object manager for getting the list of objects, so that part is already there. Every Game Object with a scanner tells the object manager to ‘ping’ objects in it’s range on a timer, and the object manager determines which ones are visible or in range / on the correct team for that object.
The coolest part (IMO), is that I’ve only split the draws into either edge-arrows, or regular blips (aka in-range items). Three floats is what I need to determine colour, opacity, and either Rotation or ‘Blip Type’ (square or circle) - but these all have to be packed into the BaseAddress, so you only get a certain amount of precision (but it’s more than enough for me). The material then unpacks this data and uses it to drive the parameters.
Here’s the way the packing is done:
FORCEINLINE float PackFloats_3(const float X, const float Y, const float Z) const
{
const uint8 XInt = X * 255.0f;
const uint8 YInt = Y * 255.0f;
const uint8 ZInt = Z * 255.0f;
const uint32 PackedInt = (XInt << 16) | (YInt << 8) | ZInt;
return (float)(((double)PackedInt) / ((double)(1 << 24)));
}
And then how it’s unpacked in the material:
Blip and Arrow materials. Byte1 is used to drive a Colour LUT to determine the colour, Byte 2 is used to determine opacity, and Byte 3 is the ‘Data’ byte.
Phew… yeah so that’s what I did this weekend!