rotating cube in orthographic mode

Started by
7 comments, last by Yours3!f 12 years, 8 months ago
Hi,

I want to rotate a cube in orthographic mode. I can set up the orthographic mod using D3DXMatrixOrthoLH(...), and I can drag a full-screen quad on screen, however when I try to rotate nothing shows up on screen.
Here's the code:

D3DXMatrixOrthoLH(&mat_proj, (FLOAT)screen_width, (FLOAT)screen_height, 0.0f, 1.0f);

D3DXMATRIX mat_w;
float rotation = -45.0f;
D3DXMatrixRotationY(&mat_w, D3DXToRadian(rotation));
dx_dev->SetTransform(D3DTS_WORLD, &mat_w);

D3DXMatrixLookAtLH( &mat_view, &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, -1.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

D3DXMATRIXA16 mat_mvp = mat_world * mat_view * mat_proj;
constant_table->SetMatrix(dx_dev, "mvp", &mat_mvp);

//render full-screen quad


Best regards,
Yours3!f
Advertisement
Try rotating 0 degrees and increase until you can't see it.

Try printing out the object to world matrix.

Make sure that you are rotating around the object space Y axis and not the world space Y axis.

Remember that the matrix in HLSL is the transpose of the matrix in DirectX.
I tried what you said at 1 (or -1) I can see only a little bit of it, so I tried to increase the z-max value when I set the orthogonal projection matrix to 1000.0 and now I can see half of the full-screen quad, I guess the rest is behind the near plane, so it gets cut out.

Try printing out the object to world matrix.
[/quote]

What do you mean by that? Do you want me to post the world matrix?

Since I don't do any translation I guess I spin the quad aroung its object space y axis.

In HLSL I just do the following:

struct VS_INPUT
{
float4 position : POSITION;
float2 tex_coord : TEXCOORD0;
};

struct VS_OUTPUT
{
float4 position : POSITION;
float2 tex_coord : TEXCOORD0;
};

float4x4 mvp;

VS_OUTPUT main( in VS_INPUT input )
{
VS_OUTPUT output;

output.position = mul(input.position, mvp);
output.tex_coord = input.tex_coord;

return output;
}


I guess this doesn't change much right?
I simplified the whole app to 317 lines, here's the code:


#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <tchar.h>
#include <sstream>
#include <stdexcept>

LPDIRECT3D9 dx;
LPDIRECT3DDEVICE9 dx_dev;
D3DPRESENT_PARAMETERS dx_pp = {0};

HWND the_hwnd;
HINSTANCE the_instance;
WNDCLASSEX wc;

int screen_width = 0;
int screen_height = 0;

#define CFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
struct CV
{
CV(FLOAT xx, FLOAT yy, FLOAT zz, DWORD cc)
{
x = xx;
y = yy;
z = zz;
color = cc;
}
FLOAT x, y, z;
DWORD color;
};

LPDIRECT3DVERTEXBUFFER9 vbo = NULL;

DWORD global_time = GetTickCount();

LRESULT CALLBACK window_process(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
HRESULT init_top_tasks(int w, int h);
void shutdown_top_tasks();
void enter_main_loop();
HRESULT init_dx();
HRESULT init_vbo();
void render();
void clean_up();
BOOL build_present_parameters();
void handle_keypress(WPARAM wparam);

//enables key press handling
#ifndef D3BUG
#define D3BUG
#endif

int WINAPI _tWinMain(HINSTANCE instance, HINSTANCE, LPTSTR, int nCmdShow)
{
the_instance = instance;

HRESULT result = init_top_tasks(1024, 576);

enter_main_loop();

shutdown_top_tasks();

return result;
}

HRESULT init_top_tasks(int w, int h)
{
screen_width = w;
screen_height = h;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = window_process;
wc.hInstance = the_instance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";

RegisterClassEx(&wc);

the_hwnd = CreateWindowEx(NULL,
L"WindowClass",
L"DX",
WS_OVERLAPPEDWINDOW,
20,
20,
screen_width,
screen_height,
NULL,
NULL,
the_instance,
NULL);

ShowWindow(the_hwnd, SW_SHOW);

return init_dx();
}

HRESULT init_dx()
{
HRESULT result;

dx = Direct3DCreate9(D3D_SDK_VERSION);

//build pp
if(!build_present_parameters())
{
return -1;
}

result = dx->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
the_hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&dx_pp,
&dx_dev);
if(FAILED(result))
{
return result;
}

result = dx_dev->SetRenderState(D3DRS_LIGHTING, FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
if(FAILED(result))
{
return result;
}

result = init_vbo();
if(FAILED(result))
{
return result;
}

return result;
}

BOOL build_present_parameters()
{
ZeroMemory(&dx_pp, sizeof(dx_pp));
dx_pp.Windowed = TRUE;
dx_pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dx_pp.hDeviceWindow = the_hwnd;
dx_pp.BackBufferFormat = D3DFMT_X8R8G8B8;
dx_pp.BackBufferWidth = screen_width;
dx_pp.BackBufferHeight = screen_height;
dx_pp.EnableAutoDepthStencil = TRUE;
dx_pp.AutoDepthStencilFormat = D3DFMT_D16;

return TRUE;
}

HRESULT init_vbo()
{
HRESULT result;

CV vertices[] =
{
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255)),
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255)),
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255))
};

result = dx_dev->CreateVertexBuffer(6 * sizeof(CV), 0, CFVF, D3DPOOL_MANAGED, &vbo, NULL);
if(FAILED(result))
{
return result;
}

VOID* v;

vbo->Lock(0, 0, (void**)&v, 0);
memcpy(v, vertices, sizeof(vertices));
vbo->Unlock();
return result;
}

void render()
{
D3DXMATRIX mat_world, mat_view, mat_proj;

dx_dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);

dx_dev->BeginScene();

dx_dev->SetFVF(CFVF);

D3DXMatrixOrthoLH(&mat_proj, screen_width, screen_height, -1.0f, 1.0f);
dx_dev->SetTransform(D3DTS_PROJECTION, &mat_proj);

D3DXMatrixLookAtLH( &mat_view, &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, -1.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
dx_dev->SetTransform( D3DTS_VIEW, &mat_view );

D3DXMatrixRotationY(&mat_world, D3DXToRadian(1.0f));
dx_dev->SetTransform(D3DTS_WORLD, &mat_world);

dx_dev->SetStreamSource(0, vbo, 0, sizeof(CV));
dx_dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

dx_dev->EndScene();
dx_dev->Present(NULL, NULL, NULL, NULL);
}

void shutdown_top_tasks()
{
clean_up();
}

void clean_up()
{
vbo->Release();
dx_dev->Release();
dx->Release();
SendMessage(the_hwnd, WM_DESTROY, NULL, NULL);
}

void enter_main_loop()
{
MSG msg;
int return_value;

if(dx_dev)
{
render();
}

//the main message pump
while((return_value = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if(return_value == -1)
{
//error
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

LRESULT CALLBACK window_process(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
break;
}
#ifdef D3BUG
case WM_KEYDOWN:
{
handle_keypress(wparam);
break;
}
#endif
default:
{
if(dx_dev)
{
int current_time = GetTickCount() - global_time;
if(current_time > 33)
{
render();
global_time = GetTickCount();
}
}
break;
}
}

return DefWindowProc(hwnd, msg, wparam, lparam);
}

void handle_keypress(WPARAM wparam)
{
switch(LOWORD(wparam))
{
default:
break;
};
}
Dont use mat_world in the combined matrix u pass to the shader constant... use mat_w that u created, hehe :)
In C++, friends have access to your privates.
In ObjAsm, your members are exposed!
Oh dx9 my bad - same deal...

dx_dev->SetTransform(D3DTS_WORLD, &mat_world);[/quote]
Wrong.

The world transform is your imaginary 3d pen...
Set the world transform to the one you created, just before u draw, to rotate and translate the thing you will render.
And if you need to move somewhere else in the world, set it again, then render.
Try that :)

In C++, friends have access to your privates.
In ObjAsm, your members are exposed!

Oh dx9 my bad - same deal...

dx_dev->SetTransform(D3DTS_WORLD, &mat_world);

Wrong.

The world transform is your imaginary 3d pen...
Set the world transform to the one you created, just before u draw, to rotate and translate the thing you will render.
And if you need to move somewhere else in the world, set it again, then render.
Try that :)


[/quote]

I did exactly that...check out the example that I posted, you can see that half of the full-screen quad is getting cut out...

Dont use mat_world in the combined matrix u pass to the shader constant... use mat_w that u created, hehe :)


umm I use what I created, mat_w is in the first example, I posted the whole source where it is called mat_world
ok, I finally got it, I just had to think about the orthographic projection frustum as a cuboid which is screen_width wide, screen_height tall, and has near z plane at screen_width / -2 and a far plane at screen_width / 2. so I had to set up the projection matrix like this:

D3DXMatrixOrthoLH(&mat_proj, screen_width, screen_height, (float)screen_width / -2.0f, (float)screen_width / 2.0f);

here's the full code (rotate it with space):

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <tchar.h>
#include <sstream>
#include <stdexcept>

LPDIRECT3D9 dx;
LPDIRECT3DDEVICE9 dx_dev;
D3DPRESENT_PARAMETERS dx_pp = {0};

HWND the_hwnd;
HINSTANCE the_instance;
WNDCLASSEX wc;

int screen_width = 0;
int screen_height = 0;

#define CFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
struct CV
{
CV(FLOAT xx, FLOAT yy, FLOAT zz, DWORD cc)
{
x = xx;
y = yy;
z = zz;
color = cc;
}
FLOAT x, y, z;
DWORD color;
};

LPDIRECT3DVERTEXBUFFER9 vbo = NULL;

DWORD global_time = GetTickCount();

float rotation = 0.0f;

LRESULT CALLBACK window_process(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
HRESULT init_top_tasks(int w, int h);
void shutdown_top_tasks();
void enter_main_loop();
HRESULT init_dx();
HRESULT init_vbo();
void render();
void clean_up();
BOOL build_present_parameters();
void handle_keypress(WPARAM wparam);

//enables key press handling
#ifndef D3BUG
#define D3BUG
#endif

int WINAPI _tWinMain(HINSTANCE instance, HINSTANCE, LPTSTR, int nCmdShow)
{
the_instance = instance;

HRESULT result = init_top_tasks(1024, 576);

enter_main_loop();

shutdown_top_tasks();

return result;
}

HRESULT init_top_tasks(int w, int h)
{
screen_width = w;
screen_height = h;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = window_process;
wc.hInstance = the_instance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";

RegisterClassEx(&wc);

the_hwnd = CreateWindowEx(NULL,
L"WindowClass",
L"DX",
WS_OVERLAPPEDWINDOW,
20,
20,
screen_width,
screen_height,
NULL,
NULL,
the_instance,
NULL);

ShowWindow(the_hwnd, SW_SHOW);

return init_dx();
}

HRESULT init_dx()
{
HRESULT result;

dx = Direct3DCreate9(D3D_SDK_VERSION);

//build pp
if(!build_present_parameters())
{
return -1;
}

result = dx->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
the_hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&dx_pp,
&dx_dev);
if(FAILED(result))
{
return result;
}

result = dx_dev->SetRenderState(D3DRS_LIGHTING, FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
if(FAILED(result))
{
return result;
}
result = dx_dev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
if(FAILED(result))
{
return result;
}

result = init_vbo();
if(FAILED(result))
{
return result;
}

return result;
}

BOOL build_present_parameters()
{
ZeroMemory(&dx_pp, sizeof(dx_pp));
dx_pp.Windowed = TRUE;
dx_pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dx_pp.hDeviceWindow = the_hwnd;
dx_pp.BackBufferFormat = D3DFMT_X8R8G8B8;
dx_pp.BackBufferWidth = screen_width;
dx_pp.BackBufferHeight = screen_height;
dx_pp.EnableAutoDepthStencil = TRUE;
dx_pp.AutoDepthStencilFormat = D3DFMT_D16;

return TRUE;
}

HRESULT init_vbo()
{
HRESULT result;

CV vertices[] =
{
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255)),
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / -2.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 255)),
CV((FLOAT)screen_width / 2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255)),
CV((FLOAT)screen_width / -2.0f, (FLOAT)screen_height / 2.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255))
};

result = dx_dev->CreateVertexBuffer(6 * sizeof(CV), 0, CFVF, D3DPOOL_MANAGED, &vbo, NULL);
if(FAILED(result))
{
return result;
}

VOID* v;

vbo->Lock(0, 0, (void**)&v, 0);
memcpy(v, vertices, sizeof(vertices));
vbo->Unlock();
return result;
}

void render()
{
D3DXMATRIX mat_world, mat_view, mat_proj;

dx_dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);

dx_dev->BeginScene();

dx_dev->SetFVF(CFVF);

D3DXMatrixOrthoLH(&mat_proj, screen_width, screen_height, (float)screen_width / -2.0f, (float)screen_width / 2.0f);
dx_dev->SetTransform(D3DTS_PROJECTION, &mat_proj);

D3DXMatrixLookAtLH( &mat_view, &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, -1.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
dx_dev->SetTransform( D3DTS_VIEW, &mat_view );

D3DXMatrixRotationY(&mat_world, D3DXToRadian(rotation));
dx_dev->SetTransform(D3DTS_WORLD, &mat_world);

dx_dev->SetStreamSource(0, vbo, 0, sizeof(CV));
dx_dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

dx_dev->EndScene();
dx_dev->Present(NULL, NULL, NULL, NULL);
}

void shutdown_top_tasks()
{
clean_up();
}

void clean_up()
{
vbo->Release();
dx_dev->Release();
dx->Release();
SendMessage(the_hwnd, WM_DESTROY, NULL, NULL);
}

void enter_main_loop()
{
MSG msg;
int return_value;

if(dx_dev)
{
render();
}

//the main message pump
while((return_value = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if(return_value == -1)
{
//error
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

LRESULT CALLBACK window_process(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
break;
}
#ifdef D3BUG
case WM_KEYDOWN:
{
handle_keypress(wparam);
break;
}
#endif
default:
{
if(dx_dev)
{
int current_time = GetTickCount() - global_time;
if(current_time > 33)
{
render();
global_time = GetTickCount();
}
}
break;
}
}

return DefWindowProc(hwnd, msg, wparam, lparam);
}

void handle_keypress(WPARAM wparam)
{
switch(LOWORD(wparam))
{
case 0x20:
{
rotation += 1.0f;
}
default:
break;
};
}

This topic is closed to new replies.

Advertisement