PDA

View Full Version : In desperate need of some help regarding gluLookAt

binary_bandit
05-11-2005, 11:56 PM
Hiya,

Im trying to use the subdivided icosahedron from the redbook, and use the gluLookAt() function to look at each of the vertices that are plotted and then record there pixel value to a text file, I think this all works - however (there always is a however isnt there!)

Basically I know that I need to "re-display" after ive used gluLookAt, otherwise nothing moves and I just record the same pixel value again and again (Thats whats happening),

Im really stuck with this, ive tried numerous things for the past day or 2 now, and I really can't figure it out, posting here was a last resort...

Any advice would be greatly recieved by this village idiot....(code below, there are 2 files in the project "main.c" and "scan.c" think my problem is in scan.c which is at the bottom)

thanks!

Dave

///////////////////////////////////main.c\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//main.c

#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>

#define A 0.5257311 //more precision needed?
#define B 0.8506508 //more precision needed?

FILE *fp;

static GLfloat vdata[12][3]=
{
{-A, 0, B}, {A, 0, B}, {-A, 0, -B}, {A, 0, -B},
{0, B, A}, {0, B, -A}, {0, -B, A}, {0, -B, -A},
{B, A, 0}, {-B, A, 0}, {B, -A, 0}, {-B, -A, 0}
};

static GLuint index[20][3] =
{
{1, 4, 0}, {4, 9, 0}, {4, 9, 5}, {8, 5, 4}, {1, 8, 4},
{1, 10, 8}, {10, 3, 8}, {8, 3, 5}, {3, 2, 5}, {3, 7, 2},
{3, 10, 7}, {10, 6, 7}, {6, 11, 7}, {6, 0, 11}, {6, 1, 0},
{10, 1, 6}, {11, 0, 9}, {2, 11, 9}, {5, 2, 9}, {11, 2, 7}
};

int NumberofDivisions = 2; //5 seems to provide a nice resolution

void scan(void);

void DrawTriangle(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3])
{
fprintf(fp,"%f, %f, %f\n ", v1[1], v1[2], v1[3]);
fprintf(fp,"%f, %f, %f\n", v2[1], v2[2], v2[3]);
fprintf(fp,"%f, %f, %f\n", v3[1], v3[2], v3[3]);

glBegin(GL_POLYGON);
glNormal3fv(v1);
glVertex3fv(v1);
glNormal3fv(v2);
glVertex3fv(v2);
glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}

void Normalize(float v[3])
{
GLfloat d;

d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);

if(d == 0)
{
exit(0);
}

v[0] /= d;
v[1] /= d;
v[2] /= d;
}

void NormCrosProd(float u[3], float v[3], float out[3])
{
out[0] = u[1] * v[2] - u[2] * v[1];
out[1] = u[2] * v[0] - u[0] * v[2];
out[2] = u[0] * v[1] - u[1] * v[0];
Normalize(out);
}

void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth)
{
GLfloat v12[3], v23[3], v31[3];
int i;

if(depth == 0)
{
DrawTriangle(v1, v2, v3);
return;
}

for(i = 0; i < 3; i++)
{
v12[i] = (v1[i] + v2[i]) / 2.0;
v23[i] = (v2[i] + v3[i]) / 2.0;
v31[i] = (v3[i] + v1[i]) / 2.0;
}

Normalize(v12);
Normalize(v23);
Normalize(v31);
Subdivide(v1, v12, v31, depth-1);
Subdivide(v2, v23, v12, depth-1);
Subdivide(v3, v31, v23, depth-1);
Subdivide(v12, v23, v31, depth-1);

}

void init(void)
{
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

glClearColor(0.0, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

}

void reshape (int w, int h)
{
if(h == 0)
{
h = 1;
}

glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);

gluPerspective(45.0, w/h, 1.0, 100.0);

glMatrixMode(GL_MODELVIEW);
}

void display(void)
{
int i, j;
GLfloat d1[3], d2[3], norm[3];

glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glTranslatef(0.0, 0.0, -10.0);
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );

for(i = 0; i <= 20; i++)
{
Subdivide(vdata[index[i][0]], vdata[index[i][1]], vdata[index[i][2]], NumberofDivisions);
//subdivide and draw sphere
}

glFlush();

}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {

case 27: //bug out.
exit(0);
break;

case 'a':
case 'A':
scan();
break;

}
}

int main(int argc, char** argv)
{
fp = fopen("c:/realdata.txt", "a");

glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Recursive subdivision of a sphere");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
fclose(fp);

return 0;
}

///////////////////////////////////scan.c\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//scan.c

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

struct Vectors{
float X;
float Y;
float Z;
};

struct Vectors *vData;

void scan(void)
{

printf("we have go\n");
int i = 1;
int j = 1;
FILE *fpa;
FILE *fpb;

char filename[256];

vData = (struct Vectors *) malloc(240 + 1 * sizeof(struct Vectors));

if((fpa = fopen("c:/realdata.txt", "r")) == NULL)
{
printf("ut-oh spageteo! vector file couldnt be opened\n");
exit ( 0 );
}

while(i < 240 &amp;&amp; fscanf(fpa, "%f,%f,%f", &amp;vData[i].X, &amp;vData[i].Y, &amp;vData[i].Z) !=EOF)
{

++i;
}

fclose(fpa);

fpb = fopen("c:/intensityreal.txt", "a");

GLubyte pixel[3];

for(j = 1; j <=240; j++)
{
glMatrixMode(GL_MODELVIEW);
gluLookAt(vData[j].X + 1, vData[j].Y + 1, vData[j].Z + 1, 0, 0, 0, 0, 1, 0);
fprintf(fpb, "%d\n", pixel[0]);
}

fclose(fpb);
}

CWiC
05-12-2005, 01:07 AM
Setting the lookAt function just before reading give you nothing. You must set it first, then DRAW, and only then read what you have draw.

binary_bandit
05-12-2005, 01:31 AM
Yea I get that,

But being the idiot I am I can't figure out how to draw it..

so would I just scrap the scan.c and move the gluLookAt and Pixel read into my display() function?

im very confused by this, sorry to be a pain

Dave

charliejay
05-12-2005, 01:56 AM
just a wild guess, but try using glutPostRedisplay somewhere in your input loop, after you take the user's input and adjust the camera position accordingly

CJ

EDIT: no, that isn't it, more to follow
EDIT (ii): actually, no, I >do< think it's that

dvm
05-12-2005, 02:56 AM
Or you could make your display like this:

glClear(..blalbla..);
gluLookAt(eyepos[0], eyepos[1], eyepos[2],
eyelook[0], eyelook[1], eyelook[2],
up[0], up[1], up[2]);

.. do you thing

glutSwapBuffers();
glutPostRedisplay();..or vData instead of eyepos now that I took a better look at your code. Then in your keyboard callback you change the eyepos values and you'll see the result in your image. Remember, you're clearing the matrix (glLoadIdentity()) just before you draw anything, so any call up to that time gets lost. Hope I've made it more clear now. You might want to check out glutSpecialFunc to use the cursor keys to rotate around or use the mouse!

binary_bandit
05-13-2005, 01:16 AM
So I tried to write my function as you said, and decided it was quicker to try and do away with scan.c, and I put it all in one file and change the display funtion to render(), and have render call display from inside its self, code is below,

But i still cant get it to work, I really wanna learn how to make it work, would be grateful if someone would show me but i understand if thats asking to much, sorry.

Anyway cheers guys

Dave

void render(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if(f == 1)
{
display();
printf("d1\n");

if((fpa = fopen("c:/realdata.txt", "r")) == NULL)
{
printf("ut-oh spageteo! vector file couldnt be opened\n");
exit ( 0 );
}

while(i < 240 &amp;&amp; fscanf(fpa, "%f,%f,%f", &amp;vData[i].X, &amp;vData[i].Y, &amp;vData[i].Z) !=EOF)
{

++i;
}

fclose(fpa);
}

fpb = fopen("c:/intensityreal.txt", "a");
gluLookAt(vData[f].X, vData[f].Y, vData[f].Z, 0, 0, 0, 0, 1, 0);
fclose(fpb);
display();
++f;
glutSwapBuffers();

}

T101
05-13-2005, 01:41 AM
I haven't looked at your gluLookAt stuff, but you're doing some very unwise things in your render function:

1. You load from a file. It's not technically wrong, and it only happens when a global variable "f" is 1, but it's not a logical spot to place file loading code. Make a separate function and call it from your main().
2. The variable "i" in your file loading code is not initialised. It may be bigger than 40 , it may be smaller than 0, there is no way of knowing what that will do - although it probably won't do what you want it to do. Also, it would be a better idea to make it a local variable.
3. When you use gluLookAt, you need to make sure that you have the modelview matrix selected, and you need to do a glLoadIdentity before you call it. Otherwise your view is going to "run away".
4. You also try to write (append) to a file before anything is rendered (I think - since the backbuffer would have been cleared on the first line of that function). You open the file, you do a glReadPixels, but you don't actually write anything to the file.
5. You're trying to open files using forward slashes. I could be mistaken, but that probably won't work on Windows. It's more likely that you end up with a file somewhere on your C disk, named "/realdata.txt". To be on the safe side, you should write backslashes. E.g.: "C:\\realdata.txt" (You need to put a double backslash because the backslash is a character "escape" in C).
6. And finally, for that same reason, I would expect the program to just exit when trying to load that file in "frame 1" because there is no file by that name.

T101
05-13-2005, 02:14 AM
Now I've had a look at your scan function, and the following things stand out (although you didn't repost that, so it may no longer be the case):

int i = 1;
vData = (struct Vectors *) malloc(240 + 1 * sizeof(struct Vectors));

for(j = 1; j <=240; j++) 1. I get the impression that you don't know that arrays in C are 0-based. You can have your indices run from 0 up to and including 239. That's 240 items.
2. You're doing a malloc with a value that is too small. That's because you intended to allocate 241 vectors but you've forgotten to put brackets around the 240+1. So now you're allocating 240+sizeof(struct Vectors) bytes instead of 241*sizeof(etc...
3. You're keeping the camera at the origin, and aim it at every "source" vertex in succession. However, there may be other stuff in the way (depending on your data)
4. You're loading into a locally allocated vData array (which isn't the right size, as I stated earlier), but you're drawing using a different vdata (an array of 12*3 floats, defined in your main.c).
5. Good: I notice that you _were_ doing an fprintf in _that_ scan function. Although I presume you'd want to write all three color components, not just the red component.
6. Something that will cause distortion when you're looking at vertices that are ar above/below the horizon: you're using a fixed up-vector. When you tilt the camera up, the up-vector has to tilt backwards. Draw it, you should be able to find out the correct up-vector for a given view target with a little trigonometry.
7. I'm not sure what GLUT_SINGLE does in your main function (I don't use glut). If it means single-buffering, you won't have a backbuffer. That may not be a problem - it could be that GL_BACK just defaults to the frontbuffer if there is no backbuffer.

dvm
05-13-2005, 03:19 PM
Well, since you were kind enough, here's what I consider a barebones glut program:

#include <iostream>
#include <GL/glut.h>

using namespace std;

void init();
void display();
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);

int main(int argc, char *argv[])
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(500, 500);
glutInit(&amp;argc, argv);
glutCreateWindow("My OpenGL Window");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();

return 0; // not really used, glutMainLoop never returns
}

void init()
{
glEnable(GL_DEPTH_TEST);
}

void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // clear the matrix in the start of every frame

gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0); // set up my camera. Of course you can put variables that change from the keyboard callback or from somewhere else;

glutSolidTeapot(1.0); // draw me 'pot

glutSwapBuffers();
glutPostRedisplay();
}

void reshape(int w, int h)
{
glViewport(0, 0, w, h); // set the viewport to cover the whole window
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // of course clear the matrix!
gluPerspective(60.0, (GLdouble)w / (GLdouble)h, 1.0, 100.0); // set our world
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); // just to be safe :)
}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0); // quit if Escape is pressed;
break;
}
}...and that's it!
}

binary_bandit
05-14-2005, 01:15 AM
T101 and dvm,

Im so grateful for all your excellent help, its made me not want to give up learning opengl :-)

Thanks for the time you have spent helping me,

thanks

Dave