PDA

View Full Version : Help to set gluperspective. How to fit every model on screen?



educota
01-08-2016, 07:09 AM
Hey guys!

I hope you all are very well and having a nice new year!

I have been learining a lot with this forum and I would like to ask you some help.

I am trying to draw some models on a OpenGL window. It works already, but just for some models (I am using stl files).

I know I should learn more about perspectives, projections and camera stuff, but I tried it already and I could not make it yet.



What should I do to guarantee that every model fits in the center of my window?

I have already done some calculation with max/minimium values of the model points to give as parameters to gluperspective, but it went wrong...

Thank you in advance and sorry my weird english.





void display(GLFWwindow* window)
{

while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity();
gluLookAt(0, 0, -g_fViewDistance, 0, 0, -1, 0, 1, 0);


glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();

gluPerspective(60, (double)windowWidth / (double)windowHeight, 0.1, 100);



glMatrixMode(GL_MODELVIEW_MATRIX);
glTranslatef(0, 0, zoom);



// Set up the stationary light
glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);


draw();

// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();
}
}

Carmine
01-08-2016, 02:59 PM
My approach is to write a basic program that can display a cube whose dimensions go from -1.0 to +1.0 in all 3 directions. You do not need gluLookAt to do this. You also do not need the variable zoom. Just find the correct number that puts the cube nicely into the field of view of the default GL camera. Once you are able to display the cube, all you have to do is position and scale the model into the cube. You said you have already computed the max and min values of x, y, and z of the STL model, right? The model centroid (u,v,w) would be at:

u = (xmin + xmax) / 2.0
v = (ymin + ymax) / 2.0
z = (zmin + zmax) / 2.0

Translate the model using glTranslatef (-u, -v, -w) to center it in the cube.

The model must also be scaled to fit inside the cube. Do something like below:

xs = (xmax - xmin) / 2.0;
ys = (ymax - ymin) / 2.0;
zs = (zmax - zmin) / 2.0;

qs = the largest of xs, ys, and zs.
sk = 1.0 / qs;

glScalef (sk, sk, sk);

Translation must be applied to the model before the scaling.

GClements
01-08-2016, 05:12 PM
You probably shouldn't be changing the projection to fit the model, but setting the distance between the model and the viewpoint so that the model isn't too close.

If h is the maximum height of the model above or below the point that's at the centre of the view, the distance between the viewpoint and the model should be at least h/tan(radians(fovy/2)), where fovy is the first parameter in the gluPerspective() call.

If w is the maximum width of the model to the left or right of the point that's at the centre of the view, the distance between the viewpoint and the model should be at least w/aspect/tan(radians(fovy/2)).

educota
01-11-2016, 09:48 AM
Great idea, Carmine!
I try to do that now :D

Great idea too, GClements. However how should I do with the third max/min value? I have max/min x, max/min y and max/min z for each model... Sorry if I misunderstood what you said.

GClements
01-11-2016, 10:40 AM
However how should I do with the third max/min value? I have max/min x, max/min y and max/min z for each model...
The minimum and maximum X and Y coordinates tell you how far the model needs to be in front of the viewpoint.

The maximum Z coordinate (i.e. the minimum -Z coordinate; positive Z is behind the viewpoint, negative Z in front) tells you how far the closest point is in front of the viewpoint for a given Z offset.

educota
01-11-2016, 11:54 AM
u = (xmin + xmax) / 2.0
v = (ymin + ymax) / 2.0
z = (zmin + zmax) / 2.0


z should be w, right?
-------------------


I tried to do what you wrote, but it didn't go right yet. I am guessing the problem is on the translate part... I have a model which has every -(min) = max. In this way there won't be a translation, because u, v and w are 0. And only this model (that is not translated) appears right on screen.

Do you have any idea?

Here follows the code. Thank you very very much!!!

ps.: 3 is the number that makes the cube fit in the center of the screen :)




void display(GLFWwindow* window)
{

while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(70, (double)windowWidth / (double)windowHeight, 0.01, 1000);

glMatrixMode(GL_MODELVIEW_MATRIX);
glTranslatef(0, 0, -3);//, zoom);

// Set up the stationary light
glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);

calculamaxmin();

// to fit inside cube
u = (minx + maxx) / 2.0;
v = (miny + maxy) / 2.0;
w = (minz + maxz) / 2.0;

glTranslatef(-u, -v, -w);

// to scale model
xs = (maxx - minx) / 2.0;
ys = (maxy - miny) / 2.0;
zs = (maxz - minz) / 2.0;

if (xs > ys&&xs > zs){
qs = xs;
}
else if (ys > zs){
qs = ys;
}
else{
qs = zs;
}

sk = 1.0 / qs;

glScalef(sk, sk, sk);


//drawCube();
drawSTL();

// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();
}
}

Carmine
01-11-2016, 04:04 PM
Try to display BOTH the cube and the STL model on the screen at the same time. If everything works correctly, the model should show up totally contained within the cube (displayed in wireframe mode). This would be a visual check to make sure your scaling and positioning of the STL model is correct. This would not happen the way your code is written. But it's very easy to do. The call to drawCube must be BEFORE the calls to glScalef and glTranslatef. glScalef and the glTranslatef (-u,-v,-w) should be applied to the STL model ONLY - not the cube. So order of operations would look something like this -



drawCube ();

[compute scale factor of STL]
[compute viewing origin of STL model]

glScalef (sk, sk, sk);
glTranslatef (-u, -v, -w); // Translation applied first, then Scale.

drawSTL();


Remember that the order in which modeling transformations are applied to an object is REVERSE the order of which they appear in the code.

I tried running your code to display a unit cube. It didn't work, unless I made the following changes:

changed glMatrixMode (GL_PROJECTION_MATRIX); to glMatrixMode (GL_PROJECTION);

changed glMatrixMode (GL_MODELVIEW_MATRIX); to glMatrixMode (GL_MODELVIEW);

Also, I had to call glLoadIdentity after the glMatrixMode call.

After making the changes above, if you still don't see the STL model inside the cube, print out the values of xs, ys, zs, and qs to make sure they make sense and are computed correctly. Good luck.

Carmine
01-11-2016, 04:17 PM
I tried to do what you wrote, but it didn't go right yet. I am guessing the problem is on the translate part... I have a model which has every -(min) = max. In this way there won't be a translation, because u, v and w are 0. And only this model (that is not translated) appears right on screen.

It's quite possible that u, v, and w will be 0.0. It means that the origin of the STL model is (0,0,0).
That will not mess up the procedure I have given you because further up in the code you translate by (0, 0, -3).
That translation brings the cube (with the model inside it) to a place where the camera can see it. Once again, do everything in wireframe mode until it's debugged, then go back to surfaces with lighting, etc.

An easy way to switch between wireframe and surface display is to use glPolygonMode.

glPolygonMode(GL_FRONT, GL_LINE); ---> to display model in wireframe mode

glPolygonMode(GL_FRONT, GL_FILL); ---> to display model as solid surfaces

educota
01-12-2016, 08:55 AM
It's quite possible that u, v, and w will be 0.0. It means that the origin of the STL model is (0,0,0).
That will not mess up the procedure...

Yes, I know is possible and it won't be a problem :) But what I meant is that I think the translation math is wrong because only the model which is not affected by translation is appearing on screen. All the others are being affected by the gltranslatef and are not appearing on screen :)


Thank you very much for your help! I will keep trying it now! I haven't already tried what you sent...

educota
01-12-2016, 11:44 AM
Hey guys!

I got what I needed! Now every model is centered and scaled! Thanks, Carmine!!! Now I am having problems with lighting ://

I think my lighting is not fixed and I don't know why...




static float g_lightPos[4] = { 0.5, 1, 1, 0 };

GLFWwindow* initWindow(const int resX, const int resY)
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return NULL;
}
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing

// Open a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow(resX, resY, "TEST", NULL, NULL);

if (window == NULL)
{
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return NULL;
}

glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, controls);

// Get info of GPU and supported OpenGL version
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("OpenGL version supported %s\n", glGetString(GL_VERSION));

glEnable(GL_DEPTH_TEST); // Depth Testing
glDepthFunc(GL_LEQUAL);

glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
return window;
}

void display(GLFWwindow* window)
{


while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);


glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(70, (double)windowWidth / (double)windowHeight, 0.01, 1000);
glMatrixMode(GL_MODELVIEW_MATRIX);


glTranslatef(0, 0, -3);


glRotatef(rotacionarx, 0.0f, 1.0f, 0.0f);

glRotatef(rotacionary, 1.0f, 0.0f, 0.0f);

glRotatef(rotacionarz, 0.0f, 0.0f, 1.0f);


calculamaxmin();


// to scale model
xs = (maxx - minx) / 2.0;
ys = (maxy - miny) / 2.0;
zs = (maxz - minz) / 2.0;

if (xs > ys&&xs > zs){
qs = xs;
}
else if (ys > zs){
qs = ys;
}
else{
qs = zs;
}

sk = 1.0 / qs;

glScalef(sk, sk, sk);


// to fit inside cube
u = (minx + maxx) / 2.0;
v = (miny + maxy) / 2.0;
w = (minz + maxz) / 2.0;

glTranslatef(-u, -v, -w);

drawSTL();

// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();
}
}

Carmine
01-12-2016, 03:54 PM
I got what I needed! Now every model is centered and scaled! Thanks, Carmine!!!Glad to hear you got it working.

A suggestion to speed up your program. STL files can be very large. You don't want to be calling calculamaxmin every time you update the display. It only needs to be called once. Same things go for the variables u,v,w, xs, ys, zs, qs, sk, etc. I assume these are global variables since I don't see them declared anywhere. You could calculate all of them only the first time display is called using a static variable. Something like below ..


void display(GLFWwindow* window)
{
static int first = 1;

while (!glfwWindowShouldClose(window))
{
if (first) {
first = 0;
calculamaxmin ();

xs = (maxx - minx) / 2.0;
ys = (maxy - miny) / 2.0;
zs = (maxz - minz) / 2.0;

if (xs > ys&&xs > zs) qs = xs;
else if (ys > zs) qs = ys;
else qs = zs;

sk = 1.0 / qs;

u = (minx + maxx) / 2.0;
v = (miny + maxy) / 2.0;
w = (minz + maxz) / 2.0;
}

// Scale to window size

// Draw stuff

glScalef (sk, sk, sk);
glTranslatef (-u, -v, -w);

drawSTL ();

// Update Screen

// Check for any input, or window movement
}
}

This should speed up your program, particularly for large .stl files.
To make the display routine cleaner, I'd put the code that calculates all of those variables into the calculamaxmin routine.


I think my lighting is not fixed and I don't know why... This is pretty vague. I'd go back to displaying a solid cube to test the lighting. Perhaps you can post a picture. It could be that the vertex normals of the .stl model haven't been calculated correctly. Are you calculating normals in calculamaxmin or drawSTL? It should be done in calculamaxmin since it is only called once (assuming you take my suggestions above).

Good luck.

Carmine
01-12-2016, 07:08 PM
It could be that the vertex normals of the .stl model haven't been calculated correctly. Are you calculating normals ... Oops. My bad. Just looked up .stl format and found that normals are specified, so you don't have to calculate them. This simplifies things for you. I'd still go back to rendering a solid cube to see if the lighting looks right.

educota
01-16-2016, 10:29 AM
Hey Guys!
I still have the lighting Problem... I have watched some tutorials during the week, but none of them helped me to solve it.

Do you have an idea or some direction I should follow to solve the problem?

For some models, the lighting is moving when I rotate it. And for others is completly wrong. This is not what I want to... I want light just to make it look more real. I tried already to do something to "compensate" when it moves, but I made it wrong.




#define GLFW_INCLUDE_GLU

#include <glew.h>

#include <glfw3.h>

#include <cstdio>




int rotacionarx = 0;
int rotacionary = 0;
int rotacionarz = 0;




float lightAmbient[] = { 0.2f, 0.3f, 0.6f, 1.0f };
float lightDiffuse[] = { 0.2f, 0.3f, 0.6f, 1.0f };
float lightPosition[] = { -2, 2, -3, 1 };//100, 0, -100, 1 };//-2, 2, -3, 1 };// 0, 0, 3, 1};//10, 10, -100, 1};





float u = 0;
float v = 0;
float w = 0;

float xs = 0;
float ys = 0;
float zs = 0;

float qs = 0;
float sk = 0;

float minx = 100000;
float miny = 100000;
float minz = 100000;

float maxx = 0;
float maxy = 0;
float maxz = 0;

void calculamaxmin(){
for (int i = 0; i < n_triangles; i++){
if (tripontos[i].pointss[0].x > maxx) maxx = tripontos[i].pointss[0].x;
if (tripontos[i].pointss[1].x > maxx) maxx = tripontos[i].pointss[1].x;
if (tripontos[i].pointss[2].x > maxx) maxx = tripontos[i].pointss[2].x;

if (tripontos[i].pointss[0].y > maxy) maxy = tripontos[i].pointss[0].y;
if (tripontos[i].pointss[1].y > maxy) maxy = tripontos[i].pointss[1].y;
if (tripontos[i].pointss[2].y > maxy) maxy = tripontos[i].pointss[2].y;

if (tripontos[i].pointss[0].z > maxz) maxz = tripontos[i].pointss[0].z;
if (tripontos[i].pointss[1].z > maxz) maxz = tripontos[i].pointss[1].z;
if (tripontos[i].pointss[2].z > maxz) maxz = tripontos[i].pointss[2].z;

if (tripontos[i].pointss[0].x < minx) minx = tripontos[i].pointss[0].x;
if (tripontos[i].pointss[1].x < minx) minx = tripontos[i].pointss[1].x;
if (tripontos[i].pointss[2].x < minx) minx = tripontos[i].pointss[2].x;

if (tripontos[i].pointss[0].y < miny) miny = tripontos[i].pointss[0].y;
if (tripontos[i].pointss[1].y < miny) miny = tripontos[i].pointss[1].y;
if (tripontos[i].pointss[2].y < miny) miny = tripontos[i].pointss[2].y;

if (tripontos[i].pointss[0].z < minz) minz = tripontos[i].pointss[0].z;
if (tripontos[i].pointss[1].z < minz) minz = tripontos[i].pointss[1].z;
if (tripontos[i].pointss[2].z < minz) minz = tripontos[i].pointss[2].z;

}
}

void controls(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
if (key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GL_TRUE);


if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS){
rotacionary = rotacionary - 5;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS){
rotacionary = rotacionary + 5;
}

if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS){
rotacionarx = rotacionarx - 5;
}
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS){
rotacionarx = rotacionarx + 5;
}

if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS){
rotacionarz = rotacionarz - 5;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
rotacionarz = rotacionarz + 5;
}




}

GLFWwindow* initWindow(const int resX, const int resY)
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return NULL;
}
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing

// Open a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow(resX, resY, "TEST", NULL, NULL);

if (window == NULL)
{
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return NULL;
}

glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, controls);

// Get info of GPU and supported OpenGL version
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("OpenGL version supported %s\n", glGetString(GL_VERSION));

glEnable(GL_DEPTH_TEST); // Depth Testing
glDepthFunc(GL_LEQUAL);

glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);


glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
return window;
}

void drawCube()
{
GLfloat vertices[] =
{
-1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1,
1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1,
-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
-1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1
};


GLfloat colors[] =
{
0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,
1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0,
0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1
};

static float alpha = 0;
//attempt to rotate cube
//glTranslatef(-1, 1, 0);
glRotatef(rotacionarx, 0, 1, 0);
glRotatef(rotacionary, 1, 0, 0);

//glTranslatef(1, -1, 0);

///* We have a color array and a vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

/* Send data : 24 vertices */
glDrawArrays(GL_QUADS, 0, 24);

///* Cleanup states */
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

}



void drawSTL(){


glPushMatrix();
glBegin(GL_TRIANGLES);

for (int i = 0; i < n_triangles; i++){

glNormal3f(trinormals[i].x, trinormals[i].y, trinormals[i].z);
glVertex3f(tripontos[i].pointss[0].x, tripontos[i].pointss[0].y, tripontos[i].pointss[0].z);
glVertex3f(tripontos[i].pointss[1].x, tripontos[i].pointss[1].y, tripontos[i].pointss[1].z);
glVertex3f(tripontos[i].pointss[2].x, tripontos[i].pointss[2].y, tripontos[i].pointss[2].z);

}

glEnd();
glPopMatrix();

}

void display(GLFWwindow* window)
{
static int first = 1;

while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(60, (double)windowWidth / (double)windowHeight, 1, 10000);
glMatrixMode(GL_MODELVIEW_MATRIX);

glTranslatef(0, 0, -3);

/* lightPosition[0] = lightPosition[0] - rotacionarx;
lightPosition[1] = lightPosition[1] - rotacionary;
*///lightPosition[2] = lightPosition[2] - rotacionarz;


glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); //Setup The Ambient Light
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); //Setup The Diffuse Light
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); //Position The Light


glRotatef(rotacionarx, 0.0f, 1.0f, 0.0f);
glRotatef(rotacionary, 1.0f, 0.0f, 0.0f);
glRotatef(rotacionarz, 0.0f, 0.0f, 1.0f);

if (first){
first = 0;

calculamaxmin();


// to scale model
xs = (maxx - minx) / 2.0;
ys = (maxy - miny) / 2.0;
zs = (maxz - minz) / 2.0;

if (xs > ys&&xs > zs) qs = xs;
else if (ys > zs) qs = ys;
else qs = zs;

sk = 1.0 / qs;

// to fit inside cube
u = (minx + maxx) / 2.0;
v = (miny + maxy) / 2.0;
w = (minz + maxz) / 2.0;

}


glScalef(sk, sk, sk);
glTranslatef(-u, -v, -w);

// drawCube();
drawSTL();

// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();
}
}

int meumain()
{
GLFWwindow* window = initWindow(1024, 620);
if (NULL != window)
{
display(window);
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}






PS: I tried to upload some prints but it didnt work out... That is why I created this link https://www.dropbox.com/sh/lkg4er0l9h1oya7/AAA0e218TdOxx0fagbYldGeha?dl=0

The spider I find already very good, but the others are wrong

Carmine
01-16-2016, 05:04 PM
I don't see glEnable(GL_NORMALIZE) in your code. Should probably go in your initWindow routine.

Carmine
01-16-2016, 05:23 PM
You're taking a bit of a chance initializing your max and min variables using the code below.
What happens if you get an STL model with all coordinates less than zero?
This which would lead to incorrect values for maxx, maxy, and maxz.


float minx = 100000;
float miny = 100000;
float minz = 100000;

float maxx = 0;
float maxy = 0;
float maxz = 0;

A better way, which I have used for years, is to do something similar to below.
The min and max values are initialized to values actually in the model.


void calculamaxmin (void)
{
maxx = minx = tripontos[0].pointss[0].x;
maxy = miny = tripontos[0].pointss[0].y;
maxz = minz = tripontos[0].pointss[0].z;

for (int i = 1; i < n_triangles; i++) { // Start this loop with i = 1, instead of i = 0
for (int j = 0; j < 3; j++) {
if (tripontos[i].pointss[j].x > maxx) maxx = tripontos[i].pointss[j].x;
if (tripontos[i].pointss[j].y > maxy) maxy = tripontos[i].pointss[j].y;
if (tripontos[i].pointss[j].z > maxz) maxz = tripontos[i].pointss[j].z;

if (tripontos[i].pointss[j].x < minx) minx = tripontos[i].pointss[j].x;
if (tripontos[i].pointss[j].y < miny) miny = tripontos[i].pointss[j].y;
if (tripontos[i].pointss[j].z < minz) minz = tripontos[i].pointss[j].z;
}
}

educota
01-18-2016, 12:07 PM
Thank you very much, Carmine!!!
This way is much smarter than mine! I knew it was kind of wrong, but I needed to show the model on screen fast hahaha
glEnable(GL_NORMALIZE) helped a bit, but I still have the problem to light the model... I've created more 2 lights and it is almost going nice :D

educota
01-22-2016, 10:44 AM
Hey guys!

Is there an way to rotate the object without rotating the original axis?

Carmine
01-25-2016, 12:13 AM
Is there an way to rotate the object without rotating the original axis?Not sure what you mean. I've written an STL displayer that can rotate a model independent of the unit box and original axes. Is this what you had in mind? BTW - this is done with one light source only.

http://s22.postimg.org/baposyr29/Vader.gif

educota
01-26-2016, 08:54 AM
Yes! This is what I meant...
I need to have the axis fixed, because I want to store the rotations I did in angles (to be applied in other model).

When the axis are not fixed, I store the wrong values for the angles... This happens because when a rotate in x and after in y, at the moment of the second roration there is a new x axis, different from original.

ps.: great darth vader btw hahaa

educota
02-01-2016, 11:13 AM
Hey Carmine :)
Could you tell me how did you do the rotation independent of the original axes?

Thank you very much :D :D

Carmine
02-02-2016, 09:11 PM
... when a rotate in x and after in y, at the moment of the second roration there is a new x axis, different from original.Not sure what you mean. Do you understand Push and PopMatrix? In the code below, the modeling transformations on lines AAAAA, BBBBB, and CCCCC would only be applied to Object_A. Without the Push and Pop statements the transformations would be applied to objects A and B. Does this help you out?


glPushMatrix ();
glTranslatef (); // AAAAA
glRotatef (); // BBBBB
glScalef (); // CCCCC
Draw_Object_A ();
glPopMatrix ();

Draw_Object_B ();

educota
02-03-2016, 07:12 AM
Hey! Thank you (agaaaain :)) for your answer.

Yes. I understand Push/Pop, but actually I don't draw two objects... I draw and rotate the same object.

The problem is that i need to store how much I am rotating (in angle degrees). For that I am using the variables "rotacionarx", "rotacionary" and "rotacionarz" (as the code below), but I am not storing it right, because when I apply the stored angles it is messed up.


glRotatef(rotacionarx, 1.0f, 0.0f, 0.0f);
glRotatef(rotacionary, 0.0f, 1.0f, 0.0f);
glRotatef(rotacionarz, 0.0f, 0.0f, 1.0f);


The reference (x,y,z) is changing when I rotate and that is why I am storing the values wrongly. I need the reference axis to be fixed just as you did with the darth vader :)


Someone told me that the problem is related to the matrix property A*B != B*A and that I can't use glRotatef because it rotates one axis per time.
For solving this I shouldn't use glRotatef and build my own rotation matrix. I've been working on it and trying to understand how it works, but didn't get it yet...

I also found something like this :


float radAngle = (rotacionarx / 180.f)*3.1415f;
glRotatef(rotacionarx, 1.f, 0.f, 0.f);
glRotatef(rotacionary, 0.f, cos(radAngle), -sin(radAngle));

Which is kind of compensation for the "reference changing" but I could not apply to my project.

Thank you very much for your help and generosity. I hope I am not bothering you too much :D


edit: I just read my problem name is gimble lock

Carmine
02-03-2016, 05:02 PM
Someone told me that the problem is related to the matrix property A*B != B*A and that I can't use glRotatef because it rotates one axis per time. For solving this I shouldn't use glRotatef and build my own rotation matrix. This might be your problem. If so, you can still use glRotatef, if done correctly.


I just read my problem name is gimble lockI doubt the problem is gimbal lock.

But I still don't understand your problem. Rather than trying to explain it in general terms, can you give us a specific example of what you want to happen, and what actually happens. I'm sure the forum could help you out if you did that. It would also help if you included just the portion of your code where the rotations are applied.

educota
02-05-2016, 09:53 AM
This is my problem:

http://i.stack.imgur.com/EWKWG.gif

After each rotation I have a new reference.

I need to rotate the object and keep the reference the same :)




void display(GLFWwindow* window)
{
static int first = 1;

while (!glfwWindowShouldClose(window))
{
// Scale to window size
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);

// Draw stuff


glClearColor(212.0f/255.0f, 208.0f/255.0f, 200.0f/255.0f, 1.0f); //255 r 236 g 233 b 216
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
gluPerspective(60, (double)windowWidth / (double)windowHeight, 1, 10000);
glMatrixMode(GL_MODELVIEW_MATRIX);

glPushMatrix();

glTranslatef(0, 0, -3);

// drawCube();


glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); //Setup The Ambient Light
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); //Setup The Diffuse Light
// glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); //Position The Light
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbient); //Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse); //Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION, lightPosition1); //Position The Light
glLightfv(GL_LIGHT2, GL_AMBIENT, lightAmbient); //Setup The Ambient Light
glLightfv(GL_LIGHT2, GL_DIFFUSE, lightDiffuse); //Setup The Diffuse Light
glLightfv(GL_LIGHT2, GL_POSITION, lightPosition2); //Position The Light


glRotatef(rotacionarx, 1.0f, 0.0f, 0.0f);
glRotatef(rotacionary, 0.0f, 1.0f, 0.0f);
glRotatef(rotacionarz, 0.0f, 0.0f, 1.0f);

/*float radAngle = (rotacionarx / 180.f)*3.1415f;
glRotatef(rotacionarx, 1.f, 0.f, 0.f);
glRotatef(rotacionary, 0.f, cos(radAngle), -sin(radAngle));*/





if (first){
first = 0;

calculamaxmin();


// to scale model
xs = (maxx - minx) / 2.0;
ys = (maxy - miny) / 2.0;
zs = (maxz - minz) / 2.0;

if (xs > ys&&xs > zs) qs = xs;
else if (ys > zs) qs = ys;
else qs = zs;

sk = 1.0 / qs;

// to fit inside cube
u = (minx + maxx) / 2.0;
v = (miny + maxy) / 2.0;
w = (minz + maxz) / 2.0;

}


glScalef(sk, sk, sk);

glTranslatef(-u, -v, -w);

// drawCube();

drawSTL();
glPopMatrix();


// Update Screen
glfwSwapBuffers(window);

// Check for any input, or window movement
glfwPollEvents();
}
}



Thank you again :D

Carmine
02-05-2016, 01:25 PM
Thanks for taking the time to post. I am working on a response, but I must be sure I understand what your goal is. Because, there are lots of people out there who would want their rotations to behave exactly as shown in your animation (Euler sequence rotations). I assume that you want the second and third rotations (and maybe more) to take place around the blue axes, not the red or yellow axes? Correct? If so, I can show you a simple fix to your code that will make that happen. Though, you may find, in the long run, that you don't really want your rotations to behave that way.

educota
02-06-2016, 09:20 AM
I am the one who needs to thank haha :)

Yes... that is what I want. All rotations to take place at the blue axes.

After that, I guess I will achieve my second goal: store in 3 variables how much I've rotated the object in x,y,z (from the blue fixed axes) in angle degrees.

Thank youuuu :)

Carmine
02-06-2016, 10:30 PM
.... what I want. All rotations to take place at the blue axes. I just posted some code/animation (https://www.opengl.org/discussion_boards/showthread.php/198179-Fixed-Pipeline-Axis-Relative-Rotations?p=1281448#post1281448) that shows how to do this and then some. The demo shows how to implement rotations around screen-fixed axes and/or body-fixed axes. The type of rotations you want are screen-fixed. I leave it up to you to alter your code to do what my GLUT demo does. My rotations are driven by pushing buttons on the keyboard. What drives your rotations?

It is true that A*B != B*A when it comes to matrix multiplication. Rotating my robot +15 degs around the X axis, then -10 degs around the Y axis results in a different orientation than rotating -10 degs about Y followed by +15 about X. If you want to reproduce an orientation exactly using a sequence of rotations about axes, you have to keep track of the rotation angles and the order in which the rotations were done. An easier way to do this is to save the orientation matrix (omat in my code), and reload it to reproduce a previous orientation.

Note that glRotatef is not explicitly used in my Display function. What glRotatef does is generate a 4x4 matrix which is applied to the matrix stack or object via matrix multiplication. glMultMatrix(omat) is used in my code instead. 'omat' is a matrix that is stored and manipulated in response to keyboard actions. These 'manipulations' are simply matrix multiplications accomplished using the appropriate glRotatef commands in the 'Screen_Orientation' routine.