PDA

View Full Version : can glColor* change size of rendering object?



twinra
08-16-2013, 04:02 PM
Hello everybody!

I'm trying to write program rendering cone, that can be rotated using direction keys. I approximate cone by triangles and use GL_TRIANGLES_FAN to defien vertexes. If all the vertexes have the same color everuthing is ok. But if I alternate color of vertexes (red-green-red... and so on) strange behaviour is observable: on every even(n%2 == 0) render I see a cone and on every odd(n%2 == 1) render I see a flat circle. What am I doing wrong?

Unfortunately , I can't add links to screenshots, but hope explanation is understandable.

System: Windows 7 Maximum (6.1.7600)
OpenGL: version 4.3.0; vendor NVIDIA; renderer GeForce GTX 560
FreeGLUT: 2.8.1-1.mp for MSVC
IDE: Microsoft Visual Studio 2008 Version 9.0.21022.8 RTM

Source code:


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

#define GL_PI 3.1415f
#define ROTAION_STEP 5.0f
#define FULL_CIRCLE 360.0f

#define HEIGHT 90.0f
#define RADIUS 45.0f

GLfloat vColorRED[3] = {1.0f, 0.0f, 0.0f};
GLfloat vColorGRN[3] = {0.0f, 1.0f, 0.0f};

GLfloat xRot = 315.0f;
GLfloat yRot = 0.0f;

long renderNum = 0;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
printf("renderNum = %d, xRot = %f, yRot = %d\n", renderNum, xRot, yRot);

glBegin(GL_TRIANGLE_FAN);
{
int icolor = 0;
glVertex3f(0.0f,0.0f,HEIGHT);
for(GLfloat angle = 0.0f; angle <= 2*GL_PI; angle += (GL_PI / 10))
{
glColor3fv(icolor++ % 2? vColorRED : vColorGRN);
glVertex2f(RADIUS * cos(angle), RADIUS * sin(angle));
}
}
glEnd();

glPopMatrix();
glutSwapBuffers();
renderNum++;
}


void SetupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glColor3fv(vColorGRN);

glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_BACK,GL_LINE);
}

void SpecialKeys(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_UP: xRot-= ROTAION_STEP; break;
case GLUT_KEY_DOWN: xRot+= ROTAION_STEP; break;
case GLUT_KEY_LEFT: yRot-= ROTAION_STEP; break;
case GLUT_KEY_RIGHT: yRot+= ROTAION_STEP; break;
}

if(xRot > FULL_CIRCLE - ROTAION_STEP)
xRot = 0.0f;

if(xRot < 0.0f)
xRot = FULL_CIRCLE - ROTAION_STEP;

if(yRot > FULL_CIRCLE - ROTAION_STEP)
yRot = 0.0f;

if(yRot < 0.0f)
yRot = FULL_CIRCLE - ROTAION_STEP;

glutPostRedisplay();
}


void ChangeSize(int w, int h)
{
GLfloat nRange = 100;

if(h == 0) h = 1;
if(w == 0) w = 1;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Rotating Cone Example");
glutPositionWindow(300, 300);

glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();

printf("Version: %s\n", glGetString(GL_VERSION));
printf("Vendor: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));

glutMainLoop();

return 0;
}

Decesive
08-16-2013, 07:00 PM
I'll be swift, I have NO IDEA why doesn't your code work.

Obviously, I would not be replying if I didn't find the answer, and also obviously glColor* doesn't affect the size of the object in any way (apart from any illusions that is), what is affecting the size, is that use glVertex2f, this for some reason makes the geometry render in 3D, which is really odd and don't get me wrong, I think it's really clever to put a 3D vertex on top and make the lower part of 2D's but! that just doesn't work, I guess OpenGL just doesn't know what to stick with (I'm no expert in the matter, so that's my guess).


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

#define GL_PI 3.1415f
#define ROTAION_STEP 5.0f
#define FULL_CIRCLE 360.0f

#define HEIGHT 90.0f
#define RADIUS 45.0f

GLfloat vColorRED[3] = {1.0f, 0.0f, 0.0f};
GLfloat vColorGRN[3] = {0.0f, 1.0f, 0.0f};

GLfloat xRot = 315.0f;
GLfloat yRot = 0.0f;

int renderNum = 0;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
printf("renderNum = %d, xRot = %f, yRot = %f\n", renderNum, xRot, yRot);

glBegin(GL_TRIANGLE_FAN);
{
int icolor = 1;
glVertex3f(0.0f,0.0f,HEIGHT);
for(GLfloat angle = 0.0f; angle <= 2*GL_PI; angle += (GL_PI / 10))
{
glColor3fv(icolor++ % 2? vColorRED : vColorGRN);
glVertex3f(RADIUS * cos(angle), RADIUS * sin(angle), 0.0f); // <---------------------------- This simple change is the answer to how to make it work correctly
}
}
glEnd();

glPopMatrix();
glutSwapBuffers();
renderNum++;
}


void SetupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glColor3fv(vColorGRN);

glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_BACK,GL_LINE);
}

void SpecialKeys(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_UP: xRot-= ROTAION_STEP; break;
case GLUT_KEY_DOWN: xRot+= ROTAION_STEP; break;
case GLUT_KEY_LEFT: yRot-= ROTAION_STEP; break;
case GLUT_KEY_RIGHT: yRot+= ROTAION_STEP; break;
}

if(xRot > FULL_CIRCLE - ROTAION_STEP)
xRot = 0.0f;

if(xRot < 0.0f)
xRot = FULL_CIRCLE - ROTAION_STEP;

if(yRot > FULL_CIRCLE - ROTAION_STEP)
yRot = 0.0f;

if(yRot < 0.0f)
yRot = FULL_CIRCLE - ROTAION_STEP;

glutPostRedisplay();
}


void ChangeSize(int w, int h)
{
GLfloat nRange = 100;

if(h == 0) h = 1;
if(w == 0) w = 1;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Rotating Cone Example");
glutPositionWindow(300, 300);

glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();

printf("Version: %s\n", glGetString(GL_VERSION));
printf("Vendor: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));

glutMainLoop();

return 0;
}

You're welcome ; ).

GClements
08-17-2013, 12:20 AM
What am I doing wrong?
FWIW, your code works fine for me.

However, compiling with warnings enabled gives:


test.c: In function 'RenderScene':
test.c:27:2: warning: format '%d' expects type 'int', but argument 2 has type 'long int'
test.c:27:2: warning: format '%d' expects type 'int', but argument 4 has type 'double'


I suppose it's possible that this could cause problems, although I don't see how.

twinra
08-17-2013, 12:25 AM
Decesive, Thanks a lot! Your advice helped

GClements
08-17-2013, 12:38 AM
is that use glVertex2f, this for some reason makes the geometry render in 3D, which is really odd and don't get me wrong, I think it's really clever to put a 3D vertex on top and make the lower part of 2D's but! that just doesn't work, I guess OpenGL just doesn't know what to stick with (I'm no expert in the matter, so that's my guess).
Vertex coordinates always have 4 components: x,y,z,w. If you don't specify w, it defaults to 1. If you don't specify z, it defaults to 0. So glVertex2f(x,y) is equivalent to glVertex3f(x,y,0) which is equivalent to glVertex4f(x,y,0,1).

twinra
08-17-2013, 12:43 AM
FWIW, your code works fine for me.

However, compiling with warnings enabled gives:


test.c: In function 'RenderScene':
test.c:27:2: warning: format '%d' expects type 'int', but argument 2 has type 'long int'
test.c:27:2: warning: format '%d' expects type 'int', but argument 4 has type 'double'


I suppose it's possible that this could cause problems, although I don't see how.

GCElements, I added this code just for debugging after the problem occurs. I was sure as you are about glVertex*. But using glVertex3f instead of glVertex2f solved the problem.

GClements
08-17-2013, 01:05 AM
But using glVertex3f instead of glVertex2f solved the problem.
In that case, there's a bug in your driver.

Decesive
08-17-2013, 08:32 AM
In that case, there's a bug in your driver.

Try it yourself then, change from glVertex2f to glVertex3f, it's definitely the source of problem, I know that OpenGL defaults those values, but I guess it just doesn't wanna work in 3D. (Which I still find odd by the way, either way)

Maybe there is a bug, in that case, I have it too, running latest drivers from Nvidia (not latest beta, latest stable).

GClements
08-17-2013, 09:37 AM
Try it yourself then,
I did. As I mentioned in my original post, the original code with glVertex2f() works fine for me (AMD HD6800 series).


I guess it just doesn't wanna work in 3D.
"In 3D" is redundant. OpenGL doesn't have "2D" and "3D" modes, it's all 3D.

Based upon the symptoms, I suspect that the function is simply forgetting to set the Z coordinate to zero. If the memory where the Z coordinate is stored normally happens to be zero, the problem wouldn't necessarily show up in testing (and I doubt that glBegin/glEnd-style rendering gets a great deal of testing; it's not likely to be used in any of the programs which are normally used as benchmarks).

Decesive
08-17-2013, 02:14 PM
I've got GTX 460.

Yeah, it sure doesn't get a great deal of testing since it's deperected ; ) I don't think this method should be used anywhere beyond at-home-checking/testing (It's not like I really know why, but I bet they had good reasons to move it to depreceted section) and one more thing, the code works perfectly if you don't move the object, try using those arrow keys, that actually breaks it. (That is, for me and apparently him ; ) )