Jump to content
  • Advertisement
Sign in to follow this  
prux

Camera system, rotating an object regardless the camera

This topic is 3007 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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
Advertisement
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
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
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
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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!