Advertisement

How to auto-center a geometry?

Started by November 22, 2020 12:05 AM
3 comments, last by Vilem Otte 4 years, 1 month ago

I have a very simple geometry that I load, but it's very far off in the distance on my canvas. Also, if it's a plane and I rotate it, it rotates where a corner of the plane is at 0, 0, 0 so it doesn't rotate from the center of the model.

I set my camera like such, if it helps:

       camera = sceneManager->createCamera("Camera");
       camera->setPosition(Vector3(0, 5, 15));
       camera->lookAt(Vector3(0, 0, 0));
       camera->setNearClipDistance(0.2f);
       camera->setFarClipDistance(1000.0f);
       camera->setAutoAspectRatio(true);

But I'd like to know how to calculate the auto-center of a geometry?

There is a simple way how to center you geometry to F.e. center of gravity. This needs to be done right after loading before you submit geometry to the GPU.

Right after you load your 3D geometry, into let's say into a vector of float4, you can do:

... load 3D geometry ...

float4 center = float4(0.0f, 0.0f, 0.0f, 0.0f);
for (int i = 0; i < mesh.vertices.size(); i++)
{
    center += mesh.vertices[i];
}
center /= (float)mesh.vertices.size();

for (int i = 0; i < mesh.vertices.size(); i++)
{
    mesh.vertices[i] -= center;
}

... now your vertex positions are centered around center of gravity ...

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Advertisement

@Vilem Otte Thanks, this works in centering it. But I should have added.

How do you compute in auto-scaling it so it fits the screen?

@wizumwalt So - for auto scaling you will need to know some information from the camera.

What I do in such cases (default zoom in viewer for example) is calculating bounding sphere for the object (based on the center of gravity calculated previously). You technically just need max radius like:

float radius = 0.0f;
for (int i = 0; i < mesh.vertices.size(); i++)
{
	float4 v = center - mesh.vertices[i];
	float r = length(v);
	if (r > radius)
	{
	    radius = r;
	}
}

Now, the next thing is positioning it properly, you are aiming for something like this:

Where:

  • C is your camera
  • S is your center (of object)
  • r is radius of bounding sphere
  • a is your frustum angle
  • distance between S and C is what you're looking for (I'll denote it as d)

Keep in mind that the angle between your frustum edge and r is right angle. Therefore trigonometry is enough - as:

We're searching for d
This is equation to calculate.

Now, once you have your d value, you position your object at:

Where:

  • P is your resulting object position
  • Cp is camera position
  • Cf is camera forward vector
  • d is the distance we calculated above

This way you will be able to see whole object in your frustum. Beware of using proper angle (due to aspect ratio of the camera!)

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

for (int i = 0; i < mesh.vertices.size(); i++)
{
....
	// a squared_length(v) calc would save computing sqrt( ) in this loop for each v
	float r = length(v);
  
	if (r > radius)
	{
	    radius = r;
	}
}

radius = sqrt(radius); // then u could sqrt it here after the loop

Vilem Otte said:
Cf is camera forward vector

make sure Cf is normalized, before plugging it into P = …

that's it … all the best ?

This topic is closed to new replies.

Advertisement