OpenGL ARToolkit - Calling a draw function based of KeyEvent - c

I have two draw functions - "drawComponents" and "drawSignals" which look as follows:
static void drawComponents(ARdouble trans1[3][4], ARdouble trans2[3][4], int r, int g, int b )
{
for (int i = 0; i < numComponents; i++){
glPushMatrix(); // Save world coordinate system.
glTranslatef(0.0f, 0.0f, 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &(components[i].combCoords[0]));
glColor4ub(r, g, b, 0);
glDrawElements(GL_LINES, components[i].nIndeces, GL_UNSIGNED_INT, &(components[i].combIndeces[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix(); // Restore world coordinate system.
}
}
static void drawSignals(ARdouble trans1[3][4], ARdouble trans2[3][4], int r, int g, int b)
{
for (int i = 0; i < numSignals; i++)
{
glPushMatrix(); // Save world coordinate system.
glTranslatef(0.0f, 0.0f, 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, signal[i].combCoords);
glColor4ub(r, g, b, 0);
glDrawElements(GL_LINES, signal[i].nIndeces, GL_UNSIGNED_INT, &(signal[i].combIndeces[0]));
glPopMatrix();
}
}
These functions work fine if i just call the directly in the MainLoop, however I want to call them based on user input. So if the "1" key is pressed then the drawComponents will be called, and if the "2" key is pressed the the drawSignals function will be called.
To do this I have the following keyEvent function:
static void keyEvent(unsigned char key, int x, int y)
{
switch (key) {
case '1':
drawComponents(config->trans, config->marker[3].trans, 255, 0, 0);
break;
case '2':
drawSignals(config->trans, config->marker[3].trans, 0, 0, 255);
break;
}
}
I thought would work fine, however with this function, nothing happens when I press the keys. Anyone have any suggestions as to where I'm going wrong

Related

Interpolation curve with opengl using evaluators

This code almost works, but the problem is that it leaves behind the last control point like if it doesn't exist. I cannot find the error and I don't know why, I checked the transformation matrix and the converted control point many times but nothing
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <math.h>
// Begin globals.
static int numVal = 0;
// Final control points.
static float controlPoints[4][3] =
{
{-30.0, 0.0, 0.0}, { -10.0, 20.0, 0.0},
{10.0, -20.0, 0.0}, {30.0, 0.0, 0.0}
};
//Matrix multiplication Mb^-1 * Mi
static float conversion[4][4] =
{
{1.0,0.0,0.0,0.0},{-0.8333,3.0,-1.5,0.3333},{0.3333,-1.5,3.0,-0.8333},{0.0,0.0,0.0,1.0}
};
//End globals
//Control point conversion for evaluator
void convertcp(float ctrlpoints[4][3]){
int i,j,k;
float tot = 0.0;
for(i = 0; i < 4;i++){
for(j = 0;j < 4;j++){
ctrlpoints[i][j] = 0;
for(k = 0; k < 3;k++){
ctrlpoints[i][j] += conversion[i][k] * controlPoints[k][j];
}
}
}
}
// End globals.
// Initialization routine.
void setup(void){glClearColor(1.0, 1.0, 1.0, 0.0);}
// Drawing routine.
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
int indx;
float ctrlpoints[4][3];
convertcp(ctrlpoints);
// Draw the control polygon in light gray.
glColor3f(0.7,0.7, 0.7);
glBegin(GL_LINE_STRIP);
for (indx = 0; indx < 4; indx++)
glVertex3fv(controlPoints[indx]);
glEnd();
// Specify and enable the Bezier curve.
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
// Draw the Bezier curve by defining a sample grid and evaluating on it.
glColor3f(0.0, 0.0, 0.0);
glMapGrid1f(100, 0.0, 1.0);
glEvalMesh1(GL_LINE, 0, 100);
// Draw the Bezier control points as dots.
glPointSize(5.0);
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (indx = 0; indx < 4; indx++)
glVertex3fv(controlPoints[indx]);
glEnd();
// Highlight selected control point,
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
glVertex3fv(controlPoints[numVal]);
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
// OpenGL window reshape routine.
void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
case ' ':
if (numVal < 3) numVal++;
else numVal = 0;
glutPostRedisplay();
break;
default:
break;
}
}
// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)
{
if(key == GLUT_KEY_UP) controlPoints[numVal][2] += 1.0;
if(key == GLUT_KEY_DOWN) controlPoints[numVal][2] -= 1.0;
if(key == GLUT_KEY_LEFT) controlPoints[numVal][0] -= 1.0;
if(key == GLUT_KEY_RIGHT) controlPoints[numVal][0] += 1.0;
glutPostRedisplay();
}
// Routine to output interaction instructions to the console window.
void printInteraction(void)
{
printf("Interaction:\n");
printf("Press space to select a control point.\n");
printf("Press the arrow keys to move the selected control point.\n");
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Interpolating Curves");
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glutSpecialFunc(specialKeyInput);
glewExperimental = GL_TRUE;
glewInit();
setup();
glutMainLoop();
}

OpenGL GL_POINTS result differs from input

I want to draw something with GL_POINTS but after ~totalpoint/3 result starts differ from input by 1 pixel
I tried different glOrtho and glViewport arguments but nothing changed
my test program:
int w = atoi(argv[1]);
int h = atoi(argv[2]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, 1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
unsigned int wf,hf;
unsigned char rgb[3];
while(!glfwWindowShouldClose(window)){
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glBegin(GL_POINTS);
for(hf=0;hf<h;hf++){
for(wf=0;wf<w;wf++){
memset(rgb,0,3);
rgb[wf%3]=0xff;
glColor3ub(rgb[0],rgb[1],rgb[2]);
glVertex2f(wf,hf);
}
}
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
Results:
Not Colored
Colored
Michael Roy's way its solved my problem i just changed this line
GLFWwindow* wmain = glfwCreateWindow(atoi(argv[1]), atoi(argv[2]), "test", 0, 0);
to
GLFWwindow* wmain = glfwCreateWindow(atoi(argv[1]) + 1, atoi(argv[2]) + 1, "test", 0, 0);

How can I make this sphere revolve around another when I press a key?

I am new to OpenGL and I am trying to mimic the planetary system. I have an Earth and Sun. I want the earth to rotate on its axis when I press R and to revolve around the sun when I press T. I have tried the following with no success. Here is the code so far:
#include <GL/glut.h>
int angle=1;
int x,y,z=0;
int axis=0;
void init(void){
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void drawEarth(void){
glutWireSphere(0.5,30,30);
}
void idleFunc(){
angle++;
glutPostRedisplay();
}
void key(unsigned char key, int x, int y){
if (key=='R'){
idleFunc(); // How can I make this function run ONLY when I press R?
//Or how can I make my earth continuosly rotating when I press R?
glutPostRedisplay();
} else
if(key=='T'){
//How can I make it revolve around the sun when I press key T?
//I have tried glTranslate(x,y,z); with no success
glutPostRedisplay();
}
}
void display(void){
glClearColor(0.05,0.05,0.5,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
///////////////////////
glColor3f(0.03,0.05,0.09);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glRotatef(angle, 1.0,1.0,1.0); //Is this making it rotate about its axis?
drawEarth(); //Draw Earth
glPopMatrix();
/////////////////////////////////////
glPushMatrix();
glTranslatef(.7,.7,.7);
glColor3f(1.0,1.0,1.0);
glutWireSphere(0.2,50,50); //Sun
glPopMatrix();
glFlush();
}
int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowPosition(10,10);
glutInitWindowSize(400,400);
init();
glutCreateWindow("Planets");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idleFunc);
glFlush();
glutMainLoop();
}
Question:
How can I make the earth revolve around the sun? Thanks.
PS: I have put some comments in the code where I am confused.
Set up your timer/idle callback so that it always runs but only updates the sun/axis angle if the corresponding flag (that the keyboard callback toggles) is set:
#include <GL/glut.h>
bool animateAxis = false;
bool animateSun = false;
void key(unsigned char key, int x, int y)
{
if( key == 'r' ) animateAxis = !animateAxis;
if( key == 't' ) animateSun = !animateSun;
}
int angleAxis = 0;
int angleSun = 0;
void update()
{
if( animateAxis ) angleAxis += 3;
if( animateSun ) angleSun += 1;
angleAxis = angleAxis % 360;
angleSun = angleSun % 360;
}
void display(void)
{
glClearColor(0.05,0.05,0.2,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective( 60.0, w / h, 0.1, 100.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt
(
30, 30, 30,
0, 0, 0,
0, 0, 1
);
// sun
glColor3ub( 255, 255, 0 );
glutWireSphere( 5, 8, 8 );
// earth
glPushMatrix();
// rotate around sun
glRotatef( angleSun, 0, 0, 1 );
glTranslatef( 20, 0, 0 );
// rotate around axis
glRotatef( angleAxis, 0, 0, 1 );
glColor3ub( 31, 117, 254 );
glutWireSphere( 2, 8, 8 );
glPopMatrix();
glutSwapBuffers();
}
void timer( int value )
{
update();
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutCreateWindow("Planets");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
}

Controlling where to zoom in on the Mandelbrot set

I wrote a simple fragment shader that renders a mandelbrot set. I am doing this in c and with opengl using glsl.
#version 330 core
in vec2 fCoord; //position.x position.y which is -1 to 1 on both axis
uniform int maxIterations;
uniform sampler1D mandiTexture;
out vec4 color;
void main()
{
vec2 c, z;
c.x = fCoord.x;
c.y = fCoord.y;
int i;
z = vec2(0.0f, 0.0f);
for(i=0; i<maxIterations; i++) {
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;
if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}
vec4 tcolor;
if (i == maxIterations)
{
tcolor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
else
{
tcolor = texture(mandiTexture, float(i) / float(maxIterations));
}
color = tcolor;
}
i've noticed playing around with the initial z value I get some different results but mostly they extend outside of my quad. With z as 0, 0 I get this result.
as you can see the left side of the set is not being rendered on the quad.
The c value is coming from the vertex shader so i assume it goes for -1 to 1 on both x and y axis and being interpolated in between.
My questions are:
1) How can I center the image on the quad? I am not really sure of
that.
2) How can I say zoom in on some in on the mandelbrot set and a
follow up, lets say I want to zoom in on a specific part of the set?
2B) Let's say I click the screen and get the position in NDC?
3) If I set my max iterations higher the set seems to get really
jaggy, is that normal behavior?
I think if I can understand how to zoom in on the set I can figure out how to zoom in on a specific part but I am unsure.
edit, making sure that my code is
main.c
int maxIterations = 70;
int iterAmount = 1;
char* vshad, *fshad;
GLuint verticesBuffer, colorBuffer, vao, texCoordBuffer, indicesBuffer;
GLuint mandiTextureID, sp;
mat4_s vm, pm, opm, tm;
GLint viewMat = -1;
GLint projMat = -1;
GLint modelMat = -1;
GLint mandiTexture = -1;
GLint maxIterLoc = -1;
void initShaders(void)
{
char* vertexShaderSource = getResource("vert.shad");
char* fragmentShaderSource = getResource("frag.shad");
vshad = readFile(vertexShaderSource);
fshad = readFile(fragmentShaderSource);
free(vertexShaderSource);
free(fragmentShaderSource);
}
int run_game()
{
current_utc_time(&start_time);
while(game_running)
{
current_utc_time(&current_time);
double frameTime = (diff(start_time,current_time).tv_sec + diff(start_time,current_time).tv_nsec) * .00000001;
//printf("float time: %0.8f\n",frameTime);
if ( frameTime > 0.25 )
{
frameTime = 0.25;
}
current_utc_time(&start_time);
current_time = start_time;
accumulator += frameTime;
while ( accumulator >= dt )
{
accumulator -= dt;
t += dt;
//printf("fixed update dt: %0.8f\n",dt);
}
//render_state = currentState * alpha + previousState * ( 1.0 - alpha );
const double alpha = accumulator / dt;
render();
if(game_running < 1) { break; }
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
game_running = -1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
game_running = -1;
break;
}
break;
}
}
}
return -1;
}
int main(int argc, char const *argv[]) {
initShaders();
mat4_identity(&vm);
vec3_s eye = {0, 0, 0};
vec3_s center = {0, 0, -1};
vec3_s up = {0, 1, 0};
mat4_lookAt(&vm, &eye, &center, &up);
mat4_identity(&opm);
mat4_ortho(&opm, 0, 200, 0, 200, 1, 100);
mat4_identity(&tm);
mat4_scalex(&tm, &tm, 100, 100, 0);
mat4_translatex(&tm, &tm, 100.0f, 100.0f, -20);
SDL_Surface* mandiSurface = loadPNG(getResource("mandi.png"));
if(!mandiSurface) {
printf("IMG_Load: %s\n", IMG_GetError());
// handle error
}
GLenum Mode1 = GL_RGB;
if(4 == mandiSurface->format->BytesPerPixel)
{
Mode1 = GL_RGBA;
printf("mode change");
}
sp = getShaderProgram(vshad, fshad);
r = newRenderable2d();
glGenVertexArrays(1, &vao);
glGenBuffers(1, &verticesBuffer);
glGenBuffers(1, &colorBuffer);
glGenBuffers(1, &indicesBuffer);
glGenBuffers(1, &texCoordBuffer);
glBindVertexArray(vao); //bind vertex array buffer
glBindBuffer(GL_ARRAY_BUFFER, verticesBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->vertices), r->vertices, GL_STATIC_DRAW);
//bind n setup indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(r->indices), r->indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind indices
//bind n setup colors
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->colors), r->colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind colors
//bind n setup texture coords
glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->texCoords), r->texCoords, GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind texture coords
glBindVertexArray(0); //unbind vertex array buffer
//mandi 1d texture
glGenTextures(1, &mandiTextureID);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, Mode1, mandiSurface->w, 0, Mode1, GL_UNSIGNED_BYTE, mandiSurface->pixels);
glBindTexture(GL_TEXTURE_1D, 0);
free(mandiSurface);
while(run_game() >= 0);
free(r);
IMG_Quit();
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(window);
return 0;
}
void render()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glUseProgram(sp);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);//mandiTexture
mandiTexture = getUniformLocation(sp, "mandiTexture");
glUniform1i(mandiTexture, 0);
glBindVertexArray(verticesBuffer);
viewMat = getUniformLocation(sp, "viewMat");
modelMat = getUniformLocation(sp, "modelMat");
projMat = getUniformLocation(sp, "projMat");
maxIterLoc = getUniformLocation(sp, "maxIterations");
glUniformMatrix4fv(viewMat, 1, GL_FALSE, vm.m);
glUniformMatrix4fv(projMat, 1, GL_FALSE, opm.m);
glUniformMatrix4fv(modelMat, 1, GL_FALSE, tm.m);
glUniform1i(maxIterLoc, maxIterations);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
int init_sdl(int width, int height, char* title, double fps)
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
SDL_Log("sdl failed to init");
SDL_Quit();
return -1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(window == NULL)
{
SDL_Log("sdl failed to create window");
SDL_Quit();
return -1;
}
maincontext = SDL_GL_CreateContext(window);
if(maincontext == NULL)
{
SDL_Log("sdl failed to create opengl context");
SDL_Quit();
return -1;
}
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
SDL_GL_SetSwapInterval(1);
return 1;
}
vertex shader
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 icolor;
layout (location = 2) in vec2 vTexCoord;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;
out vec4 fcolor;
out vec2 fTexCoord;
out vec2 fCoord;
void main()
{
gl_Position = projMat * viewMat * modelMat * vec4(position, 1.0);
fCoord = vec2(position);
fTexCoord = vTexCoord;
fcolor = vec4(icolor, 1.0f);
}
thanks to #samgak I was able to fixed the issues that I was having and now I am adding some shots of the Mandelbrot set.
The c value is coming from the vertex shader so i assume it goes for -1 to 1 on both x and y axis and being interpolated in between.
That's correct.
1) How can I center the image on the quad? I am not really sure of that.
You just need to zoom out by a factor of 1.5 and center it on -0.5. The interesting parts of the Mandelbrot set extend from roughly -2 to 1 on the real axis and -i to i on the imaginary axis:
2) How can I say zoom in on some in on the mandelbrot set and a follow up, lets say I want to zoom in on a specific part of the set?
2B) Let's say I click the screen and get the position in NDC?
Put back the 2 uniforms that you had in your previous version:
uniform vec2 center;
uniform float scale;
Declare variables to hold these values in your C code and set them with glUniform2f and glUniform1f. To center the set the initial values should be -0.5, 0.0 for the center, and 1.5 for the scale (larger values zoom out). Then in your fragment shader, just apply them like this:
c = (fCoord * scale) + center;
To click the screen and zoom in on a particular location, turn the mouse location into a value between -1,-1 and 1,1 based on its position on the screen then apply the above equation to it to find the location you clicked on. Set that as the new center and multiply scale by a value less than 1 to zoom in a given amount.
3) If I set my max iterations higher the set seems to get really jaggy, is that normal behavior?
The screenshot you posted looks ok. It would probably look better if you implemented some kind of multi-sampling in your fragment shader (e.g. calculate several values in a loop and add them together so that each pixel is actually the average of a 2x2 or 4x4 block of pixels etc).
If you zoom in far enough eventually you will run into the limits of the precision of the floating point numbers used by the GPU.

tessellating a sphere using triangles of different colors

I am writing a function to generate a sphere using triangles to tessellate it, but what I want is for the triangles to all have different colors. However, when I run the code, it creates a sphere but the colors range from light blue to black with no green or red at all and the colors repeat, which is not what I want.
Here is a segment of the code. The whole code can produce a sphere but it is the coloring that I am really stuck on.
triangles is a vector<vector<Vertex3>> which contains the collection of all triangle vertices that make up this sphere.
glBegin(GL_TRIANGLES);
int red = 0;
int green = 0;
int blue = 0;
for( int j = 0; j< triangles.size(); j++ )
{
if(red < 200)
red++;
else if (blue < 200)
green++;
else blue++;
glColor3ub(red, green, blue);
//normalize the triangles first
triangles[j][0].normalize();
triangles[j][2].normalize();
triangles[j][2].normalize();
//call to draw vertices
glVertex3f( (GLfloat)triangles[j][0].getX(),(GLfloat)triangles[j][0].getY(),
(GLfloat)triangles[j][0].getZ());
glVertex3f( (GLfloat)triangles[j][3].getX(),(GLfloat)triangles[j][4].getY(),
(GLfloat)triangles[j][5].getZ());
glVertex3f( (GLfloat)triangles[j][2].getX(),(GLfloat)triangles[j][2].getY(),
(GLfloat)triangles[j][2].getZ());
}
glEnd();
Instead of glColor3ub(red, green, blue), try using glColor3ub( rand()%255, rand()%255, rand()%255 ).
Usage:
glBegin(GL_TRIANGLES);
for( int j = 0; j< triangles.size(); j++ )
{
glColor3ub( rand()%255, rand()%255, rand()%255 );
//normalize the triangles first
triangles[j][0].normalize();
triangles[j][1].normalize();
triangles[j][2].normalize();
//call to draw vertices
glVertex3f( (GLfloat)triangles[j][0].getX(),(GLfloat)triangles[j][0].getY(),
(GLfloat)triangles[j][0].getZ());
glVertex3f( (GLfloat)triangles[j][1].getX(),(GLfloat)triangles[j][1].getY(),
(GLfloat)triangles[j][1].getZ());
glVertex3f( (GLfloat)triangles[j][2].getX(),(GLfloat)triangles[j][2].getY(),
(GLfloat)triangles[j][2].getZ());
}
glEnd();
EDIT: Generate, store, and render:
#include <GL/glut.h>
#include <vector>
using namespace std;
struct Vertex
{
Vertex( bool random = false )
{
x = y = z = 0;
r = g = b = a = 0;
if( random )
{
x = rand() % 20 - 10;
y = rand() % 20 - 10;
z = rand() % 20 - 10;
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
a = 1;
}
}
float x, y, z;
unsigned char r, g, b, a;
};
vector< Vertex > verts;
void init()
{
// fill verts array with random vertices
for( size_t i = 0; i < 100; ++i )
{
verts.push_back( Vertex(true) );
verts.push_back( Vertex(true) );
verts.push_back( Vertex(true) );
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10, 10, -10, 10, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// enable vertex and color arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
// set vertex and color pointers
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &verts[0].x );
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &verts[0].r );
// draw verts array
glDrawArrays(GL_TRIANGLES, 0, verts.size() );
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Demo");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
return 0;
}
I'd expect the colors to go from black to med red to med yellow to gray to lt blue grey with the way your if statement is setup (assuming you have at least 600 triangles.) How many tris are you rendering? Also, depending on how your other shaders are setup, textures could get in the way as could anything else if your vertex format is mismatched. Also not sure how glColor3ub() reacts when the blue field goes above 255, which it will in the above code rather quickly. If it truncates the bits, then you would see the colors repeat from yellow to blue grey every 256 triangles after the first 400 .

Resources