Search code examples
directxdirectx-11direct3d

DirectX and DirectXTK translation limits


I use DirectX Toolkit to display a 3d model, following the 'Rendering the model' and my pyramid is displayed:

enter image description here

When trying to transform the object, the scaling and rotation work well but I'm not sure how to move the object (translate) around. Basically I'm looking for an algorithm that determines, given the current camera position, focus, viewport and the rendered model (which the DirectX toolkit gives me the bounding box so it's "size") the minimum and maximum values for XYZ translation so the object remains visible.

The bounding box is always the same, no matter the view port size, so how do I compare it's size against my viewport?

Please excuse my newbiness, I'm not a 3D developer, at least yet.

The "Simple Rendering" example which draws a triangle:

Matrix proj = Matrix::CreateScale( 2.f/float(backBufferWidth),
   -2.f/float(backBufferHeight), 1.f)
   * Matrix::CreateTranslation( -1.f, 1.f, 0.f );
m_effect->SetProjection(proj);

says that the normalized triangle size is [1,1,1] but here normalized values do not work.


Solution

  • TL:DR: To move your model around the world, create a matrix for the translation and set it as the world matrix with SetWorld.

    Matrix world = Matrix::CreateTranslation( 2.f, 1.f, 3.f);
    m_effect->SetWorld(world);
    
    // Also be sure you have called SetView and SetProjection for the 3D camera setup
    //covered in the 3D shapes / Rendering a model tutorial
    

    You should start with a basic review of 3D transformations, in particular the world -> view -> projection transformation pipeline.

    1. The world transformation performs the affine transformation to get the model you are rendering into it's 'world' position. (a.k.a. 'local coordinates to world coordinates transformation').

    2. The view transformation performs the transformation to get world positions into the camera's point of view (i.e. position and direction) (a.k.a. 'world coordinates to view coordinates transformation').

    3. The projection transformation performs the transformation to get the view positions into the canonical "-1 to 1" range that the actual hardware uses, including any perspective projection (a.k.a. 'view coordinates to 'clip' coordinates transformation).

    4. The hardware itself performs the final step of converting the "-1 to 1" to pixel locations in the render target based on the Direct3D SetViewport information (a.k.a. 'clip' coordinates to pixel coordinates transformation).

    This Direct3D 9 era article is a bit dated, but it covers the overall idea well.

    In the DirectX Tool Kit BasicEffect system, there are distinct methods for each of these matrices: SetWorld, SetView, and SetProjection. There is also a helper if you want to set all three at once SetMatrices.

    The simple rendering tutorial is concerned with the simplest form of rendering, 2D rendering, where you want the coordinates you provide to be in natural 'pixel coordinates'

    Matrix proj = Matrix::CreateScale( 2.f/float(backBufferWidth),
       -2.f/float(backBufferHeight), 1.f)
       * Matrix::CreateTranslation( -1.f, 1.f, 0.f );
    m_effect->SetProjection(proj);
    

    The purpose of this matrix is to basically 'undo' what the SetViewport will do so that you can think in simple pixel coordinates. It's not suitable for 3D models.

    In the 3D shapes tutorial I cover the basic camera model, but I leave the world matrix as the identity so the shape is sitting at the world origin.

    m_view = Matrix::CreateLookAt(Vector3(2.f, 2.f, 2.f),
        Vector3::Zero, Vector3::UnitY);
    m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f,
        float(backBufferWidth) / float(backBufferHeight), 0.1f, 10.f);
    

    In the Rendering a model tutorial, I also leave the world matrix as identity. I get into the basics of this in Basic game math tutorial.

    One of the nice properties of affine transformations is that you can perform them all at once by transforming by the concatenation of the individual transforms. Point p transformed by matrix W, then transformed by matrix V, then transformed by matrix P is the same as point p transformed by matrix W * V * P.