private static SphereDistribution CalculateDistribution(int numChildren) { // todo: estimate good radius from number float radius = 2f; var angles = new PitchYaw[numChildren]; while (!TryCalculateDistributionForRadius(radius, angles)) { radius *= 1.1f; } return(new SphereDistribution(radius, angles)); }
private static bool TryCalculateDistributionForRadius(float radius, PitchYaw[] anglesToFill) { var numChildren = anglesToFill.Length; if (numChildren == 0) { return(true); } var middleIndex = numChildren / 2 - 1 + numChildren % 2; var currentIndex = middleIndex; var pitch = 0f; while (currentIndex < numChildren) { var horizontalCapacity = HorizontalCapacity(radius, pitch); var pitchStep = PitchStep(radius); var nextPitch = pitch + pitchStep; if (nextPitch + pitchStep / 2 > 0.66f * MathHelper.PiOver2) { return(false); } var localPitchStep = pitchStep / horizontalCapacity; var yawStep = YawStep(radius, pitch); var localBorder = Math.Min(currentIndex + horizontalCapacity, numChildren); if (currentIndex == middleIndex) { anglesToFill[currentIndex] = new PitchYaw(0, 0); currentIndex++; } for (int i = currentIndex; i < localBorder; i++) { anglesToFill[i] = new PitchYaw(anglesToFill[i - 1].Pitch + localPitchStep, anglesToFill[i - 1].Yaw + yawStep); } currentIndex = localBorder; pitch = nextPitch; } for (int i = middleIndex - 1; i >= 0; i--) { var opposite = anglesToFill[middleIndex + (middleIndex - i)]; anglesToFill[i] = new PitchYaw(-opposite.Pitch, -opposite.Yaw); } return(true); }