# 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 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:

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 on other sites
prux    138
not really. I dont know why you switched to "D3DTS_WORLD"

##### 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 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 instanceHWND wndHandle; // global variable to hold the window handleLPDIRECT3D9			 pD3D=NULL;				//objectLPDIRECT3DDEVICE9	 pd3dDevice=NULL;		//deviceLPD3DXMESH			 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 on other sites
prux    138
ok yes thx the infos, the D3DTS_WORLD was needed.

##### Share on other sites
Jeremy6996    120
Quote:
 Original post by Kapoefsome1 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.