CiNN
CiNN

Reputation: 9870

3d model to fit in viewport

How does a 3D model handled unit wise ?
When i have a random model that i want to fit in my view port i dunno if it is too big or not, if i need to translate it to be in the middle...
I think a 3d object might have it's own origine.

Upvotes: 0

Views: 2303

Answers (3)

toymaker
toymaker

Reputation: 31

"so i tried to scale it down"

The best thing to do in this situation is not to transform your model at all! Leave it be. What you want to change is your camera.

First calculate the bounding box of your model somewhere in 3D space.

Next calculate the radius of it by taking the max( aabb.max.x-aabb.min.x, aabb.max.y-aabb.min.y, aabb.max.z-aabb.min.z ). It's crude but it gets the job done.

To center the object in the viewport place the camera at the object position. If Y is your forward axis subtract the radius from Y. If Z is the forward axis then subtract radius from it instead. Subtract a fudge factor to get you past the pesky near plane so your model doesn't clip out. I use quaternions in my engine with a nice lookat() method. So call lookat() and pass in the center of the bounding box. Voila! You're object is centered in the viewport regardless of where it is in the world.

This always places the camera axis aligned so you might want to get fancy and transform the camera into model space instead, subtract off the radius, then lookat() the center again. Then you're always looking at the back of the model. The key is always the lookat().

Here's some example code from my engine. It checks to see if we're trying to frame a chunk of static terrain, if so look down from a height, or a light or a static mesh. A visual is anything that draws in the scene and there are dozens of different types. A Visual::Instance is a copy of the visual, or where to draw it.

void EnvironmentView::frameSelected(){
  if( m_tSelection.toInstance() ){
    Visual::Instance& I = m_tSelection.toInstance().cast();
    Visual* pVisual = I.toVisual();
    if( pVisual->isa( StaticTerrain::classid )){
      toEditorCamera().toL2W().setPosition( pt3( 0, 0, 50000 ));
      toEditorCamera().lookat( pt3( 0 ));
    }else if( I.toFlags()->bIsLight ){
      Visual::LightInstance& L = static_cast<Visual::LightInstance&>( I );
      qst3& L2W = L.toL2W();
      const sphere s( L2W.toPosition(), L2W.toScale() );
      const f32 y =-(s.toCenter()+s.toRadius()).y();
      const f32 z = (s.toCenter()+s.toRadius()).y();
      qst3& camL2W = toEditorCamera().toL2W();
      camL2W.setPosition(s.toCenter()+pt3( 0, y, z ));//45 deg above
      toEditorCamera().lookat( s.toCenter() );
    }else{
      Mesh::handle hMesh = pVisual->getMesh();
      if( hMesh ){
        qst3& L2W = m_tSelection.toInstance()->toL2W();
        vec4x4 M;
        L2W.getMatrix( M );
        aabb3 b0 = hMesh->toBounds();
        b0.min = M * b0.min;
        b0.max = M * b0.max;
        aabb3 b1;
        b1 += b0.min;
        b1 += b0.max;
        const sphere s( b1.toSphere() );
        const f32 y =-(s.toCenter()+s.toRadius()*2.5f).y();
        const f32 z = (s.toCenter()+s.toRadius()*2.5f).y();
        qst3& camL2W = toEditorCamera().toL2W();
        camL2W.setPosition( L2W.toPosition()+pt3( 0, y, z ));//45 deg above
        toEditorCamera().lookat( b1.toOrigin() );
      }
    }
  }
}

Upvotes: 0

Skizz
Skizz

Reputation: 71070

You need to find a bounding volume, a shape that encloses all the object's vertices, for your object that is easier to work with than the object itself. Spheres are often used for this. Either the artist can define the sphere as part of the model information or you can work it out at run time. Calculating the optimal sphere is very hard, but you can get a good approximation using the following:

determine the min and max value of each point's x, y and z
  for each vertex
    min_x = min (min_x, vertex.x)
    max_x = max (max_x, vertex.x)
    min_y = min (min_y, vertex.y)
    max_y = max (max_y, vertex.y)
    min_z = min (min_z, vertex.z)
    max_z = max (max_z, vertex.z)

sphere centre = (max_x + min_x) / 2, (max_y + min_y) / 2, (max_z + min_z) / 2
sphere radius = distance from centre to (max_x, max_y, max_z)

Using this sphere, determine the a world position that allows the sphere to be viewed in full - simple geometry will determine this.

Upvotes: 2

schnaader
schnaader

Reputation: 49719

Sorry, your question is very unclear. I suppose you want to center a 3D model to a viewport. You can achieve this by calculating the model's bounding box. To do this, traverse all polygons and get the minimum/maximum X/Y/Z coordinates. The bounding box given by the points (min_x,min_y,min_z) and (max_x,max_y,max_z) will contain the whole model. Now you can center the model by looking at the center of this box. With some further calculations (depending on your FOV) you can also get the left/right/upper/lower borders inside your viewport.

Upvotes: 0

Related Questions