Jump to content
  • Advertisement
Sign in to follow this  
eflatmajor

Rendering disappears if camera looks along the 'up' axis

This topic is 3416 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

I'm abit new to direct3d and im having this problem with my program where if i rotate the camera to point straight down or straight up then my textures all vanish. (when im just using diffuse colours then the colours switch places) I've tried searching around for a solution and checking all my math but i cant seem to find the problem. left and right moves the camera right and left up and down zooms in and out pgup and pgdn moves the camera up and down In my program when you move the camera all the way up or down everything vanishes. I have the .cpp code below, just make any png file called wood.png in the program directory Thanks in advance edit: oh if anyone is wondering i am using this tutorial http://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B.aspx
// include the basic windows header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// define the screen resolution
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480

// global declarations
LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;    // the pointer to the vertex buffer
// texture declarations
LPDIRECT3DTEXTURE9 texture_1;


// function prototypes
void initD3D(HWND hWnd);    // sets up and initializes Direct3D
void render_frame(void);    // renders a single frame
void cleanD3D(void);    // closes Direct3D and releases memory
void init_graphics(void);    // 3D declarations

struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR; FLOAT U, V;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam);

// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    // the handle for the window, filled by a function
    HWND hWnd;
    // this struct holds information for the window class
    WNDCLASSEX wc;

    // clear out the window class for use
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // fill in the struct with the needed information
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "WindowClass1";

    // register the window class
    RegisterClassEx(&wc);

    // create the window and use the result as the handle
    hWnd = CreateWindowEx(NULL,
                          "WindowClass1",    // name of the window class
                          "Our First Windowed Program",   // title of the window
                          WS_EX_TOPMOST | WS_POPUP,    // fullscreen values    // window style
                          0,0,    // x-position of the window    // y-position of the window
                          SCREEN_WIDTH, SCREEN_HEIGHT,    // set window to new resolution // width of the window
                          NULL,    // we have no parent window, NULL
                          NULL,    // we aren't using menus, NULL
                          hInstance,    // application handle
                          NULL);    // used with multiple windows, NULL

    // display the window on the screen
    ShowWindow(hWnd, nCmdShow);

    // set up and initialize Direct3D
    initD3D(hWnd);

    // enter the main loop:

    // this struct holds Windows event messages
    MSG msg;

	// Enter the infinite message loop
	while(TRUE)
	{
		// Check to see if any messages are waiting in the queue
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			// Translate the message and dispatch it to WindowProc()
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		// If the message is WM_QUIT, exit the while loop
		if(msg.message == WM_QUIT)
			break;

		init_graphics();
		render_frame();
		// check the 'escape' key
		if(KEY_DOWN(VK_ESCAPE))
		{
			PostMessage(hWnd, WM_DESTROY, 0, 0); 
		}
		// Run game code here
		// ...
		// ...
	}
	cleanD3D();
    // return this part of the WM_QUIT message to Windows
    return msg.wParam;
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // sort through and find what code to run for the message given
    switch(message)
    {
        // this message is read when the window is closed
        case WM_DESTROY:
            {
                // close the application entirely
                PostQuitMessage(0);
                return 0;
            } break;
    }

    // Handle any messages the switch statement didn't
    return DefWindowProc (hWnd, message, wParam, lParam);
} 
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface

    D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information

    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
    d3dpp.Windowed = true;    // program windowed, not fullscreen
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
    d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit
    d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer
    d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the buffer
    d3dpp.EnableAutoDepthStencil = TRUE;    // automatically run the z-buffer for us
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;    // 16-bit pixel format for the z-buffer

    // create a device class using this information and information from the d3dpp stuct
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);
	init_graphics();    // call the function to initialize the triangle
	d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
	d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW );//draw one side //D3DCULL_CCW draws none
	d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);    // turn on the z-buffer
}

// this is the function used to render a single frame
void render_frame(void)
{
    // clear the window to a deep blue
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
	d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    d3ddev->BeginScene();    // begins the 3D scene

    // do 3D rendering on the back buffer here

	// select which vertex format we are using
    d3ddev->SetFVF(CUSTOMFVF);
	// SET UP THE PIPELINE
	static float distance = 10.0f;
	static float horiangle = 0.0f;
	static float vertangle = 90.0f;
	static float xpos = 0.0f;
	static float zpos = 0.0f;
	static float ypos = 0.0f;
	static float rotationx = 0.0f;
	static float rotationy = 0.0f;
	static float rotationz = 0.0f;
	if(KEY_DOWN(VK_UP) && distance >= 7.0f)
	{
		distance -=  0.5f;
	}
	if(KEY_DOWN(VK_DOWN))
	{
		distance += 0.5f;
	}
	if(KEY_DOWN(VK_RIGHT))
	{
		horiangle += 4.0f;
	}
	if(KEY_DOWN(VK_LEFT))
	{
		horiangle -= 4.0f;
	}
	if(KEY_DOWN(VK_PRIOR) && vertangle > 0)
	{
		vertangle -=3.0f;
	}
	if(KEY_DOWN(VK_NEXT) && vertangle < 180)
	{
		vertangle +=3.0f;
	}	

	xpos = distance * sin(D3DXToRadian(horiangle)) * sin(D3DXToRadian(vertangle));
	ypos = distance * cos(D3DXToRadian(vertangle)) ;
	zpos = distance * cos(D3DXToRadian(horiangle)) * sin(D3DXToRadian(vertangle));

    // tell Direct3D about our matrix

    D3DXMATRIX matView;    // the view transform matrix

    D3DXMatrixLookAtLH(	&matView,
						&D3DXVECTOR3 (xpos, ypos, zpos),    // the camera position
						&D3DXVECTOR3 (0.0f, 0.0f, 0.0f),    // the look-at position
						&D3DXVECTOR3 (0.0f, 1.0f, 0.0f));    // the up direction

    d3ddev->SetTransform(D3DTS_VIEW, &matView);    // set the view transform to matView

    D3DXMATRIX matProjection;     // the projection transform matrix

    D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),    // the horizontal field of view
                               (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
                               1.0f,    // the near view-plane
                               1000.0f);    // the far view-plane

    d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);       // set the projection

    // select the vertex buffer to display
    // select the vertex buffer to display
    d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));

	D3DXMATRIX matRotateX;// a matrix to store the translation

	D3DXMatrixRotationX(&matRotateX, D3DXToRadian(rotationx));
	d3ddev->SetTransform(D3DTS_WORLD, &matRotateX);

    // build MULTIPLE matrices to translate the model and one to rotate
	// the front side
    // tell Direct3D about each world transform, and then draw another triangle

	d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
    // set the texture
    d3ddev->SetTexture(0, texture_1);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);
	d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2);
	texture_1->Release();
	v_buffer->Release();    // close and release the vertex buffer
    // copy the vertex buffer to the back buffer

    d3ddev->EndScene();    // ends the 3D scene
    d3ddev->Present(NULL, NULL, NULL, NULL);    // displays the created frame
}

// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
	v_buffer->Release();    // close and release the vertex buffer
	texture_1->Release();    // close and release the texture
    d3ddev->Release();    // close and release the 3D device
	d3d->Release();// close and release Direct3D
}

// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
	// load the texture we will use
    D3DXCreateTextureFromFile(d3ddev,
                              "wood.png",
                              &texture_1);
    // create the vertices using the CUSTOMVERTEX struct
    CUSTOMVERTEX vertices[] =
    {
		
    // side 1
    { -3.0f, 3.0f, -3.0f, 0xffffffff,1 ,0 ,},
    { 3.0f, 3.0f, -3.0f, 0xffffffff,0 ,0 ,},
    { -3.0f, -3.0f, -3.0f, 0xffffffff,1 ,1 ,},
    { 3.0f, -3.0f, -3.0f, 0xffffffff,0 ,1 ,},

    // side 2
    { -3.0f, 3.0f, 3.0f, 0xffffffff ,1 ,0 ,},
    { -3.0f, -3.0f, 3.0f, 0xffffffff ,0 ,0 ,},
    { 3.0f, 3.0f, 3.0f, 0xffffffff ,1 ,1 ,},
    { 3.0f, -3.0f, 3.0f, 0xffffffff ,0 ,1 ,},

    // side 3
    { -3.0f, 3.0f, 3.0f, 0xffffffff ,1 ,0 ,},
    { 3.0f, 3.0f, 3.0f, 0xffffffff ,0 ,0 ,},
    { -3.0f, 3.0f, -3.0f, 0xffffffff ,1 ,1 ,},
    { 3.0f, 3.0f, -3.0f, 0xffffffff ,0 ,1 ,},

    // side 4
    { -3.0f, -3.0f, 3.0f, 0xffffffff ,1 ,0 ,},
    { -3.0f, -3.0f, -3.0f, 0xffffffff ,0 ,0 ,},
    { 3.0f, -3.0f, 3.0f, 0xffffffff ,1 ,1 ,},
    { 3.0f, -3.0f, -3.0f, 0xffffffff ,0 ,1 ,},

    // side 5
    { 3.0f, 3.0f, -3.0f, 0xffffffff ,1 ,0 ,},
    { 3.0f, 3.0f, 3.0f, 0xffffffff ,0 ,0 ,},
    { 3.0f, -3.0f, -3.0f, 0xffffffff ,1 , 1 ,},
    { 3.0f, -3.0f, 3.0f, 0xffffffff ,0 , 1 ,},

    // side 6
    { -3.0f, 3.0f, -3.0f, 0xffffffff ,1 ,0 ,},
    { -3.0f, -3.0f, -3.0f, 0xffffffff ,0 ,0 ,},
    { -3.0f, 3.0f, 3.0f, 0xffffffff ,1 ,1 ,},
    { -3.0f, -3.0f, 3.0f, 0xffffffff ,0 , 1 ,},
    };

    // create a vertex buffer interface called v_buffer
    d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX),
                               0,
                               CUSTOMFVF,
                               D3DPOOL_MANAGED,
                               &v_buffer,
                               NULL);

	VOID* pVoid;    // a void pointer
	
	// lock v_buffer and load the vertices into it
	v_buffer->Lock(0, 0, (void**)&pVoid, 0);
	memcpy(pVoid, vertices, sizeof(vertices));
	v_buffer->Unlock();
}



[Edited by - jollyjeffers on May 16, 2009 9:51:27 AM]

Share this post


Link to post
Share on other sites
Advertisement
Welcome to the GDNet forums [smile]

May I request that you choose more descriptive thread titles than "Help please." A good subject line will get you the attention you need in order to get a swift response as many people will skip over threads with poor descriptions. Thanks.


Anyway, your problem.

I'm pretty sure it'll be due to your specifying the 'up' vector in D3DXMatrixLookAtLH() as being (0,1,0). When you rotate your view to look +/- along the same axis then, quite simply, the mathematics do not work out - the look-at and up vectors should define a coordinate space along with an implicit 3rd vector defined from the two you specify. This basically collapses when the two vectors you provide are the same (iirc the cross product will tend towards a zero-length vector).

Basically you will need to rotate your 'up' vector along with your look-at vector so that they remain perpendicular to each other and never actually meet. You may also wish to read up on 'gimbal lock' as another problem you'll have to watch out for.


hth
Jack

Share this post


Link to post
Share on other sites
Quote:
I'm pretty sure it'll be due to your specifying the 'up' vector in D3DXMatrixLookAtLH() as being (0,1,0).

I second. Try to calculate a up vector rather than using a static one.



Try this to compute your view matrix:
D3DXMATRIX matView;    // the view transform matrix

D3DXVECTOR3 CamPos(xpos, ypos, zpos);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 Right(1.0f, 0.0f, 0.0f);
D3DXVECTOR3 ViewVec = LookAt - CamPos;
D3DXVECTOR3 Up;

D3DXVec3Cross(&Up, &Right, &ViewVec);
D3DXVec3Normalize(&Up, &Up);

D3DXMatrixLookAtLH(&matView,
&CamPos, // the camera position
&LookAt, // the look-at position
&Up); // the up direction

d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView

This uses a static right vector to compute a up vector by taking the cross product of your view direction and the right vector. But note, that this will no longer work if you change your camera code to enable panning. Then you will have to use a variable right vector that you compute from your camera orientation.

Also, from your code I can see that you are loading and releasing your texture every frame. This is terribly slow and inefficient and you should rather load it once at the program start, keep it during program execution and release it at the end of the program.

Edit: Changed the code to make it more understandable.

Share this post


Link to post
Share on other sites
Thanks for the help, i thought I might have to alter the up axis but found the math of changing the way axis face abit confusing. I couldnt really think of a good way to phrase it when i wrote the title (which was also part of the reason i found trouble searching for the problem online)

And I added the part that clears textures during every render because when I didnt the program would run and eventually get slower. I checked my memory usage in task manager while i ran it and noticed that as the program ran it continually accumulated more and more memory until it slowed eveything down. Please tell me if you know why that is.

Share this post


Link to post
Share on other sites
You are loading the texture every frame from your hard drive when you call CreateTexture() and override the pointer that points to the texture you created the previous frame (texture_1). This is called am memory leak since your program hasn't any means anymore to free the memory of the texture from the last frame and this memory is lost. So your use of memory is increasing during runtime.

But when you release the texture every frame this doesn't happen since you freed the memory your pointer was pointing to before you overwrite it again. Therefore your program doesn't leak memory any more. But loading your texture every frame is, like I already said, very unefficient and slow.

So try instead to remove the CreateTexture() and the release() call from your rendering function and load the texture at program start (i.e. before your main loop starts), keep the pointer and pass it to your render function every frame and release it when your program ends (after your mainloop).
Basically your init_graphics() function is supposed to be called only ONCE to create your texture and vertex buffer and you should release them also only once after your main loop.

If anything is still unclear, feel free to post here again, I will try to elaborate.

And BTW this is exactly the kind of problem many people encounter who learn from directxtutorial.com. You might be better off buying a good DirectX book that will teach you right.

Share this post


Link to post
Share on other sites
DirectX is based around COM, and all its resource objects inherit from IUnknown. Therefore all D3D Resource objects are reference counted. When you pass your null texture pointer into CreateTexture, D3D "new's" a texture object, and assigns the address to the pointer you passed in. It also increments the reference count by 1. (Remember all resource objects derive from the common IUnknown interface)

From there on it is your responsibility to use your resource and then when you have finished with it you need to call Release(), which will decrement the ref count and effectivily delete the memory if the ref count is 0. If you don't release it, it will never get cleaned up....

e.g

// DirectX // (Whats happening)
Foo* obj = 0;
CreateFoo(&obj); //obj = new Foo(); obj->refCount++;
obj->Release(); //obj->refCount--; if(obj->refCount == 0) delete obj;




If you look at the C++ equivelent of whats happening in the code above, it should be preety clear on why you was leaking memory before, if not then I recommend you look over some C++ books in regards to mem managament.

Its a good idea to run DX in debug mode because it can detect any memory leaks. To do this go to your dx control panel and select the debug mode.

Share this post


Link to post
Share on other sites
Ok I think i get the perpindicular thing now but i want to be able to control the up vector of the camera using shift + left or shift + right and i cant quite figure out the math behind it. Here's an attempt.


static float distance = 10.0f;
static float horiangle = 0.0f;
static float vertangle = 90.0f;
static float camrightangle = 0.0f;
static float xpos = 0.0f;
static float zpos = 0.0f;
static float ypos = 0.0f;
static float rotationx = 0.0f;
static float rotationy = 0.0f;
static float rotationz = 0.0f;
static float xright = 1.0f;
static float yright = 0.0f;
static float zright = 0.0f;

if(KEY_DOWN(VK_UP) && distance >= 7.0f)
{
distance -= 0.5f;
}
if(KEY_DOWN(VK_DOWN))
{
distance += 0.5f;
}
if(KEY_DOWN(VK_RIGHT) && KEY_UP(VK_SHIFT))
{
horiangle += 4.0f;
}
if(KEY_DOWN(VK_LEFT) && KEY_UP(VK_SHIFT))
{
horiangle -= 4.0f;
}
if(KEY_DOWN(VK_PRIOR) && vertangle > 0)
{
vertangle -=3.0f;
}
if(KEY_DOWN(VK_NEXT) && vertangle < 180)
{
vertangle +=3.0f;
}
if(KEY_DOWN(VK_RIGHT) && KEY_DOWN(VK_SHIFT))
{
camrightangle += 4.0f;
}
if(KEY_DOWN(VK_LEFT) && KEY_DOWN(VK_SHIFT))
{
camrightangle -= 4.0f;
}

xpos = distance * sin(D3DXToRadian(horiangle)) * sin(D3DXToRadian(vertangle));
ypos = distance * cos(D3DXToRadian(vertangle)) ;
zpos = distance * cos(D3DXToRadian(horiangle)) * sin(D3DXToRadian(vertangle));


xright = xpos + distance * sin(D3DXToRadian(camrightangle)) * sin(D3DXToRadian(horiangle));
yright = ypos + distance * cos(D3DXToRadian(vertangle)) ;
zright = zpos + distance * cos(D3DXToRadian(camrightangle)) * sin(D3DXToRadian(horiangle));


D3DXMATRIX matView; // the view transform matrix

D3DXVECTOR3 CamPos(xpos, ypos, zpos);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 Right(xright, yright, zright);
D3DXVECTOR3 ViewVec = LookAt - CamPos;
D3DXVECTOR3 Up;

D3DXVec3Cross(&Up, &Right, &ViewVec);
D3DXVec3Normalize(&Up, &Up);

D3DXMatrixLookAtLH(&matView,
&CamPos, // the camera position
&LookAt, // the look-at position
&Up); // the up direction






Im thinking it would be something along the lines of a slanted circle perpindicular to th camera lookat vector with the 'right' placed somewhere on this circle but i cant get my head around the parametrics.

Share this post


Link to post
Share on other sites
	static float distance = 10.0f;
static float horiangle = 0.0f;
static float vertangle = 0.0f;
static float camrightangle = 0.0f;
static float xpos = 0.0f;
static float zpos = 0.0f;
static float ypos = 0.0f;
static float rotationx = 0.0f;
static float rotationy = 0.0f;
static float rotationz = 0.0f;
static float xright = 1.0f;
static float yright = 0.0f;
static float zright = 0.0f;

if(KEY_DOWN(VK_UP) && distance >= 7.0f)
{
distance -= 0.5f;
}
if(KEY_DOWN(VK_DOWN))
{
distance += 0.5f;
}
if(KEY_DOWN(VK_RIGHT) && KEY_UP(VK_SHIFT))
{
horiangle += 4.0f;
}
if(KEY_DOWN(VK_LEFT) && KEY_UP(VK_SHIFT))
{
horiangle -= 4.0f;
}
if(KEY_DOWN(VK_PRIOR) && vertangle > -90)
{
vertangle -=3.0f;
}
if(KEY_DOWN(VK_NEXT) && vertangle < 90)
{
vertangle +=3.0f;
}
if(KEY_DOWN(VK_RIGHT) && KEY_DOWN(VK_SHIFT))
{
camrightangle += 4.0f;
}
if(KEY_DOWN(VK_LEFT) && KEY_DOWN(VK_SHIFT))
{
camrightangle -= 4.0f;
}

xpos = distance * sin(D3DXToRadian(horiangle)) * cos(D3DXToRadian(vertangle));
ypos = distance * sin(D3DXToRadian(vertangle)) ;
zpos = distance * cos(D3DXToRadian(horiangle)) * cos(D3DXToRadian(vertangle));

xright = sin(D3DXToRadian(horiangle-90));
yright = 0.0f;
zright = cos(D3DXToRadian(horiangle-90));


D3DXMATRIX matView; // the view transform matrix

D3DXVECTOR3 CamPos(xpos, ypos, zpos);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 Right(xright, yright, zright);
D3DXVECTOR3 ViewVec = LookAt - CamPos;
D3DXVECTOR3 Up;

D3DXVec3Cross(&Up, &Right, &ViewVec);
D3DXVec3Normalize(&Up, &Up);

D3DXMatrixLookAtLH(&matView,
&CamPos, // the camera position
&LookAt, // the look-at position
&Up); // the up direction

D3DXMATRIX matRoll;
D3DXMatrixRotationZ(&matRoll, D3DXToRadian(camrightangle));
matView *= matRoll;




This should work.
But first I'll try to explaining it (I'm not so good at explaining complicated stuff in english, but I'll give it a try :P). Its pretty important, that you understand what this does.

You computed your 'right' vector like this.
xright = xpos + distance * sin(D3DXToRadian(camrightangle)) * sin(D3DXToRadian(horiangle));
yright = ypos + distance * cos(D3DXToRadian(vertangle)) ;
zright = zpos + distance * cos(D3DXToRadian(camrightangle)) * sin(D3DXToRadian(horiangle));

This is nonsense since your 'right', 'up' and your cameras view direction should build a relative coordinate system that defines the camera space that your hole scene ist transformed into during rendering. So they should have the lenght 1 and be perpendicular (at least in this case since you don't want to scale or stretch the hole scene). You computed a vector from the origin to a point somewhere near the camera, rather than a vector representing the new coordinate spaces' x vector after transformation.

I also didn't directly rotate the right and up vectors by camrightangle to create the roll effect you wanted, but rather ignored roll and set the camera only up to face the box and applied a rotation around the z-axis after camera transformation, since this is a lot easier to do.
Like this:
	D3DXMATRIX matRoll;
D3DXMatrixRotationZ(&matRoll, D3DXToRadian(camrightangle));
matView *= matRoll;

I simply created a rotation matrix that will rotate the hole scene around the z-axis (using D3DXMatrixRotationZ())and multiplied it to the camera matrix.
This way the hole scene will be first transformed to camera space and then rotated around the z-axis (which is you cameras viewing direction in camera space).

I don't think I made things cristal clear, but just ask if you have problems with this. Also it might help you to understand if you read up a bit about linear transformations and matrices in general and about the DirectX transformation pipeline.
MSDN - Transformations

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!