Advertisement

Falloff

Started by October 17, 2024 09:17 PM
76 comments, last by taby 1 week, 1 day ago

In Newtonian gravity, the isotropic emitter ensures that space is curved. This is not quite the same as what happens in general relativity. In general relativity, time is also curved. One way to try to model the curvature of time is to produce graviton overlap by using pseudorandom direction vectors. Preliminary results show that up close, gravitation becomes stronger than that predicted by Newtonian gravitation alone.

Here $$M$$ is the emitter mass.

It is important to note that the gravitational time dilation is like

$$\frac{d\tau}{dt} = \sqrt{1 - \frac{2GM}{c^2 R}},$$

and that Einstein's partial derivative of gravitational time dilation with respect to distance $$R$$ is

$$\frac{\partial}{\partial R} \left(\sqrt{1 - \frac{2GM}{c^2 R}} \right) = \frac{GM}{c^2 R^2 \sqrt{1 - \frac{2GM}{c^2 R}}}.$$

Here we obtain Newton's partial derivative, which is numerically and dimensionally correct:

$$\frac{\partial}{\partial R} \left( c^2 \sqrt{1 - \frac{2GM}{c^2 R}} \right) = \frac{GM}{R^2 \sqrt{1 - \frac{2GM}{c^2 R}}}.$$

We see that for very large distances $$R \gg (2GM/c^2)$$ that Newton's partial derivative provides Newtonian gravitation, as desired.

These matters will be the focus of a future tutorial.

So, my analytical method doesn't work as well as the numerical (integer) method, particularly up-close. This is to be expected. But I wonder, is there a better way? The current method that I'm using is:

real_type get_intersecting_line_count_real(
	const real_type n,
	const vector_3 sphere_location,
	const real_type sphere_radius)
{
	const real_type big_area =
		4 * pi
		* sphere_location.x * sphere_location.x;

	const real_type small_area =
		pi
		* sphere_radius * sphere_radius;

	const real_type ratio =
		small_area
		/ big_area;

	return n * ratio;
}
Advertisement

taby said:
But I wonder, is there a better way?

Never sure what you try to do, but if i'm right about the solid angle thing your function would be wrong.
I'm just working on the shading from a spherical light source, and this is what i got so far:

						float distance = length(light.lightPos - shadingPointPos);
						
						float attenuation = 1.f;
						if (light.lightRadius < distance)
						{
							float lightSolidAngle = asin(light.lightRadius / distance);
							float projArea = lightSolidAngle;
							float hemisphereArea = float(PI * 2);
							attenuation = projArea / hemisphereArea;
						}
						
											
																
																					

Notice i'm using a (black) unit half sphere around the shading point ( = your gravity emitter).
Math found from the internet says the area of the (blue) spherical cap from the projection of the light equals the solid angle.

So if you want to calculate how many rays starting from emitter, spreading equally in all directions, hit the receiving sphere,
then it should be:

float unitSphereArea = float(PI * 4); // you use a whole sphere
float percentageOfHittingRays = projArea / unitSphereArea; // * 100 for real percentage ofc.

However, i'm not sure.
I thought it would take 2 mins to find sphere area light formula on the net, but no - nothing. All i've found is a nice approximation:

https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/

Which gives this image:

And my analytical solution (which ignores the special case of sphere intersectiong the shading normal plane) gives this:

Which is not a big difference. So maybe my stuff is correct enough to confirm i can use the cheap approximation from the blog.
I'll leave it at this for now, but maybe it helps.

I am using an approximation. I am using a circular cross section to calculate collision count.

Here is the code that I'm trying:

real_type get_intersecting_line_count_real(
	const real_type n,
	const vector_3 sphere_location,
	const real_type sphere_radius,
	const real_type emitter_radius)
{
	const real_type big_area =
		4 * pi
		* sphere_location.x * sphere_location.x;

	const real_type small_area =
		pi
		* sphere_radius * sphere_radius;

	real_type small_area2 =	asin(sphere_radius / sphere_location.x);

	cout << small_area / small_area2 << endl;

	const real_type ratio =
		small_area
		/ big_area;

	return n * ratio;
}

OK, this works:

real_type get_intersecting_line_count_real(
	const real_type n,
	const vector_3 sphere_location,
	const real_type sphere_radius,
	const real_type emitter_radius,
	const real_type receiver_radius)
{
	const real_type big_area =
		4 * pi
		* sphere_location.x * sphere_location.x;

	const real_type small_area =
		pi
		* sphere_radius * sphere_radius;

	real_type small_solid_angle = asin(sphere_radius / sphere_location.x);

	const real_type ratio =
		small_solid_angle * receiver_radius / (4*sphere_location.x);

	const real_type ratio2 =
		small_area
		/ big_area;

	cout << ratio / ratio2 << endl;

	return n * ratio;
}

Advertisement

Thanks for all of your help JoeJ. As always, you're helping me improve my code.

Advertisement