Sign in to follow this  
prux

Camera system, rotating an object regardless the camera

Recommended Posts

prux    138
hey, I know its a very basic question but I dont know how to figure out. I have a Quaternion-based camera system. I created my 3D objects, and I can move in it, rotate freely etc (like a spectator mode in an FPS) so everything is OK yet. Now I want to rotate a cube (not physically - no lock - rotate sin/cos - unlock). I know I have to do this all with VIEW matrixes. When I save the current view matrix, doesnt do anything with it, apply it, draw cube, and apply the original view matrix, nothing happens - I meant thats the correct behaviour. When I do this: D3DXMatrixRotationY( aWorldMatX, 1 ); D3DXMatrixMultiply( aWorldMat, aWorldMat, aWorldMatY ); then it brilliantly gyros around me - not around its origo. Cube is put the origo (1.5, -1.5 coords), originally not translated! Can anyone give me some formulas how to rotate this cube so that it remains where its set originall? And if I do this: D3DXMatrixRotationX( aWorldMatX, gyro ); D3DXMatrixRotationY( aWorldMatY, gyro ); D3DXMatrixRotationZ( aWorldMatZ, gyro ); D3DXMatrixMultiply( aWorldMat, aWorldMatX, aWorldMatY ); D3DXMatrixMultiply( aWorldMat, aWorldMat, aWorldMatY ); then it does gyro around me - but then it "follows" me, I cant go out of this box!

Share this post


Link to post
Share on other sites
Kapoef    115
some1 very smart told me once that the order that u multiply the matrices are important.

The general way to do it is

worldMat=scaleMat*rotationMat*translationMat;

For this case the scaleMat should be an identity matrix so u can ignore it.

thus becomes

worldMat=rotationMat*translationMat;// this will rotate around its own axes

worldMat=translationMat*rotationMat;// this will rotate around the world origin

so lets say u want to move the cube to (2,5,-8) and let it rotate around its own axis then u would do the following:


// in your render call

D3DXMATRIX worldMat,translationMat,rotationMat;

D3DXMatrixTranslation(&translationMat,2,5,-8); // saves the translation

D3DXMatrixRotationY(&,timeGetTime()/100.0f);// rotate around Y-axis


worldMat=rotationMat*translationMat;

//worldMat=translationMat*rotationMat; //this will rotate around the map origin

dev->SetTransform(D3DTS_WORLD, &worldMat);

// now draw the cube

i hope this helps

Share this post


Link to post
Share on other sites
Kapoef    115
D3DTS_WORLD tells your graphics device where to draw an object. U have to use D3DTS_VIEW and D3DTS_PROJECTION as well.

U need all 3 transforms to view an 3D scene. The view tells the device where u r looking from, the projection tells the device how to project objects in 3D space and lastly D3DTS_WORLD specifies where/how large and how the object is rotated that u r rendering.

I can give u an complete example that will rotate an object around its own axis if u like?

Share this post


Link to post
Share on other sites
Kapoef    115
try this code, i assume u r using visual studio's C++



#include <Windows.h>
#include <mmsystem.h>
#include <d3d9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <d3dx9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe.h>
#pragma warning( disable : 4996 ) // disable deprecated warning

HINSTANCE hInst; // global handle to hold the application instance
HWND wndHandle; // global variable to hold the window handle

LPDIRECT3D9 pD3D=NULL; //object
LPDIRECT3DDEVICE9 pd3dDevice=NULL; //device
LPD3DXMESH cube=NULL;

void cleanUp()
{
if(pD3D!=NULL)
pD3D->Release();
if(pd3dDevice!=NULL)
{
pd3dDevice->Release();
pd3dDevice=NULL;
}
if(cube!=NULL)
cube->Release();
}

VOID cameraStuff()
{
//////////////FOV+PROECTION///////////////////////////

D3DXMATRIX matProj,matView;

float nearClip=0.01f,farClip=17500;

D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/3.0, 4.0f/3.0f, nearClip, farClip);

pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);

//////////////FOV+PROECTION///////////////////////////

/////////////CAMERA///////////////////////////////////

D3DXVECTOR3 cameraPosition(0.0f,5.0f,-5.0f),cameraLook(0.0f,0.0f,0.0f);
D3DXMatrixLookAtLH (&matView,
&cameraPosition, //camera position
&cameraLook, //look at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); //up direction
pd3dDevice->SetTransform (D3DTS_VIEW, &matView);

}


void DrawCube1()//will rotate around its own axis (Y axis) at pos(1,1,1)
{

D3DXMATRIX world,rot,pos;

D3DXMatrixTranslation(&pos,1,1,1);
D3DXMatrixRotationY(&rot,timeGetTime()/1000.0f);

world=rot*pos;

pd3dDevice->SetTransform(D3DTS_WORLD,&world);

cube->DrawSubset(0);
}

void DrawCube2()//will rotate (Y axis) around the world origin (0,0,0) at a distance 1
{

D3DXMATRIX world,rot,pos;

D3DXMatrixTranslation(&pos,1,1,1);
D3DXMatrixRotationY(&rot,timeGetTime()/1000.0f);

world=pos*rot;

pd3dDevice->SetTransform(D3DTS_WORLD,&world);

cube->DrawSubset(0);
}

void render()
{
pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER ,D3DCOLOR_XRGB( 0,128,255 ), 1.0f, 0 );//clear to black

/*
* The camera u can now change to look at any point from any point using your code
*/

cameraStuff();//setup camera

if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{
DrawCube1();
DrawCube2();

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

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Check any available messages from the queue
switch (message)
{
case WM_DESTROY:{
cleanUp();
PostQuitMessage(0);
}break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

HRESULT init3D()
{
if(NULL==(pD3D=Direct3DCreate9( D3D_SDK_VERSION )) )
{
return false;
}

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory( &d3dpp, sizeof( d3dpp ) );

d3dpp.Windowed=TRUE;
d3dpp.hDeviceWindow = wndHandle;
d3dpp.BackBufferHeight = 768;
d3dpp.BackBufferWidth = 1024;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;//D3DFMT_UNKNOWN;
d3dpp.BackBufferCount=2;
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

//create main device
if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
wndHandle,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp,
&pd3dDevice ) ) )
{
return false;
}



pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);

pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );

pd3dDevice->SetRenderState (D3DRS_SPECULARENABLE, FALSE);

D3DXCreateBox(pd3dDevice,1.0f,1.0f,1.0f,&cube,NULL);//generate Cube

return true;
}

bool initWindow( HINSTANCE hInstance )
{
WNDCLASSEX wcex;

// Fill in the WNDCLASSEX structure. This describes how the window
// will look to the system
wcex.cbSize = sizeof(WNDCLASSEX); // the size of the structure
wcex.style = CS_HREDRAW | CS_VREDRAW; // the class style*/
wcex.lpfnWndProc = WndProc; // the window procedure callback
wcex.cbClsExtra = 0; // extra bytes to allocate for this class
wcex.cbWndExtra = 0; // extra bytes to allocate for this instance
wcex.hInstance = hInstance; // handle to the application instance
wcex.hIcon = 0; // icon to associate with the application
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);// the default cursor
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_PEN);//(HBRUSH)(COLOR_WINDOW+1); // the background color
wcex.lpszMenuName = NULL; // the resource name for the menu
wcex.lpszClassName = "Test"; // the class name being created
wcex.hIconSm = 0; // the handle to the small icon


RegisterClassEx(&wcex);

// Create the window
wndHandle = CreateWindow(
"Test",
"Test",
WS_OVERLAPPEDWINDOW | WS_EX_TOPMOST | WS_VISIBLE, /*WS_OVERLAPPEDWINDOW, //WIndowed*/ //WS_POPUP only graph window
// the window class to use
// the title bar text
// the window style
CW_USEDEFAULT, // the starting x coordinate
CW_USEDEFAULT, // the starting y coordinate
1024, // the pixel width of the window
768, // the pixel height of the window
NULL, // the parent window; NULL for desktop
NULL, // the menu for the application; NULL for
// none
hInstance, // the handle to the application instance
NULL); // no values passed to the window

// Make sure that the window handle that is created is valid
if (!wndHandle)
return false;

// Display the window on the screen
ShowWindow(wndHandle, SW_SHOW);
UpdateWindow(wndHandle);

return true;

}

INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow )
{
// Initialize the window
if(!initWindow( hInstance ) )
return false;

if(!init3D())
return false;

MSG msg;
ZeroMemory( &msg, sizeof( msg ) );
while( msg.message!=WM_QUIT )
{
// Check the message queue
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage ( &msg );
DispatchMessage ( &msg );
}
if(pd3dDevice!=NULL)
{
render();
}
}

return (int) msg.wParam;

}




I tested this so i know it works

Share this post


Link to post
Share on other sites
Jeremy6996    120
Quote:
Original post by Kapoef
some1 very smart told me once that the order that u multiply the matrices are important.


It is. The multiplication order of a matrix is ISR(O)T

Matrix Identity * Scale * Rotation * (Origin Matrix) * Translation

D3DTS_WOLRD tells D3D to set the world transformation in (I assume) the vertex-shader. In XNA we have no default shader, I'm not sure about DirectX, but you must be using one in some form or way.

Just as D3DTS_VIEW sets the view transformation. This is the orientation of your "camera" view.

D3DTS_PROJECTION sets the projection matrix which describes how everything should be rendered. I.e aspect ratio, near-plane, far-plane, etc is held here.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this