0

I have been hardly coding on a Direct3D9 based game. Everything went excellent util I hit a big problem. I created a class that wraps the process of loading a mesh from a .x file. I successfully loaded a cube with only one face visible. In theory, that face should look like a square but it is actually rendered as a rectangle. I am quite sure that there is something wrong with the D3DPRESENT_PARAMETERS structure. Down bellow are only the most important lines of my application's initialization.

First part to be created is the focus window:

HWND hWnd = CreateWindowEx(0UL, L"NewFrontiers3DWindowClass", Title.c_str(), WS_POPUP | WS_EX_TOPMOST, 0, 0, 1280, 1024, nullptr, (HMENU)false, hInstance, nullptr);

Then I fill out the D3DPRESENT_PARAMETERS structure.

D3DDISPLAYMODE D3DMM;
SecureZeroMemory(&D3DMM, sizeof(D3DDISPLAYMODE));
if(FAILED(hr = Direct3D9->GetAdapterDisplayMode(Adapter, &D3DMM)))
{
    // Error is processed here
}

PresP.BackBufferWidth = D3DMM.Width;
PresP.BackBufferHeight = D3DMM.Height;
PresP.BackBufferFormat = BackBufferFormat;
PresP.BackBufferCount = 1U;
PresP.MultiSampleType = D3DMULTISAMPLE_NONE;
PresP.MultiSampleQuality = 0UL;
PresP.SwapEffect = D3DSWAPEFFECT_DISCARD;
PresP.hDeviceWindow = hWnd;
PresP.Windowed = false;
PresP.EnableAutoDepthStencil = EnableAutoDepthStencil;
PresP.AutoDepthStencilFormat = AutoDepthStencilFormat;
PresP.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
PresP.FullScreen_RefreshRateInHz = D3DMM.RefreshRate;
PresP.PresentationInterval = PresentationInterval;

Then the Direct3D9 device is created, followed by the SetRenderState functions.

Next, the viewport is assigned.

D3DVIEWPORT9 D3D9Viewport;
SecureZeroMemory(&D3D9Viewport, sizeof(D3DVIEWPORT9));
    D3D9Viewport.X = 0UL;
    D3D9Viewport.Y = 0UL;
    D3D9Viewport.Width = (DWORD)D3DMM.Width;
    D3D9Viewport.Height = (DWORD)D3DMM.Height;
    D3D9Viewport.MinZ = 0.0f;
    D3D9Viewport.MaxZ = 1.0f;
if(FAILED(Direct3D9Device->SetViewport(&D3D9Viewport)))
{
    // Error is processed here
}

After this initialization, I globally declare some parameters that will be used later.

D3DXVECTOR3 EyePt(0.0f, 0.0f, -5.0f), Up(0.0f, 1.0f, 0.0f), LookAt(0.0f, 0.0f, 0.0f);
D3DXMATRIX View, Proj, World;

The update function looks like this:

Mesh.Render(Direct3D9Device);

D3DXMatrixLookAtLH(&View, &EyePt, &LookAt, &Up);
Direct3D9Device->SetTransform(D3DTS_VIEW, &View);

D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, 1.0f, 1.0f, 1000.f);
Direct3D9Device->SetTransform(D3DTS_PROJECTION, &Proj);

D3DXMatrixTranslation(&World, 0.0f, 0.0f, 0.0f);
Direct3D9Device->SetTransform(D3DTS_WORLD, &World);

The device is not a null pointer.

I recently realized that there is no difference between declaring and setting up a view port and not doing so.

If there is anybody who can point me to the right answer, please help me solve this annoying problem.

featherless biped
  • 163
  • 1
  • 5
  • 16
  • If the cube isn't exactly in the middle of the view its front side won't appear to be square because of the perspective projection. Otherwise your problem likely with your transformation matrices. – Ross Ridge Aug 22 '14 at 19:18
  • The cube is positioned right in the center of the scene. More on that, I did not use any transformation matrices and I also created a viewport. Does this matter? Am I doing or have I done something wrong? – featherless biped Aug 23 '14 at 08:53

2 Answers2

0

I think your problem not in D3DPP parameters but in your projective matrix. If you use D3DXMatrixPerspectiveFovLH, check aspect ratio to be 1280 / 1024 = 1.3333f

Dean
  • 86
  • 4
0

If you don't set any transformation matrices, so the identity transformation is applied to your mesh, then face of the cube will be stretched to the same shape of the viewport. If your viewport isn't square (eg. it's the same size as the screen) then your cube's face also won't be square.

You can use a square viewport to workaround this problem, but that will limit your rendering to just that square on the screen. If you want to render to the entire screen you'll need to set a suitable projection matrix. You can calculate a normal perspective perspective matrix using D3DXMatrixPerspectiveFovLH. If you want an orthogonal perspective, where everything is the same size regardless of the distance from the camera, then use D3DXMatrixOrthoLH to calculate the perspective matrix. Note that if you use your viewport's width and height with the later function it will shrink your cube. A unit size cube will be rendered as a single pixel on the screen. You can either use a world or view transform to scale it up again, or use something like width/height and 1 as your width and height parameters to D3DXMatrixOrthoLH.

If you go with D3DXMatrixPerspectiveFovLH then you want something like this:

D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, (double) D3DMM.Width / D3DMM.Height,
                           1.0f, 1000.f);
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • Thank you very much for replying. I tried using the function you mentioned above (D3DXMatrixPerspectiveFovLH) and I also used D3DXMatrixLookAtLH and D3DXMatrixTranslation. The problem is that I am not sure what is the right order to call these functions. In the update function, I call them in the next order: D3DXMatrixLookAtLH, D3DXMatrixPerspectiveFovLH, D3DXMatrixTranslation, but this doesn't help. I also use IDirect3DDevice9::SetTransform after each one. Am I doing things right? Is there something I miss? Could you suggest me a good tutorial for this? Please let me know. – featherless biped Aug 23 '14 at 17:16
  • It doesn't matter much what order you call them. The `D3DXMatrix` projection functions fill a matrix will the requested transformation, overwriting any previous vale in the matrix. After setting the transformation matrix, immediately call `SetTransform` with the appropriate argument. Regardless of what order you call `SetTransform` the transformations will be applied in the correct order when you draw the mesh. To get any further help you're going to need to post more details. Try to make a minimal complete example of the problem. – Ross Ridge Aug 23 '14 at 17:51
  • I just realized that it doesn't matter if I use the viewport. I am now quite sure that the problem comes from the update function. First I draw the mesh, then I process the transformation matrices in the order I described earlier. Should I post the update code of the matrices? – featherless biped Aug 23 '14 at 18:19
  • Post a Minimal Complete Verifiable Example: http://stackoverflow.com/help/mcve You can use `D3DXCreateBox` to create a cube mesh in your MCVE rather than loading one from a file. – Ross Ridge Aug 23 '14 at 18:43
  • There isn't much code to be posted here: after creating the device, I create the viewport with its width and height equal to the ones specified in the D3DPRESENT_PARAMETERS structure. Then I load a cube that was tested in the DirectX official samples and it works with absolutely no problems. After this, I first draw the cube, then I update the matrices. I will edit the question to post more code. Please check that out. – featherless biped Aug 23 '14 at 18:49
  • Thank you very much for helping me solve this problem. It looks like the "Aspect" parameter in D3DXMatrixPerspectiveFovLH was the problem. Now everything works with absolutely no problem. Thank you very much! – featherless biped Aug 24 '14 at 07:09