It’s pretty easy to find the geometric center of a group of points and I already have this working. But what if I want to have some of those points ‘weighted’ towards this centroid. I’m really stumped as to how to calculate this correctly.
Note! It’s important to understand I’m talking about a geometric center, not just the average position! That is to say - given a set of points, how to I find the exact geometric center while also taking a weight into consideration for each point?
I’m using the following for my camera tracker where it should find the exact geometric center of a set of objects it is following (already have this part working) but I also want to allow some objects to have more pull than others when determining this center.
/// <summary>
/// Returns the geometric center of a collection of Vector3s.
/// </summary>
/// <param name="points"></param>
/// <returns></returns>
public static Vector3 GetCentroid(List<Vector3> points)
{
Assert.IsNotNull(points);
Assert.IsTrue(points.Count > 0);
var min = points[0];
var max = min;
xMin = min.x;
yMin = min.y;
zMin = min.z;
xMax = max.x;
yMax = max.y;
zMax = max.z;
for (int i = 1; i < points.Count; i++)
{
Vector3 pos = points[i];
if (pos.x < xMin) xMin = pos.x;
if (pos.y < yMin) yMin = pos.y;
if (pos.z < zMin) zMin = pos.z;
if (pos.x > xMax) xMax = pos.x;
if (pos.y > yMax) yMax = pos.y;
if (pos.z > zMax) zMax = pos.z;
}
min = new Vector3(xMin, yMin, zMin);
max = new Vector3(xMax, yMax, zMax);
return min + ((max - min) * 0.5f);
}
Weighted average is just a sum of products over the sum of weights. Its actually still the same formula as the one used for a typical average position, its just simplified (as all the weights are 1 in the basic example).
eg:
Point A = [0,0,3], weight 5
Point B = [0,2,0], weight 10
sum of products = [0,0,3] * 5 + [0,2,0] * 10 = [0,20,15]
sum of weights = 5 + 10 = 15
weighted center = [0,20,15] / 15 = [0,1.333,1]
now if I change the weight of point A to 1 the center shifts drastically in favor of point B = [0,1.818,0.272]
Yes, but he’s not asking for an average, weighted or otherwise.
But then, @Sluggy1 , it’s not entirely clear what you are asking for. “Geometric center” doesn’t have a well-defined meaning as far as I’m aware. But it looks like you’re taking it to mean the center of the axis-aligned bounding box, which is a reasonable way to define it. (Another common way is the center of the smallest enclosing sphere, but that’s harder to compute.)
So now you want to do something similar, but weighing some points more heavily than others? Tricky! Once again it’s not clear quite what this would mean.
One way I can think to interpret it is: you treat these “more pull” objects as simply bigger than other points. So when computing your bounding box, you give them a little extra room on all sides (add Vector3.one times some weight to their pos when updating max, and subtract the same when updating min).
So now your bounding box includes all the points, but some extra space around certain objects, and then the camera positions itself at the center of that. Would that do what you need?
Yes, I agree. This issue is partly that nobody really seems to agree on what terminology to use for this kind of thing. Anyway, maybe a use-case would clear it up a bit.
I have a top-down 2D-ish game that support several players. The camera needs to be able to track all players and any additional targets so that they all remain on the screen - so yes, it’s very much a bounding volume of sorts. However, each player is treated as a point in this case rather than a bound of their own. I also have the ability for players to lock on to targets which I want the camera to track as well but with less strength than normal players, otherwise the camera will start to move too erratically to make the feature useful.
Does this seem reasonable? I’m thinking I might have to first calculate the centroid as normal, and then re-calculate it using the weights as a way of ‘extruding out’ from this centroid position toward that particular point. I could then save the result in a secondary list and use that completed list as the new input for calculating the weighted centroid.
I might suggest a different approach. The goal of the camera controller should be to keep all players, and their targets in view — not necessarily in the center! Generally you imagine a smaller box than the actual screen (say, 60% as wide and tall), and you move the camera only if the player(s) go outside of this box. But they can move around as much as they want inside the box, and the camera doesn’t move. This gives you generally more stable camera behavior.
Of course the drawback of this technique is, when you’re all moving steadily in one direction, you can’t see very far out in front of you.
Camera control is a much deeper topic than you’d think, because of things like this — there are all sorts of tricks and trade-offs to be made. You might posting in the Game Design forum for deeper discussion about it, and maybe get some useful references. (I know I’ve read a few, but I don’t have the links handy, alas.)
It does actually, that and the word Centroid (which he used as the function’s name) are well-defined terms and are synonyms to geometric mean, “center of gravity”, and average position.
if that is true then the formula I provided still applies, you just need to grab the bounds first like before and then apply the weighted calculation afterwards
@JoeStrout
To clarify a little more, the function I defined is actually used by a dummy object that places itself at the center of all tracked objects and then the camera tracks that object. So the effect is, as you suggest it should be, that the camera isn’t keeping the targets in the center but merely on-screen as best it can. But maybe you are right and I’m just over complicating it.
Boy don’t I know it!
I have a system that tracks multiple objects on all three axes and can be arbitrarily locked on any of them. Performs a smooth follow motion and look-ahead, uses dead-zones for each axis, and has to be able to smoothly tween to ‘focus’ points in the scene while still maintaining any potentially active lock on any axis as well as keep all targets in camera. Yikes.
@JoshuaMcKenzie
Coolio! I’ll give that a try tomorrow. My brain is too fried to figure this all out tonight.