Working on a "camera"

Jones
Unregistered
 
Post: #1
I'm working on making a "camera" routine, to look around 3D space with a mouse or keys or whatever. Unfortunatly, I've run into a strange problem. It's not in the math... I've got some help with that, and I'm figuring it out, so please refrain from telling me what I'm doing wrong in that regard. Basically, what this code *should* do, is get the Y of the mouse, then make the camera look up or down based on that. But when I run it, I just see the mac os x window... no black of the GL context... (set up with SDL). Here's my code:

Code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cmath>

#include "SDL.h"
#include "OpenGL/gl.h"
#include "OpenGL/glu.h"

#include "IL/il.h"
#include "IL/ilu.h"
#include "IL/ilut.h"

#include "FTGL_all.h"

#include "glTexture.h"

using namespace std;

int yTarget = 0;
SDL_Event event;

/*    Set up SDL, OpenGL & DevIL video stuff.    */
void setupVideo(int width_sv, int height_sv, int bpp_sv, int fullscreen_sv) {
    /*    SDL.    */
    SDL_Init(SDL_INIT_VIDEO);
    if (fullscreen_sv > 0) {
        SDL_SetVideoMode(width_sv, height_sv, bpp_sv, SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN);
    }
    else {
        SDL_SetVideoMode(width_sv, height_sv, bpp_sv, SDL_OPENGL | SDL_HWSURFACE);
    }
    /*    OpenGL.    */
    glViewport(0, 0, width_sv, height_sv);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, width_sv, 0, height_sv, 0.0, -200.0);
    glMatrixMode(GL_MODELVIEW);
    glOrtho(0.0, width_sv, 0, height_sv, 0.0, -200.0);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(0.0f);
    //glEnableClientState(GL_NORMAL_ARRAY);
    //glEnableClientState(GL_COLOR_ARRAY);
    //glEnableClientState(GL_VERTEX_ARRAY);
    //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    /*    DevIL.    */
    //ilInit();
    //iluInit();
    //ilutInit();
    //ilutRenderer(ILUT_OPENGL);

    gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);

}

int mouseMovedFunc(int relX, int relY) {
    int angleToMoveX = relX;
    int angleToMoveY = relY;
    
    int resultOfTanY = tan(relY);
    int lookHereY = resultOfTanY * 100.0;
    return(lookHereY);
}

/*    Drawing function.    */
void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    while (SDL_WaitEvent(&event) != 0) {
        
        switch(event.type) {
        
            case SDL_MOUSEMOTION:
                yTarget = mouseMovedFunc(event.motion.xrel, event.motion.yrel);
                break;
            
            default:
                yTarget = yTarget;
                break;
        
        }
        
    }
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
        glLoadIdentity();
        glTranslatef(20, 30, -100);
        glBegin(GL_QUADS);
            glVertex3d(0, 0, 0);
            glVertex3d(30, 0, 0);
            glVertex3d(30, 30, 0);
            glVertex3d(0, 30, 0);
        glEnd();
    glPopMatrix();
    
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
        gluLookAt(0.0, 0.0, 0.0, 0.0, yTarget, -100.0, 0.0, 1.0, 0.0);
    glPopMatrix();
    
    SDL_GL_SwapBuffers();
}

int main(int argc, char *argv[])
{
    setupVideo(320, 240, 32, 0);
    
    while (2 > 1) {
        display();
    }
    
    SDL_Delay(4000);
    SDL_Quit();
    return(0);
}

Basically, what I do is use the simple setupVideo function to set up a 3D space that uses pixels as measurement, although I'm still trying to wrap my mind around the concept of pixels on and off the screen in 3D space. Is it a good idea to match your glOrtho x and y values to your screen resolutions? Huh Wacko

Please, feel free to tell me how badly I'm making use of OpenGL's matrice system, and glOrtho commands... I also have the funniest feeling i've left one command out... but for the life of me I can't remember what.

Thanks for any help!
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #2
you probably dont want to do gluLookAt in projection mode,

you can replace
Code:
            default:
                yTarget = yTarget;
                break;
with

apart from that, I dunno looks ok. Get graphics on screen before doing a camera, build it up slowly.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Jones
Unregistered
 
Post: #3
Isn't the camera stuff ALWAYS supposed to be in projection mode? I thought modelview was reserved for modelling/drawing?
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #4
depends what you mean by camera.
and nothing is ALWAYS.. do it like you want to.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Jones
Unregistered
 
Post: #5
Ok. Well, I swapped some stuff up, and changed stuff that didn't make sense and here's a slightly different version:

Code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cmath>

#include "SDL.h"
#include "OpenGL/gl.h"
#include "OpenGL/glu.h"

#include "IL/il.h"
#include "IL/ilu.h"
#include "IL/ilut.h"

#include "FTGL_all.h"

#include "glTexture.h"

using namespace std;

int yTarget = 0;
SDL_Event event;

/*    Set up SDL, OpenGL & DevIL video stuff.    */
void setupVideo(int width_sv, int height_sv, int bpp_sv, int fullscreen_sv) {
    /*    SDL.    */
    SDL_Init(SDL_INIT_VIDEO);
    if (fullscreen_sv > 0) {
        SDL_SetVideoMode(width_sv, height_sv, bpp_sv, SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN);
    }
    else {
        SDL_SetVideoMode(width_sv, height_sv, bpp_sv, SDL_OPENGL | SDL_HWSURFACE);
    }
    /*    OpenGL.    */
    glViewport(0, 0, width_sv, height_sv);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, 100.0, 0, 100.0, 0.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
    glOrtho(0.0, 100.0, 0, 100.0, 0.0, 100.0);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(0.0f);
    /*    DevIL.    */
    //ilInit();
    //iluInit();
    //ilutInit();
    //ilutRenderer(ILUT_OPENGL);

    glMatrixMode(GL_PROJECTION);
    gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);

}

int mouseMovedFunc(int relX, int relY) {
    int angleToMoveX = relX;
    int angleToMoveY = relY;
    
    int resultOfTanY = tan(relY);
    int lookHereY = resultOfTanY * 100.0;
    return(lookHereY);
}

/*    Drawing function.    */
void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    while (SDL_WaitEvent(&event) != 0) {
        
        switch(event.type) {
        
            case SDL_MOUSEMOTION:
                yTarget = mouseMovedFunc(event.motion.xrel, event.motion.yrel);
                break;
            
            default:
                yTarget = yTarget;
                break;
        
        }
        
    }
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
        glLoadIdentity();
        glTranslatef(20, 30, -70);
        glBegin(GL_QUADS);
            glVertex3d(0, 0, 0);
            glVertex3d(30, 0, 0);
            glVertex3d(30, 30, 0);
            glVertex3d(0, 30, 0);
        glEnd();
    glPopMatrix();
    
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
        gluLookAt(0.0, 0.0, 0.0, 0.0, yTarget, -100.0, 0.0, 1.0, 0.0);
    glPopMatrix();
    
    SDL_GL_SwapBuffers();
}

int main(int argc, char *argv[])
{
    setupVideo(320, 240, 32, 0);
    
    while (2 > 1) {
        display();
    }
    
    SDL_Delay(4000);
    SDL_Quit();
    return(0);
}

Only slightly. I still get the same blank Cocoa window... no context. This is strange, normally when this happens I get an SDL parachute error.

Also, could somebody please explain to me the glOrtho system? It made sense for 2D, because I could set it for the number of pixels of my window's width and height, but with 3D... it gets complicated. All of a sudden I have to have z pixels, and -z pixels... (Is z by default towards me? Or into the screen? (Opposed to -z). And what about negative x and y values? Also, I say that 0,0 is the top left of my screen, does that mean the origin starts slightly to the top left of the "camera"?

No, that's impossible because the "camera" starts at 0,0,0 according to the Red Book. Wait... so if I define the top left of the window as being 0,0... do I start in the top left of my window? Wacko

My brain hurts. Rasp
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #6
why are you doing glOrtho in *both* projection and modelview? chances are it should only be in projection... who knows what the second will be doing.

Ortho defines a non-perspective view, which makes the concept of "camera" kinda weird.
Quote this message in a reply
Jones
Unregistered
 
Post: #7
Yeah, I just read that chapter of the red book. All makes sense now. I put glOrtho into modelview because I wanted to use my own form of measurement when it came to drawing. Perhaps that was silly....

EDIT: Removed the glOrtho from my modelview matrix, and replaced the projection one with a gluPerspective call. Same results. Grr.. This has got to be an SDL error or something. I'll try doing the same in GLUT.
Quote this message in a reply
Jones
Unregistered
 
Post: #8
Well, here's the GLUT version. It's a little different...

Code:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>

#include "GLUT/glut.h"

#include "FTGL_all.h"

using namespace std;

typedef struct coord2D {
    float x;
    float y;
};

typedef struct coord3D {
    float x;
    float y;
    float z;
};

coord2D mousePos;
bool firstMouseGet = TRUE;

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(0.0);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_TEXTURE_2D);
}

void glCameraRotate(float x_rot, float y_rot) {
    float resY = tanf(y_rot);
    float resX = tanf(x_rot);
    float resZ = -100.0;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 0.0, resX, resY, resZ, 0.0, 1.0, 0.0);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
        glTranslatef(0.0, 0.5, -3.0);
        glBegin(GL_POLYGON);
            glVertex3f(0.0, 0.0, 0.0);
            glVertex3f(0.6, 0.2, 0.0);
            glVertex3f(0.3, -0.2, 0.0);
        glEnd();
    glPopMatrix();
    
    glFlush();
    glutSwapBuffers();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(1.0, 1.333, 10.0, 20.0);
}

void mouse(int button, int state, int x, int y) {
    if (firstMouseGet == TRUE) {
        mousePos.x = x;
        mousePos.y = y;
        firstMouseGet == FALSE;
    }
    
    glCameraRotate(x - mousePos.x, y - mousePos.y);
    
    mousePos.x = x;
    mousePos.y = y;
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(320, 240);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("GLUT Context - OpenGL");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMainLoop();
    return(0);
}

I don't see the polygon, I've tried moving the mouse around a bit, but nothing. It should start in front of the camera, as it is down the negative z axis, no?

After a little revision of the camera section in the red book, I realise there a few basic errors. For example, my gluLookAt is actually a modelling translation. I then read this:

http://www.gamedev.net/reference/article...cle405.asp

I'm not sure I understand all the matrix math though. Any specific tutorials you'd like to suggest?
Quote this message in a reply
Moderator
Posts: 1,562
Joined: 2003.10
Post: #9
I'm not sure it's what you're looking for, but I've written a tutorial on matrices, which can be found here:

http://www.sacredsoftware.net/tutorials/...ices.xhtml
Quote this message in a reply
Jones
Unregistered
 
Post: #10
ThemsAllTook Wrote:I'm not sure it's what you're looking for, but I've written a tutorial on matrices, which can be found here:

http://www.sacredsoftware.net/tutorials/...ices.xhtml

Thanks! Your Quaternion tutorial seems useful. Well, more useful that making and modifying your own matrices. I just can't see why somebody would want to do that themselves. Are OpenGL's built in matrice manipulation commands not sufficient? A quaternion could be used in accordance with a glRotatef command, correct? (Fitting the angle, and x,y,z values into the arguments.)

As I understand it vectors are something they place in chapter 2 of the Red Book when really you don't need to use them till later... unless I need them now. Which right now I'm wondering if I do... Wacko I see how they could be useful for lighting and stuff, like cross product vectors being compared to rays of light, etc... etc. Tell me if I'm on to something here:

If I could get the vector for wherever the camera is pointing, which would essentially be 0,0,0 to 0,0,-100 (by default) or whatever it has been changed to, then I could calculate the right angle vector, for left and right movement. Wait... can that be done? *Goes back to tutorial.*

So far, I know this: If I want to point my camera 30Ëš up, for example, I'd use tan and that angle to get a y variable for my gluLookAt. (Scaled to whatever size you want it, if I knew my z was 100, then the y would be tan(30) * 100.)

The rest, I have yet to figure out.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #11
Quote:A quaternion could be used in accordance with a glRotatef command, correct?
wrong..

It would probably be useful to understand vectors before trying to deal with things like matrices or quaternions. walk before you can run etc..

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Moderator
Posts: 1,562
Joined: 2003.10
Post: #12
Using the x, y, z, and w components of a quaternion directly in glRotatef won't do what you want, but if you convert it to an axis/angle representation and pass those values to glRotatef, it will.
Quote this message in a reply
Jones
Unregistered
 
Post: #13
unknown Wrote:walk before you can run etc..

I'm not very good at that. Rasp

But if I wanted to pass value x and w of a quaternion, rather then all four, if would work, correct? Or a while loop of sorts that just sorted through the quaternion running each rotation (x,y,z) one by one. Another vector tutorial I read showed all their function as being "inline". Q quik google explained that inline functions can speed up a program significantly if used correctly (on small functions as I understand it).

After rereading your text for the third time, I had another inspiration. Let's say I take a vector, that points to the camera's target point. And then I normalize it, would it point along the same line? That's how I see it. Then, with it having a defined length of 1.0, would it not be easier to calculate at what angle left and right would be? But a length equalling 90Ëš could be in any variating set of positions or lengths... so maybe not. (Is there a... reverse dot product of sorts? Not that that would help much more...)

It your examples, ThemsAlltook, you use a spaceship rotation example. I have one question, do the ship.direction->x and ship.direction->y variables hold coordinates for a target point/vector or actually rotation values? You assign them sin and cos values, of the angle, so I'm guessin they're a point in 2D/3D space.

The problem I have is that I have no idea how to apply these mathematics to my code.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #14
Quote:But if I wanted to pass value x and w of a quaternion, rather then all four, if would work, correct?
wrong...

glRotatef(angle, x, y, z);

Quaternion, a + bi + cj + dk
a = cos(angle/2)
b = sin(angle/2)*x
c = sin(angle/2)*y
d = sin(angle/2)*z

they do not correspond.

Quote:reverse dot product of sorts?
the function you are looking for is inverse cosine.

Quote:The problem I have is that I have no idea how to apply these mathematics to my code.
you aren't applying mathematics to your code, you are using maths as a tool to create code that does what you want. So you need to be able to adequetly describe mathematically what you want to do (and note special cases etc) before you can program it. Thats why I would recommend you make your concepts of vectors and matrices concrete before dealing with quaternions.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Jones
Unregistered
 
Post: #15
Well, in truth, if I can get by with vectors and matrices then I won't bother with quaternions right away. A fourth dimension will just confuse me. Wacko

I'm beginning to understand matrices more, and I like them. Essentially all glRotate, glScale, glTranslate just modify a matrix in OpenGL's "subsystem". Essentially, one could (with reasonable ease) right those three commands for themselves. The one thing I don't understand is how to combine all the values of a matrice without some overwriting each other. I'm assuming that because the matrices are multiplied by each other that it will just be using all the values that have been simplified into less values.

And your example of matrix multiplication, all three matrices are the same. (ie m1, m2 and result)

Quote:To compute the value of each cell in the new matrix, each value on the cell's row in the left-hand matrix (starting from the left) is multiplied by each value in the cell's column in the right-hand matrix (starting from the top). The results of the multiplications are added together, and the sum becomes the new value at that cell in the matrix.

Wouldn't that mean that to get the value of the cell you label as 6, in the result you would do this:

2 * 4
6 * 5
10 * 6
14 * 7

And then add them, which would be more than 6, correct? Annoyed

Anyways, like I asked before, why would you want to do your own matrix math? It's good to know how it works, but essentially, one can always do the same with gl commands. I'm starting to realise how vectors can help me, after rereading your bit about the spaceship a couple of times. But I can gaurentee I'll be back with more problems. Wink
Quote this message in a reply
Post Reply