K.R. WEBER

Hi,

I am writing an introductory Direct3D application to familiarize myself with DirectX 9. Basically, I'm cheating, and adapting the source code from the DirectX SDK samples. Initially, I'm just displaying a few meshes, and experimenting with values for fixed function pipeline lighting, and also, using an HLSL shader to demonstrate Effects lighting and position transforms. It all works surprisingly well, given my level of sophistication, except for one thing: the meshes are displayed with the dimension in the vertical axis about a third shorter than the other two axis. I didn't even notice this until I used the sphere mesh (included with the SDK), and got what appears to be an ellipsoid.

I'm assuming that the error must be in the creation of the Direct3D Device, so I won't show you a huge bunch of what is probably irrelevant code, The problem occurs in both windowed and Full-Screen modes. Since, I am only displaying meshes, so, I haven't used a Vertex declaration, but, I suspect that the problem is my usage of FVF code (which I don't really understand), since I cloned the meshes, to add Normals and Texture coordinates. It must be something madingly simple that I have just overlooked.

I'd appreciate any suggestions, Thanks.



Re: Game Technologies: Graphics Mesh Display Not Symmetrical

Bad Habit

It sounds like a perspective problem. There are a few perspective functions to help create the projection matrix, make sure you¡¯re using the right one or adjust its values.





Re: Game Technologies: Graphics Mesh Display Not Symmetrical

K.R. WEBER

Bad Habit,

That is exactly what I thought initially. In fact, the ellipsoid can be rendered a perfect sphere by calling, D3DXMatrixScaling, and setting the vector values to compensate, then calling D3DXMatrixMultiply and setting this as IDIRECT3DDEVICE9->SetTransform (D3DTS_WORLD). However, I have textured the sphere using code that I stole from Robert Dunlop's DirectX website:

Direct3D Articles, The X-Zone, Robert Dunlop.

// This structure declaration taken from: Robert Dunlop, Spherical Texture Mapping.
typedef struct _VERTEX
{
D3DXVECTOR3 pos ;
D3DXVECTOR3 norm ;
float tu ;
float tv ;
} VERTEX, *LPVERTEX ;

// Calculate texture coordinates for SphereMesh, using the normal of esch vertex.
LPVERTEX pVertices ;
SphereMesh->LockVertexBuffer (0, (LPVOID*) &pVertices) ;

for (DWORD i = 0 ; i < SphrNumVertices ; i++)
{
pVertices->tu = asinf(pVertices->norm.x)/D3DX_PI + 0.5f ;
pVertices->tv = asinf(pVertices->norm.y)/D3DX_PI + 0.5f ;
pVertices++ ;
}
SphereMesh->UnlockVertexBuffer () ;

I'm leaving out alot of the SetRenderState calls, and the CloneMesh call. When the sphere is rendered onto the screen, (I use the Earth Image texture from the BumpEarth Sample in the DirectX9 SDK), the texture looks just like the Rendered sphere in the BumpEarth sample, except that at the extreme X coordinate (far left and far right, in the viewing perspective), the texture appearance is ballooned into a grotesque ringed convex or concave aberration of the bitmap image. And, I rotate this textured sphere, so I can see the entire surface. As I said in my original post, my application does a number of other rendering operations, and everything works fine. None of this code is anything imaginative, I just copied and pasted most of it from the SDK samples, changing values as necessary.

Here is the World, View, and Projection Matrix set-up code:

LPDIRECT3DDEVICE9 pIDirect3D9Grphcs ;

D3DXMATRIXA16 MtrxWorld ;
D3DXMATRIXA16 MtrxView ;
D3DXMATRIXA16 MtrxProj ;

D3DSURFACE_DESC DescripBckBuf ;
D3DSURFACE_DESC DescrpRendTarg ;
LPDIRECT3DSURFACE9 lpBackBuffer = NULL ;
pIDirect3D9Grphcs->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &lpBackBuffer) ;
lpBackBuffer->GetDesc (&DescripBckBuf) ;
AspectRatio = DescripBckBuf.Width / DescripBckBuf.Height ;

D3DXMatrixIdentity (&MtrxWorld) ;
D3DXMatrixRotationY (&MtrxWorld, D3DXToRadian (AngleVal)) ;
// Introduced D3DXMatrixScaling to correct ellipsoid display of sphere.
// D3DXMATRIXA16 ScaledMtrx ;
// D3DXMatrixScaling (&ScaledMtrx, 0.75f, 1.0f, 0.75f) ;
// D3DXMatrixMultiply (&MtrxWorld, &MtrxWorld, &ScaledMtrx) ;
pIDirect3D9Grphcs->SetTransform (D3DTS_WORLD, &MtrxWorld) ;
D3DXMatrixLookAtLH (&MtrxView, &D3DXVECTOR3 (0.0f, 0.0f, -6.0f),
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // Look At the origin
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)) ; // defines "up"
pIDirect3D9Grphcs->SetTransform (D3DTS_VIEW, &MtrxView) ;
D3DXMatrixPerspectiveFovLH (&MtrxProj, D3DX_PI * 0.25f, AspectRatio, 1.0f, 100.0f) ;
pIDirect3D9Grphcs->SetTransform (D3DTS_PROJECTION, &MtrxProj) ;

I call a function repeatedly using this code, and incrementing AngleVal (which is a DWORD) by one each time, and the textured (unlit) sphere rotates with the hideous texture aberration as an ellipsoid (unless I uncomment the D3DXMatrixScaling code, and then I see a sphere with the same hideous texture aberration as before).





Re: Game Technologies: Graphics Mesh Display Not Symmetrical

Bad Habit

When you calculate the aspect cast the values to float, like:

float AspctRatio = (float)DescripBckBuf.Width / (float)DescripBckBuf.Height

The width and the height values of D3DSURFACE_DESC are basically integers and when you divide these as non-floats you basically get back an integer. So instead of 3/2 = 1.5 you actually get 3/2 = 1. If Roberts code is right and you¡¯re having to scale then it seems that this might be your problem, especially if it does the same thing with other shapes.

When dealing with the world transform, scale first, then rotate XYZ, then translate.
When dealing with the view transform, translate first, then rotate ZYX, forget scaling.

Also set the perspective once, just after you¡¯ve created the device, you don¡¯t have keep setting it all the time, it¡¯s just a field of view. If you¡¯re resizing the window it¡¯s actually best to reset the device so you get a new back-buffer that matches its dimensions, this usually means recreating the rendering stuff, which is why most games won¡¯t allow you to resize the window.

// Something simple, like
IDirect3D9* D3D;
D3DPRESENT_PARAMETERS Params;
RECT ClientRect;
D3DDISPLAYMODE DisplayMode;

D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode);

If(Windowed)
{
    GetClientRect(hWnd, &ClientRect);
    Params.BackBufferWidth  = ClientRect.right;
    Params.BackBufferHeight = ClientRect.bottom;
}
else // Fullscreen
{
    Params.BackBufferWidth  = DisplayMode.Width;
    Params.BackBufferHeight = DisplayMode.Height;
}

// Create device

// Set perspective
float AspectRatio = (float)Params.BackBufferWidth / (float)Params.BackBufferHeight

// ¡­


 





Re: Game Technologies: Graphics Mesh Display Not Symmetrical

K.R. WEBER

Bad Habit,

Thanks for your advice. As it turns out, it WAS a simple perspective problem, and, to my eternal embarrassment, it was exactly as you suggested: my failure to cast the UINT to a float type before dividing and setting the aspect ratio. In fact, in several other places in my code, I had actually used the value, 1.00f as my aspect ratio. I knew it was a simple error, but there were so many possibilities, that it didn't even occur to me that I was supplying an integer as the aspect ratio. Again, thanks alot, I would eventually have gone insane, thinking it was an erroneous SetRenderState call or SetTextureStageState, or some other improbable concept.

As you probably guessed, I am just a beginner at Direct3D. Thanks again for your suggestions, I appreciate it.

My texture still has the hideous render problem, but, it's obviously my slapped together code,...I'll try other approaches until I get it. But, at least now, I know it's not the basic geometry or some fundamental DirectX Runtime misconception.