Egoshooter Perspektive programmieren mit OpenGL
-
Hallo erstmal,
ich hab da mal eine Frage, die ihr schon fast aus der Überschrift entnehmen könnt.
"Wie programmier ich eine Egoshooter Perspektive unter OpenGL ?"
Nun gut, hier sind paar spezifischere Angaben :
Ihr kennt bestimmt alle die Nehe GameDev - Tutorials. Im 10. Tutorial geht es um eine 3D - Welt und wie man sich in ihr bewegt. Den ganzen Code versteh ich, bis auf den Bewegungspart. Zum Einen wegen der Trigonometrie ( wo ich hoffe, bei Euch auf eine gute Erklärung zu stoßen ) und zum Anderen wegen dem Ablauf.
Ich hab mich da mal selber rangewagt und einen eigenen Code entwickelt. Die Welt ist die gleiche, nur die Texturen sind änderbar. Das Problem ist nachwievor die Bewegung.
main.cpp
// =============== MAIN_CPP =============== // #include "StdAfx.h" #include "texture_handler.h" #include <math.h> enum Textures{ CRATE = 0, GLASS_1, GLASS_2, GLASS_3 }eTextures = CRATE; HDC hDC=NULL; HGLRC hRC=NULL; HWND hWnd=NULL; HINSTANCE hInstance; bool keys[256]; bool active=TRUE; bool fullscreen=TRUE; GLfloat fX = 0.0f; GLfloat fY = 0.0f; GLfloat fZ = -6.0f; GLfloat fRotateX = 0.0f; GLfloat fRotateY = 0.0f; GLfloat fTransX = 0.0f; GLfloat fTransY = -0.5f; GLfloat fTransZ = -6.0f; BOOL bB = FALSE; BOOL bBlending = FALSE; BOOL bC = FALSE; BOOL bCrouching = FALSE; BOOL bSpace = FALSE; BOOL bJump = FALSE; const float piover180 = 0.0174532925f; float heading; float xpos; float zpos; GLfloat yrot; // Y Rotation GLfloat walkbias = 0; GLfloat walkbiasangle = 0; GLfloat lookupdown = 0.0f; GLfloat z = 0.0f; // Depth Into The Screen LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); texture_handler TextureHandler; struct tagVERTEX{ float x, y, z; float u, v; }vertex; struct tagTRIANGLE{ tagVERTEX vertex[3]; }triangle; struct tagSECTOR{ int numtriangles; tagTRIANGLE* triangle; }sector1; void readstr( FILE *pFile, char *szString ){ do{ fgets( szString, 255, pFile ); }while( (szString[0] == '/' ) || ( szString[0] == '\n' ) ); } void SetupWorld(){ FILE *pFile; float fX, fY, fZ, fU, fV; int iTriangleNumber; char szString[255]; pFile = fopen( "_Data/world.txt", "rt" ); if( !pFile ){ MessageBox( NULL, "Open file failed.", "File not exists", MB_OK ); } readstr( pFile, szString ); sscanf_s( szString, "NUMPOLLIES %d\n", &iTriangleNumber ); sector1.triangle = new tagTRIANGLE[ iTriangleNumber ]; sector1.numtriangles = iTriangleNumber; for( int iLoopTriangle = 0; iLoopTriangle < iTriangleNumber; iLoopTriangle++ ){ for( int iLoopVertex = 0; iLoopVertex < 3; iLoopVertex++ ){ readstr( pFile, szString ); sscanf_s( szString, "%f %f %f %f %f", &fX, &fY, &fZ, &fU, &fV ); sector1.triangle[ iLoopTriangle ].vertex[ iLoopVertex ].x = fX; sector1.triangle[ iLoopTriangle ].vertex[ iLoopVertex ].y = fY; sector1.triangle[ iLoopTriangle ].vertex[ iLoopVertex ].z = fZ; sector1.triangle[ iLoopTriangle ].vertex[ iLoopVertex ].u = fU; sector1.triangle[ iLoopTriangle ].vertex[ iLoopVertex ].v = fV; } } fclose( pFile ); } 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(); } int InitGL(){ if( !TextureHandler.LoadTexture( "_Data/_Pics/crate.bmp", TextureHandler.GetTexture( CRATE ) ) ){ return FALSE; } if( !TextureHandler.LoadTexture( "_Data/_Pics/glass_1.bmp", TextureHandler.GetTexture( GLASS_1 ) ) ){ return FALSE; } if( !TextureHandler.LoadTexture( "_Data/_Pics/glass_2.bmp", TextureHandler.GetTexture( GLASS_2 ) ) ){ return FALSE; } if( !TextureHandler.LoadTexture( "_Data/_Pics/glass_3.bmp", TextureHandler.GetTexture( GLASS_3 ) ) ){ return FALSE; } glColor4f( 1.0f, 1.0f, 1.0f, 0.5f ); glBlendFunc( GL_SRC_ALPHA,GL_ONE ); glEnable( GL_TEXTURE_2D ); glShadeModel( GL_SMOOTH ); glClearColor( 0.0f, 0.0f, 0.0f, 0.5f ); glClearDepth( 1.0f ); glEnable( GL_DEPTH_TEST ); glDepthFunc( GL_LEQUAL ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); SetupWorld(); return TRUE; } int DrawGLScene(){ int iNumberTriangle; GLfloat x_m, y_m, z_m, u_m, v_m; GLfloat sceneroty = 360.0f - fRotateX; fTransY = walkbias - 0.25f; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glBindTexture( GL_TEXTURE_2D, TextureHandler.GetTexture( eTextures ) ); glRotatef( sceneroty, 0.0f, 1.0f, 0.0f ); glRotatef( fRotateY, 1.0f, 0.0f, 0.0f ); glTranslatef( fTransX, fTransY, fTransZ ); iNumberTriangle = sector1.numtriangles; for (int loop_m = 0; loop_m < iNumberTriangle; loop_m++){ glBegin(GL_TRIANGLES); glNormal3f( 0.0f, 0.0f, 1.0f); x_m = sector1.triangle[loop_m].vertex[0].x; y_m = sector1.triangle[loop_m].vertex[0].y; z_m = sector1.triangle[loop_m].vertex[0].z; u_m = sector1.triangle[loop_m].vertex[0].u; v_m = sector1.triangle[loop_m].vertex[0].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); x_m = sector1.triangle[loop_m].vertex[1].x; y_m = sector1.triangle[loop_m].vertex[1].y; z_m = sector1.triangle[loop_m].vertex[1].z; u_m = sector1.triangle[loop_m].vertex[1].u; v_m = sector1.triangle[loop_m].vertex[1].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); x_m = sector1.triangle[loop_m].vertex[2].x; y_m = sector1.triangle[loop_m].vertex[2].y; z_m = sector1.triangle[loop_m].vertex[2].z; u_m = sector1.triangle[loop_m].vertex[2].u; v_m = sector1.triangle[loop_m].vertex[2].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); glEnd(); } return TRUE; } GLvoid KillGLWindow(){ 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 && !ReleaseDC(hWnd,hDC)){ MessageBox( NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION ); hDC = NULL; } if (hWnd && !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( &wc ) ){ MessageBox( NULL, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION ); return FALSE; } if (fullscreen){ DEVMODE dmScreenSettings; memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL){ if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",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(&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,&pfd))){ KillGLWindow(); MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if(!SetPixelFormat(hDC,PixelFormat,&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_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 ){ MSG msg; BOOL done=FALSE; if ( MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO ){ fullscreen = FALSE; } if ( !CreateGLWindow("NeHe's OpenGL Framework", 640, 480, 16, fullscreen )){ return 0; } while( !done ){ if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ if ( msg.message == WM_QUIT ){ done=TRUE; } else{ TranslateMessage(&msg); DispatchMessage(&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("NeHe's OpenGL Framework",640,480,16,fullscreen)){ return 0; } } } // ============== KEYBOARD_CONTROL ============== // if( keys['W'] ){ fTransX -= (float)sin(heading*piover180) * 0.05f; fTransZ -= (float)cos(heading*piover180) * 0.05f; if (walkbiasangle <= 1.0f) { walkbiasangle = 359.0f; } else { walkbiasangle+= 10; } walkbias = (float)sin(walkbiasangle * piover180)/20.0f; } if( keys['S'] ){ fTransX += (float)sin(heading*piover180) * 0.05f; fTransZ += (float)cos(heading*piover180) * 0.05f; if (walkbiasangle <= 1.0f) { walkbiasangle = 359.0f; } else { walkbiasangle-= 10; } walkbias = (float)sin(walkbiasangle * piover180)/20.0f; } if( keys['A'] ){ fRotateX += 1.0f; } if( keys['D'] ){ fRotateX -= 1.0f; } if( keys[ VK_UP ] ){ fRotateY -= 1.0f; } if( keys[ VK_DOWN ] ){ fRotateY += 1.0f; } if( keys[ VK_LEFT ] ){ if( fRotateX > 360.0f || fRotateX < -360.0f ){ fRotateX = 0.0f; } fRotateX -= 1.5f; } if( keys[ VK_RIGHT ] ){ if( fRotateX > 360.0f || fRotateX < -360.0f ){ fRotateX = 0.0f; } fRotateX += 1.5f; } // ============== CHANGE_TEXTURE ============== // if( keys[ VK_F5 ] ){ keys[ VK_F5 ] = FALSE; eTextures = CRATE; } if( keys[ VK_F6 ] ){ keys[ VK_F6 ] = FALSE; eTextures = GLASS_1; } if( keys[ VK_F7 ] ){ keys[ VK_F7 ] = FALSE; eTextures = GLASS_2; } if( keys[ VK_F8 ] ){ keys[ VK_F8 ] = FALSE; eTextures = GLASS_3; } // ============== SPECIAL_KEYS ============== // // ================ BLENDING ================ // if( keys['B'] && !bB){ bB = TRUE; bBlending = !bBlending; if( bBlending ){ glEnable( GL_BLEND ); glDisable( GL_DEPTH_TEST ); } else{ glEnable( GL_DEPTH_TEST ); glDisable( GL_BLEND ); } } if( !keys['B'] ){ bB = FALSE; } // ================ CROUCHING ================ // if( keys['C'] && !bC ){ bCrouching = TRUE; if( bCrouching ){ fTransY += 0.2f; bC = TRUE; } } if( !keys['C'] && bC ){ bCrouching = FALSE; if( !bCrouching ){ fTransY -= 0.2f; bC = FALSE; } } }//while(!done) KillGLWindow(); return (msg.wParam); }
Da der Code jetzt, denk ich mal, ein bisschen mächtig ist, sind hier nocheinmal die spannenden stellen.
main.cpp -> DrawGLScene() :
int DrawGLScene(){ int iNumberTriangle; GLfloat x_m, y_m, z_m, u_m, v_m; GLfloat sceneroty = 360.0f - fRotateX; fTransY = walkbias - 0.25f; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glBindTexture( GL_TEXTURE_2D, TextureHandler.GetTexture( eTextures ) ); glRotatef( sceneroty, 0.0f, 1.0f, 0.0f ); glRotatef( fRotateY, 1.0f, 0.0f, 0.0f ); glTranslatef( fTransX, fTransY, fTransZ ); iNumberTriangle = sector1.numtriangles; for (int loop_m = 0; loop_m < iNumberTriangle; loop_m++){ glBegin(GL_TRIANGLES); glNormal3f( 0.0f, 0.0f, 1.0f); x_m = sector1.triangle[loop_m].vertex[0].x; y_m = sector1.triangle[loop_m].vertex[0].y; z_m = sector1.triangle[loop_m].vertex[0].z; u_m = sector1.triangle[loop_m].vertex[0].u; v_m = sector1.triangle[loop_m].vertex[0].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); x_m = sector1.triangle[loop_m].vertex[1].x; y_m = sector1.triangle[loop_m].vertex[1].y; z_m = sector1.triangle[loop_m].vertex[1].z; u_m = sector1.triangle[loop_m].vertex[1].u; v_m = sector1.triangle[loop_m].vertex[1].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); x_m = sector1.triangle[loop_m].vertex[2].x; y_m = sector1.triangle[loop_m].vertex[2].y; z_m = sector1.triangle[loop_m].vertex[2].z; u_m = sector1.triangle[loop_m].vertex[2].u; v_m = sector1.triangle[loop_m].vertex[2].v; glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m); glEnd(); } return TRUE; }
main.cpp -> WinMain -> While-Loop :
while( !done ){ if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ if ( msg.message == WM_QUIT ){ done=TRUE; } else{ TranslateMessage(&msg); DispatchMessage(&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("NeHe's OpenGL Framework",640,480,16,fullscreen)){ return 0; } } } // ============== KEYBOARD_CONTROL ============== // if( keys['W'] ){ fTransX -= (float)sin(heading*piover180) * 0.05f; fTransZ -= (float)cos(heading*piover180) * 0.05f; if (walkbiasangle <= 1.0f) { walkbiasangle = 359.0f; } else { walkbiasangle+= 10; } walkbias = (float)sin(walkbiasangle * piover180)/20.0f; } if( keys['S'] ){ fTransX += (float)sin(heading*piover180) * 0.05f; fTransZ += (float)cos(heading*piover180) * 0.05f; if (walkbiasangle <= 1.0f) { walkbiasangle = 359.0f; } else { walkbiasangle-= 10; } walkbias = (float)sin(walkbiasangle * piover180)/20.0f; } if( keys['A'] ){ fRotateX += 1.0f; } if( keys['D'] ){ fRotateX -= 1.0f; } if( keys[ VK_UP ] ){ fRotateY -= 1.0f; } if( keys[ VK_DOWN ] ){ fRotateY += 1.0f; } if( keys[ VK_LEFT ] ){ if( fRotateX > 360.0f || fRotateX < -360.0f ){ fRotateX = 0.0f; } fRotateX -= 1.5f; } if( keys[ VK_RIGHT ] ){ if( fRotateX > 360.0f || fRotateX < -360.0f ){ fRotateX = 0.0f; } fRotateX += 1.5f; } // ============== CHANGE_TEXTURE ============== // if( keys[ VK_F5 ] ){ keys[ VK_F5 ] = FALSE; eTextures = CRATE; } if( keys[ VK_F6 ] ){ keys[ VK_F6 ] = FALSE; eTextures = GLASS_1; } if( keys[ VK_F7 ] ){ keys[ VK_F7 ] = FALSE; eTextures = GLASS_2; } if( keys[ VK_F8 ] ){ keys[ VK_F8 ] = FALSE; eTextures = GLASS_3; } // ============== SPECIAL_KEYS ============== // // ================ BLENDING ================ // if( keys['B'] && !bB){ bB = TRUE; bBlending = !bBlending; if( bBlending ){ glEnable( GL_BLEND ); glDisable( GL_DEPTH_TEST ); } else{ glEnable( GL_DEPTH_TEST ); glDisable( GL_BLEND ); } } if( !keys['B'] ){ bB = FALSE; } // ================ CROUCHING ================ // if( keys['C'] && !bC ){ bCrouching = TRUE; if( bCrouching ){ fTransY += 0.2f; bC = TRUE; } } if( !keys['C'] && bC ){ bCrouching = FALSE; if( !bCrouching ){ fTransY -= 0.2f; bC = FALSE; } } }//while(!done)
und jetzt nocheinmal den Link zum beschriebenen Tutorial :
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=10PS:
Wenn das mit meinem Code, zugegebenermaßen, ein wenig zu anstrengend ist zu Erklären, würde ich mich ebenfalls darüber freuen, wenn Ihr mir die Grundlegende Idee erklärt.
Was machen die Funktionen sin(x) und cos(x) ?
Für welchen Trigonometriequatsch braucht man den ?usw.
Danke schonmal, wenn ihr bis hierher gelesen habt.
**Mfg
jookerxxx**
-
Das ist OpenGL 1.x. Lerne lieber direkt OpenGL 3.x oder OpenGL 4.x.
-
ja Danke schonmal für deine Antwort.
Trotzdem wird die Mathematik die selbe sein. Und die Art, wie man die Perspektive erstellt auch
-
Sinus und Cosinus benötigt man für Rundungen (
cos(x)
=sin(x + (Pi / 2)
). Wie die Graphen der Funktionen aussehen kannst du auf Wikipedia nachschauen. Die beiden Funktionen benötigt man um Rundungen zu kalkulieren (Kreise, Ellipsen, Kugeln, runde Kanten, ...).Auf was du sicher noch stossen wirst ist Tangens und Arkus-Tangens. Sie berechnen Winkel im rechwinkligen Dreieck.
-
jookerxxx schrieb:
Und die Art, wie man die Perspektive erstellt auch
Die Perspektive ist eigentlich nur eine 4x4-Matrix mit der alle Vektoren multipliziert werden müssen. Diese Matrix kannst du vor OpenGL 3.0 mit irgendwelchen FF-Funktion manipulieren. Ab OpenGL 3.0 schickst du sie als Array an das Vertex-Programm.
-
wieso denn eine 4x4 Matrix ? Was komm denn da für Werte rein ?
Ich hab da so an x,y,z gedacht. Das wärn dann drei
-
Bei der Grafik rechnet man häufig mit Homogenen Koordinaten (weil man da auch die Translation durch Matrix-Multiplikation ausdrücken kann).
-
Identitätsmatrix ("leere" Matrix):
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
Translationsmatrix:
1 0 0 x 0 1 0 y 0 0 1 z 0 0 0 1
Skalierungsmatrix:
x 0 0 0 0 y 0 0 0 0 z 0 0 0 0 1
Rotationsmatrix: Keine Ahnung, schau irgendwo nach...
Wenn du zwei Matrizen auf eine Matrix "reduzieren" willst (die dann noch das selbe macht) muss du sie miteinander multiplizieren (Achtung, nicht kommutativ!).
EDIT: CStoll war schneller...
-
WoW,
Danke für die MatritzenHilfe, aber meine Frage ist :
Der Code enthält doch wohl kaum Matrizen Rechnung, wie sie
bei OpenGL 5.0x gebraucht wird oder ?mat3, mat4, etc. seh ich iwie nischt xD
oder was versucht Ihr mir hier zu vermitteln ?
Also ich hab mich jetzt einigermaßen GUT in sin(x) und cos(x) eingelsen.Meine Frage ist nur, wie er die neue Position berechnet wird ?
Mal angenommen, auf der "W"-Taste bewegt man sich nach "vorne".
Wenn man sich dann um 180° dreht, dann liegt bei mir das große Problem,
dass ich mich nach HINTEN bewege. Eigentlich auch klar, weil die Taste
"W" bei mir nix anderes macht, als eine Variable zu Dekrementieren.Genau das gleiche Problem ist , wenn man sich um 90° nach links dreht und "W" immernoch drückt, so bewegt man sich nicht nach vorne, sondern zur Seite nach rechts.
drückt, so bewegt er s
-
jookerxxx schrieb:
Der Code enthält doch wohl kaum Matrizen Rechnung, wie sie
bei OpenGL 5.0x gebraucht wird oder ?Ab OpenGL 3.x sicher nicht. Aber OpenGL 5.x gibt's noch nicht
.
Und das wegen dem Winkel und der Fortbewegung: Dreiecks-Welle
-
jookerxxx schrieb:
Mal angenommen, auf der "W"-Taste bewegt man sich nach "vorne".
Wenn man sich dann um 180° dreht, dann liegt bei mir das große Problem,
dass ich mich nach HINTEN bewege. Eigentlich auch klar, weil die Taste
"W" bei mir nix anderes macht, als eine Variable zu Dekrementieren.Wo Vorne und Hinten ist kannst Du abhanegig vom Rotationswinkel am Einheitskreis ablesen.
-
Ihr habt lust mich zu schockieren oda? xD
Kann mir nicht jemand die Rechnung Punktgenau erklären ? So mit süßen Bildchen ? xD Bin aufgeschmissen.
Ich weiß zwar was Matrizen sind. Wie man sie Multipliziert und was für Matrizenformen ( scale, translate etc. ) es da gibt. Sinus Cosinus ist jetzt auch nicht mehr das allzu große Problem, aber mit dem Code komm ich einfach nicht klar.
xD
Ich glaube mein Gehirn schaltet auf Stur xD (L)Ich wäre SEHR erfreut, wenn mir jemand die abgespeckte Version, von dem obrigen Code mit Bildchen erklären könnte.
(L)
-
Du verstehst also nicht wie man einen Punkt auf einem Kreis findet aber moechtest einen Ego-Shooter programmieren?...
-
Die Fortbewegung sollte mit einer Dreiecks-Welle und nicht mit einer Sinus-Welle erfolgen, oder irre ich mich da?
-
Germanys Next MMO Progger
-
this->that schrieb:
Germanys Next MMO Progger
MMORPG tönt realistischer :p
-
EOutOfResources schrieb:
Die Fortbewegung sollte mit einer Dreiecks-Welle und nicht mit einer Sinus-Welle erfolgen, oder irre ich mich da?
Daher auch der Ausdruck "Du drehst Dich im Dreieck" ?
-
hellihjb schrieb:
Daher auch der Ausdruck "Du drehst Dich im Dreieck" ?
Ich meinte die Fortbewegung:
W drücken: Dreieck Cosinus 0° 1 1 45° 0.5 0.707 90° 0 0
Wenn man 'W' drückt und um 45° gedreht ist, geht 50% der Geschwindigkeit in die Z-Achse und auch 50% in die X-Achse. Und nicht je 70.7%.
EDIT: Oder hab ich gerade 'nen Aussetzer?
-
EOutOfResources schrieb:
[/code]Wenn man 'W' drückt und um 45° gedreht ist, geht 50% der Geschwindigkeit in die Z-Achse und auch 50% in die X-Achse. Und nicht je 70.7%.
EDIT: Oder hab ich gerade 'nen Aussetzer?
Denk Dir mal ein Quadrat mit den Seitenlängen 0.707.
Wie lang ist die Diagonale? (Satz des Pythagoras!)
Also muß man 0.707 Geschwindigkeit in X-Richtung und 0.707 Geschwindigkeit in Y-Richtung machen, um in Schräg-Richtung 1 Geschwindigkeit zu machen.
-
Ja, stimmt. Sorry.
-
Oke, ich habs jetzt gecheckt.
Mein gehirn hat heute mal nicht ausgesetzt.Nur zur Info :
Ich hab die Variable "heading" in dem Code nicht gecheckt.
Jetzt ist eig alles klar."heading" = Angle.
Bei mir siehts also wie folgt aus :
GLfloat fAngle.
Bei Taste "A" :
fAngle += 0.5f;
Bei Taste "D" :
fAngle -= 0.5f;
Bei Taste "W" :
fTransX -= (float)sin(fAngle*piover180) * 0.05f; fTransZ -= (float)cos(fAngle*piover180) * 0.05f; //fAngle*piover180 = Gradzahl in Radiant
Bei Taste "S" :
fTransX += (float)sin(fAngle*piover180) * 0.05f; fTransZ += (float)cos(fAngle*piover180) * 0.05f; //fAngle*piover180 = Gradzahl in Radiant
Der Code in der ScenenFunktion :
glRotatef( -fAngle, 0.0f, 1.0f, 0.0f ); glTranslatef( -fTransX, fTransY, -fTransZ );
Und alles passt. Den realistikquatsch von wegen, SinusWave, damit es wie menschenLauf aussieht brauch ich nicht.
Vielen Vielen Dank, für die Hilfe, die Ihr mir gerade geboten habt. Und die Zeit über. Zumindest weiß ich jetzt, dass Trigonometrie entscheidend wichtig ist.
Mfg
jookerxxx (went lucky today)