PDA

View Full Version : rotating camera in skybox



nick2price
11-28-2008, 10:43 AM
I have a skybox with the camera currently located in the middle. When the user presses right, i would like to get the camera to rotate right and same for left. Not too sure on the way to do this. I have started of by doing

GLvoid window_special_key(int key, int x, int y)
{
switch (key) {

case KEY_RIGHT:

glutPostRedisplay();
break;

case KEY_LEFT:

glutPostRedisplay();
break;

default:
break;
}
}

Obviously, this does nothing yet. What would be the procedure to get it to rotate? I am not sure if i am to use gluLookAt and if i do, i am not too sure what numbers i need to use. Any help would be great.

dletozeun
11-28-2008, 11:43 AM
The idea is to move to the camera position and rotate around the camera vertical axis. Say that camera position is (cx, cy, cz) and y, its vertical axis.

Before rendering the whole scene, translate of (-cx, -cy, -cz), rotate around y. In terms of Opengl calls it looks like this:

glRotatef(camera_angle, 0, y, 0);
glTranslatef(-cx, -cy, -cz);

Of course this simulates only the panning movement.

nick2price
11-28-2008, 01:16 PM
i am struggling to see what call sets up my original camera position. would it be
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);or
glViewport(0,0,width,height);

What is the original function to set up a camera position?

nick2price
11-28-2008, 01:41 PM
Sorry, i have made a slight change so that my program more resembles the example i am following, which means i have no main method but creating the window myself. So for the main class, i have changed it to


#include "stdafx.h"
#include <GL/glut.h>
#include <windows.h>
#include <stdio.h> //for file access
#include <gl\gl.h>
#include "skybox.h"
#include "glbmp.h"
#include "coursework2.h"
#include "3dsloader.h"
#include "texture.h"

//Instance variables

HDC hDC=NULL;
HGLRC hRC=NULL;
HWND hWnd=NULL;
HINSTANCE hInstance;
MSG msg;

//get and instance of the skybox
skybox aSkyBox;

long mouse_x, mouse_y, mouse_temp; //keep track of the mouse

bool keys[256];
bool active=TRUE;
bool fullscreen=FALSE;

//callback procedure
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


//Function that is used to resize the Screen
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) {

if (height<=0) { height=1; }

glViewport(0,0,width,height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

//Initalize the OpenGL engine
int InitGL(GLvoid) {

glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH); //Try GL_FLAT to see the difference
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Background colour
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST); //Enables depth testing
glDepthFunc(GL_LEQUAL); //Specifies how Depth testing is done
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Affects quality of colour and texture interpolation
glFrontFace (GL_CCW); //Specifies that the front of a face is defined
//in a Counter Clockwise manner
glCullFace(GL_BACK); //Specifies that the back of faces are not shown
//so OpenGL does not need to draw things twice
glEnable(GL_CULL_FACE); //Enables culling of faces


aSkyBox.Init(); //Initalize the Skybox
mouse_x = 0;
mouse_y = 0;
mouse_temp = -5000;

return TRUE;
}

int DrawGLScene(GLvoid) {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

//this is where stuff is drawn
aSkyBox.draw();

return TRUE;
}

GLvoid KillGLWindow(GLvoid) {

if (fullscreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}

if (hRC)
{
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC))
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL;
}

if (hDC &amp;&amp; !ReleaseDC(hWnd,hDC))
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL;
}

if (hWnd &amp;&amp; !DestroyWindow(hWnd))
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL;
}

if (!UnregisterClass("OpenGL",hInstance))
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL;
}
}


bool CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) {

GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)width;
WindowRect.top=(long)0;
WindowRect.bottom=(long)height;

fullscreen=fullscreenflag;

hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";

if (!RegisterClass(&amp;wc)) {

MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (fullscreen) {

DEVMODE dmScreenSettings;
memset(&amp;dmScreenSettings,0,sizeof(dmScreenSettings ));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWID TH|DM_PELSHEIGHT;


if (ChangeDisplaySettings(&amp;dmScreenSettings,CDS_FULLS CREEN)!=DISP_CHANGE_SUCCESSFUL) {

if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","Video Mode",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) {

fullscreen=FALSE;

} else {

MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE;

}
}
}

if (fullscreen) {

dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
ShowCursor(FALSE);

} else {

dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;

}

AdjustWindowRectEx(&amp;WindowRect, dwStyle, FALSE, dwExStyle);

if (!(hWnd=CreateWindowEx( dwExStyle,
"OpenGL",
title,
dwStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,
0, 0,
WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL,
NULL,
hInstance,
NULL))) {

KillGLWindow();
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

static PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};

if (!(hDC=GetDC(hWnd))) {

KillGLWindow();
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&amp;pfd))) {
KillGLWindow();
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if(!SetPixelFormat(hDC,PixelFormat,&amp;pfd)) {
KillGLWindow();
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if (!(hRC=wglCreateContext(hDC))) {
KillGLWindow();
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

if(!wglMakeCurrent(hDC,hRC)) {
KillGLWindow();
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
ReSizeGLScene(width, height);

if (!InitGL()) {
KillGLWindow();
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}

return TRUE;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

switch (uMsg) {

case WM_ACTIVATE: {

if (!HIWORD(wParam)) {
active=TRUE;
} else {
active=FALSE;
}

return 0;
}

case WM_SYSCOMMAND: {

switch (wParam) {

case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
}

case WM_CLOSE: {

PostQuitMessage(0);
return 0;
}

case WM_MOUSEMOVE: {

if(mouse_temp == -5000) {
mouse_y = HIWORD(lParam);
mouse_x = LOWORD(lParam);
mouse_temp = 0;

} else {

mouse_temp = HIWORD(lParam);
if(mouse_temp > mouse_y) {

aSkyBox.rot_x += (mouse_temp - mouse_y);
}
if(mouse_temp < mouse_y) {
aSkyBox.rot_x -= (mouse_y - mouse_temp);
}
mouse_y = mouse_temp;

mouse_temp = LOWORD(lParam);
if(mouse_temp > mouse_x) {
aSkyBox.rot_y += (mouse_temp - mouse_x);
}
if(mouse_temp < mouse_x) {
aSkyBox.rot_y -= (mouse_x - mouse_temp);
}
mouse_x = mouse_temp;
}

return 0;
}

case WM_KEYDOWN: {

keys[wParam] = TRUE;
return 0;
}

case WM_KEYUP: {

keys[wParam] = FALSE;
return 0;
}

case WM_SIZE: {

ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
return 0;
}
}

return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

BOOL done=FALSE;

fullscreen=FALSE;

if (!CreateGLWindow("OpenGL Window",800,600,16,fullscreen)) {

return 0;
}

while(!done) {

if (PeekMessage(&amp;msg,NULL,0,0,PM_REMOVE)) {

if (msg.message==WM_QUIT) {
done=TRUE;
} else {
TranslateMessage(&amp;msg);
DispatchMessage(&amp;msg);
}
} else {

if (active) {

if (keys[VK_ESCAPE]) {
done=TRUE;
} else {
DrawGLScene();
SwapBuffers(hDC);
}
}

if (keys[VK_F1]) {

keys[VK_F1]=FALSE;
KillGLWindow();
fullscreen=!fullscreen;

if (!CreateGLWindow("OpenGL Window",800,600,16,fullscreen)) {
return 0;
}
}

//Allow user to change the skybox
if(keys['1']) {
keys['1']=FALSE;
aSkyBox.text_offset = 0;
}

if(keys['2']) {
keys['2']=FALSE;
aSkyBox.text_offset = 6;
}

if(keys['3']) {
keys['3']=FALSE;
aSkyBox.text_offset = 12;
}

if(keys['4']) {
keys['4']=FALSE;
aSkyBox.text_offset = 18;
}
}

}

KillGLWindow();
return (msg.wParam);
}


I am getting an error saying


1>Linking...
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>F:\Graphics, C++\skybox\Debug\skybox.exe : fatal error LNK1120: 1 unresolved externals


what does this mean?
cheers

trinitrotoluene
11-28-2008, 01:54 PM
Did you compile your project as a console project or as a Win32 project?. It seems that your project is set as a console project so the "special" main function is mandatory. For this case, change it for a Win32 project and all should be fine.

nick2price
11-28-2008, 02:04 PM
I am pretty sure that i set it up as a Win32 project, and if i go configuration manager, the platform is set as Win32.

If i go to linker and set it to Windows, it actually works which is strange.

trinitrotoluene
11-28-2008, 02:11 PM
Maybe,remove the #include <GL/glut.h> you don't need it.

Edit: And add #include <GL/glu.h>

nick2price
11-28-2008, 02:21 PM
That code was abit pass me anyways, so i went back to a normal main. All i have to do now is figure out where my car is. That is why i am trying to rotate the camera, because i presume the car was placed in my skybox, but who knows.

dletozeun
11-28-2008, 11:23 PM
Sorry I can not help you about your linking problem, I am not used to Win32 programming...

gluPerspective set up the projection matrix thus, tell how the geometry is projected onto the framebuffer, saying camera field of view, near, far planes...
glViewport just tells what portion of the screen that will be drawn.
So these functions may help you to initialize your camera but does not have any relation with the camera position and orientation. You need to do this by yourself transforming the whole scene.

In ReSizeGLScene, you initialize your camera depending on window size.
In DrawGLScene before drawing the scene, you need to setup the modelview matrix relating to the camera position and orientation.
You can use your own matrices, or set it with ogl transforming functions like glRotate, glTranslate, or with gluLookAt.