I have this project for Win/Linux that has to use OpenGL 1.3 because later on will be ported to another platform that only supports that version.
I have a basic scene with a directional light and using GL_COLOR_MATERIAL but all the polys are rendered completely black and I cannot find what is causing them to render like that. This is the code I'm using to set up OGL and SDL:
static si GaGlSdlSetup()
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) return 0;
GaPrPrintToConsole("\nSDL Properly initiated");
l_sdl_window = SDL_CreateWindow("Window Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_OPENGL
/*SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL*/);
if (l_sdl_window == NULL)
return 0;
GaPrPrintToConsole("\nWindow created");
// Create an OpenGL context associated with the window.
SDL_GLContext glcontext = SDL_GL_CreateContext(l_sdl_window);
if (glcontext == NULL)
return 0;
GaPrPrintToConsole("\nContext created");
return 1;
}
static si GaGlSetup()
{
const float amb = 0.2f;
const float LightAmbient[4] = { amb, amb, amb, 1.0f };
const float LightDiffuse[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
const float LightPosition[4] = { 1.0f, 2000.0f, 2.0f, 0.0f };
glClearColor(0.3, 0.3, 0.8, 0);
glClearDepth(1.0);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 35000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_POLYGON_OFFSET_FILL);
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
return 1;
}
And this is the basic rendering code. I have confirmed the values for the l_red, l_green and l_blue change according to each vertex and are within the range [0,1], and I'm currently rendering polys without any texture:
static si GaGlRender()
{
glClearColor(0.3, 0.3, 0.8, 0);
glClearDepth(1.0);
glBegin(GL_QUADS);
.
.
.
glColor3f(l_red, l_green, l_blue);
glVertex3f(l_mesh_vector_1->vx, l_mesh_vector_1->vy, l_mesh_vector_1->vz);
.
.
.
glColor3f(l_red, l_green, l_blue);
glVertex3f(l_mesh_vector_2->vx, l_mesh_vector_2->vy, l_mesh_vector_2->vz);
.
.
.
glColor3f(l_red, l_green, l_blue);
glVertex3f(l_mesh_vector_3->vx, l_mesh_vector_3->vy, l_mesh_vector_3->vz);
.
.
.
glColor3f(l_red, l_green, l_blue);
glVertex3f(l_mesh_vector_4->vx, l_mesh_vector_4->vy, l_mesh_vector_4->vz);
glEnd();
.
.
.
SDL_GL_SwapWindow(window);
}
Any idea what could be the problem?
EDIT1:
I added the directional light because I could not get any vertex color to be displayed by using only GL_COLOR_MATERIAL, disabling the lights and leaving only GL_COLOR_MATERIAL displays the same result
EDIT2:
Found the culprit: glDisable(GL_TEXTURE_2D) I thought you could leave it on and it would affect only textured polys, but apparently not...
My program refuses to do depth testing. The two sphere objects are always drawn in the order they are created, not according to their position. Sphere alpha is positioned at (0, 0, 1) and Sphere beta is positioned (0, 0, -10), yet OpenGL still draws beta on top of alpha. I set depth test to enabled in my program.
Nothing appears to work. I want OpenGL to do depth test automatically on any objects drawn in the window. Any help or advise would be greatly appreciated. Here is the full code.
#include "GL/freeglut.h"
#include "GL/gl.h"
#include "GL/glu.h"
const int SPHERE_RES = 200;
double Z_INIT = -28.0;
double RADIUS = 2;
double Red[3] = {1, 0, 0};
double Blue[3] = {0, 0, 1};
using namespace std;
/*
* Method handles resize of the window
*/
void handleResize (int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double ratio = (float)w/ (float)h;
gluPerspective(45.0, ratio, 1.0, 100.0);
}
/*
* Color and depth is enabled and in this method
*/
void configureColor(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f); //Set background to white
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear window.
glDepthFunc(GL_ALWAYS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void display (void) {
configureColor();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sun_direction[] = { 0.0, 0.0, -1.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, sun_direction);
GLUquadric* quad = gluNewQuadric();
//first sphere is drawn
glColor3f(Red[0], Red[1], Red[2]);
glPushMatrix();
glLoadIdentity();
glTranslatef(0, 0, Z_INIT);
glTranslatef(0, 0, 1.0);
gluSphere(quad, RADIUS, SPHERE_RES, SPHERE_RES);
glPopMatrix();
//second sphere is supposed to be drawn behind it,
//but it is drawn on top.
glColor3f(Blue[0], Blue[1], Blue[2]);
glPushMatrix();
glLoadIdentity();
glTranslatef(0, 0, Z_INIT);
glTranslatef(0, 0, -10.0);
gluSphere(quad, RADIUS, SPHERE_RES, SPHERE_RES);
glPopMatrix();
free(quad);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); //initializes the GLUT
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow("OpenGL - First window demo");
glutReshapeFunc(handleResize);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I am using Ubuntu 14.04 operating system.
glDepthFunc(GL_ALWAYS);
This is the reason you see the spheres in the order they are drawn. Setting the depth function to GL_ALWAYS simply means all depth tests always pass, for any fragment, be it closer or farther.
You need GL_LESS for the result you want. A fragment having depth lesser than the one in the frame buffer wins; the closer (lesser z) one wins over the farther (greater z) one.
You can either call glDepthFunc(GL_LESS) or comment out glDepthFunc(GL_ALWAYS) since GL_LESS is the default.
I'm loading an Obj model and am trying to draw it like this :
void Game::Update()
{
glViewport(0, 0, 800, 600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(Color::CornflowerBlue.R, Color::CornflowerBlue.G, Color::CornflowerBlue.B, Color::CornflowerBlue.A);
gluPerspective(45.0, 800.0 / 600.0, 1.0, 1000.0);
DrawModel(model);
}
void DrawModel(const Model &model)
{
for (size_t i = 0; i < model.Faces.size(); i++)
{
if (model.Materials.size() > 0)
{
float diffuse[] = { model.Materials[model.Faces[i].Material].Diffuse[0], model.Materials[model.Faces[i].Material].Diffuse[1], model.Materials[model.Faces[i].Material].Diffuse[2], 1.0 };
float ambient[] = { model.Materials[model.Faces[i].Material].Ambient[0], model.Materials[model.Faces[i].Material].Ambient[1], model.Materials[model.Faces[i].Material].Ambient[2], 1.0 };
float specular[] = { model.Materials[model.Faces[i].Material].Specular[0], model.Materials[model.Faces[i].Material].Specular[1], model.Materials[model.Faces[i].Material].Specular[2], 1.0 };
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialf(GL_FRONT, GL_SHININESS, model.Materials[model.Faces[i].Material].Ns);
glColor3f(diffuse[0], diffuse[1], diffuse[2]);
}
int loop = 3;
if (model.Faces[i].IsQuad){
loop = 4;
glBegin(GL_QUADS);
}
else
glBegin(GL_TRIANGLES);
if (model.NormalVertices.size() > 0)
glNormal3f(model.NormalVertices.at(model.Faces[i].Index).X, model.NormalVertices.at(model.Faces[i].Index).Y, model.NormalVertices.at(model.Faces[i].Index).Z);
for (int j = 0; j < loop; j++)
{
//TODO TEXTURE:
if (model.Vertices.size() > 0)
glVertex3f(model.Vertices[model.Faces[i].VerticesIndex[j]].X, model.Vertices[model.Faces[i].VerticesIndex[j]].Y, model.Vertices[model.Faces[i].VerticesIndex[j]].Z);
}
glEnd();
}
}
but I can't see it , because it's not centered in the screen , I know that I can translate it's coordinates , but I want it to show the model in the center without translating how is that possible?
Try gluLookAt() to place the "camera" and tell it where to look at.
You always translate the models to make them visible on screen because only the geometry rendered in the unit cube gets drawn to screen. Using gluLookAt() and gluPerspective() only generates fitting matrices to translate the geometry in the defined frustum to the unit cube.
It seems like you are learning OpenGL. If that is the case I would recommend not learning the old (<3.0) way with glBegin(GL_TRIANGLES) etc. but learn the new (>=3.0) OpenGL version, with VertexArrayObjects and the like, right away. For a start I can recommend this site: OpenGL Tutorials
Currently, I'm drawing a big room, and it's all good and pretty:
But, it's blue, so I figure, ok, I'll just disable lighting first, and then draw the room, re-enable it later, and it'll work out fine, right?
I suppose not... It loses its "depth" entirely.
Can I not simply do:
glDisable(GL_LIGHTING);
glColor3f(51/255.0, 25/255.0,0.0);
drawstuffhere
glEnable(GL_LIGHTING);
Or is this influenced by my initial lighting setup?
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST); // Enable depth testing.
// Turn on OpenGL lighting.
glEnable(GL_LIGHTING);
// Light property vectors.
float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
float lightDifAndSpec0[] = { 1.0, 1.0, 1.0, 1.0 };
float lightDifAndSpec1[] = { 1.0, 1.0, 0.0, 1.0 };
float globAmb[] = { 0.2, 0.2, 0.2, 1.0 };
// Light0 properties.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec0);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec0);
// Light1 properties.
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDifAndSpec1);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightDifAndSpec1);
glEnable(GL_LIGHT0); // Enable particular light source.
glEnable(GL_LIGHT1); // Enable particular light source.
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); // Enable local viewpoint
// Cull back faces.
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
EDIT: Source code: http://pastebin.com/DKGpWiFB
///////////////////////////////////////////////////////////////////////////////////////////
// main.cpp
//
///////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
using namespace std;
//Structures
struct perspectives {
float ex,ey,ez,cx,cy,cz;
int x, y, z;
};
struct coordinates {
float x, y, z;
};
// Globals.
static float a = .1; // Blue ambient reflectance.
static float d = 1.0; // Blue diffuse reflectance.
static float s = 1.0; // White specular reflectance.
static float h = 50.0; // Shininess.
static float e = 0.0; // Blue emittance.
static float t = 0.0; // Quadratic attenuation factor.
static float zMove = 0.0; // z-direction component.
static char theStringBuffer[10]; // String buffer.
static long font = (long)GLUT_BITMAP_8_BY_13; // Font selection.
static bool cameraRotate = false;
struct perspectives camera = {0,0,12,0,0,0,0,1,0};
struct coordinates key = {0,0,11};
// Routine to draw a bitmap character string.
void writeBitmapString(void *font, char *string)
{
char *c;
for (c = string; *c != '\0'; c++) glutBitmapCharacter(font, *c);
}
// Routine to convert floating point to char string.
void floatToString(char * destStr, int precision, float val)
{
sprintf(destStr,"%f",val);
destStr[precision] = '\0';
}
//Routine to draw a ball of light
void drawMoon()
{//TODO
// Light position vectors.
float lightPos[] = { 3, 4, -.2, 1.0 };
glDisable(GL_LIGHTING);
// Light0 and its sphere positioned.
glPushMatrix();
glLightfv(GL_LIGHT1, GL_POSITION, lightPos);
glTranslatef(lightPos[0], lightPos[1], lightPos[2]);
glColor3f(1.0, 1.0, 1.0);
glutSolidSphere(2, 20, 20);
glPopMatrix();
glEnable(GL_LIGHTING);
}
//Routine to draw starry sky
void drawStars()
{
//TODO
}
void drawPumpkin()
{
//TODO
}
void drawKey()
{
//TODO
}
//Routine to draw walls
void drawWalls()
{
//glDisable(GL_LIGHTING);
glColor3f(51/255.0,25/255.0,0);
glPushMatrix();
//glRotatef(0,0,0,1);
glScalef(1,1,3);
glBegin(GL_QUADS);
/* Floor */
glVertex3f(-1,-1,-1);
glVertex3f(-1,-1,1);
glVertex3f(1,-1,1);
glVertex3f(1,-1,-1);
/* Ceiling */
glVertex3f(-1,1,-1);
glVertex3f(1,1,-1);
glVertex3f(1,1,1);
glVertex3f(-1,1,1);
/* Walls */
/* front outer */
/* left half */
glVertex3f(-1,-1,1);
glVertex3f(-.45,-1,1);
glVertex3f(-.45,1,1);
glVertex3f(-1,1,1);
/* right half */
glVertex3f(.45,-1,1);
glVertex3f(1,-1,1);
glVertex3f(1,1,1);
glVertex3f(.45,1,1);
/* top half */
glVertex3f(-1,.5,1);
glVertex3f(1,.5,1);
glVertex3f(1,1,1);
glVertex3f(-1,1,1);
/* end front outer */
/* front door */
//TODO
/* end front door */
/* back inner */
/* left half */
glVertex3f(-1,-1,-1);
glVertex3f(-.45,-1,-1);
glVertex3f(-.45,1,-1);
glVertex3f(-1,1,-1);
/* right half */
glVertex3f(.45,-1,-1);
glVertex3f(1,-1,-1);
glVertex3f(1,1,-1);
glVertex3f(.45,1,-1);
/* top half */
glVertex3f(-1,.5,-1);
glVertex3f(1,.5,-1);
glVertex3f(1,1,-1);
glVertex3f(-1,1,-1);
/* end inner */
glVertex3f(1,1,1);
glVertex3f(1,1,-1);
glVertex3f(1,-1,-1);
glVertex3f(1,-1,1);
glVertex3f(-1,1,1);
glVertex3f(-1,-1,1);
glVertex3f(-1,-1,-1);
glVertex3f(-1,1,-1);
glEnd();
glPopMatrix();
//glEnable(GL_LIGHTING);
}
void drawLight()
{
// Light position vectors.
float lightPos0[] = { 0.0, .75, -.5, 1.0 };
glDisable(GL_LIGHTING);
// Light0 and its sphere positioned.
glPushMatrix();
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
glColor3f(1.0, 1.0, 1.0);
glutWireSphere(0.05, 8, 8);
glPopMatrix();
glEnable(GL_LIGHTING);
}
// Initialization routine.
void setup(void)
{
//Set globals
a = 1- abs(camera.ez/15.0);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST); // Enable depth testing.
// Turn on OpenGL lighting.
glEnable(GL_LIGHTING);
// Light property vectors.
float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
float lightDifAndSpec0[] = { 1.0, 1.0, 1.0, 1.0 };
float lightDifAndSpec1[] = { 1.0, 1.0, 0.0, 1.0 };
float globAmb[] = { 0.2, 0.2, 0.2, 1.0 };
// Light0 properties.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec0);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec0);
// Light1 properties.
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDifAndSpec1);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightDifAndSpec1);
glEnable(GL_LIGHT0); // Enable particular light source.
glEnable(GL_LIGHT1); // Enable particular light source.
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); // Enable local viewpoint
// Cull back faces.
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
// Drawing routine.
void drawScene()
{
// Material property vectors.
float matAmb[] = {0.0, 0.0, a, 1.0};
float matDif[] = {0.0, 0.0, d, 1.0};
float matSpec[] = { s, s, s, 1.0 };
float matShine[] = { h };
float matEmission[] = {0.0, 0.0, e, 1.0};
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// Light quadratic attenuation factor.
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, t);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, t);
//gluLookAt(0.0, ey, ez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
gluLookAt(camera.ex,camera.ey, camera.ez,
camera.cx,camera.cy,camera.cz,
camera.x,camera.y,camera.z);
//gluLookAt(0,0,0,0,0,0,0,1,0);
// Draw light source spheres after disabling lighting.
drawLight();
// Material properties of sphere.
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDif);
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
glMaterialfv(GL_FRONT, GL_SHININESS, matShine);
glMaterialfv(GL_FRONT, GL_EMISSION, matEmission);
// Sphere.
glTranslatef(0.0, 0.0, zMove); // Move the sphere.
//glutSolidCube(1.5);
drawWalls();
drawMoon();
glutSwapBuffers();
}
// OpenGL window reshape routine.
void resize (int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)w/(float)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
int mod = glutGetModifiers();
if (mod!=0)
{
switch(mod)
{
//Shift key
case 1 : cameraRotate=true; break;
//ALT key
case 4 : ; break;
mod = 0;
}
}
switch (key)
{
case 27:
exit(0);
break;
case 'a':
if (a > 0.0) a -= 0.05;
glutPostRedisplay();
break;
case 'A':
if (a < 1.0) a += 0.05;
glutPostRedisplay();
break;
case 'd':
if (d > 0.0) d -= 0.05;
glutPostRedisplay();
break;
case 'D':
if (d < 1.0) d += 0.05;
glutPostRedisplay();
break;
case 's':
if (s > 0.0) s -= 0.05;
glutPostRedisplay();
break;
case 'S':
if (s < 1.0) s += 0.05;
glutPostRedisplay();
break;
case 'e':
if (e > 0.0) e -= 0.05;
glutPostRedisplay();
break;
case 'E':
if (e < 1.0) e += 0.05;
glutPostRedisplay();
break;
case 'h':
if (h > 0.0) h -= 1.0;
glutPostRedisplay();
break;
case 'H':
if (h < 128.0) h += 1.0;
glutPostRedisplay();
break;
case 't':
if (t > 0.0) t -= 0.005;
glutPostRedisplay();
break;
case 'T':
t += 0.005;
glutPostRedisplay();
break;
default:
break;
}
}
// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)
{
if (key == GLUT_KEY_UP){
if(camera.ez - .1 >= 0)
{camera.ez += -0.1;
camera.ex += 0;}
}
if (key == GLUT_KEY_DOWN){
camera.ez += 0.1;
camera.ex += 0;
}
if (key == GLUT_KEY_LEFT){
camera.cx -= .1;
}
if (key == GLUT_KEY_RIGHT){
camera.cx += .1;
}
printf("This is my ez %f\n", camera.ez);
a = 1- abs(camera.ez/5.0);
glutPostRedisplay();
}
// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{
}
// Main routine.
int main(int argc, char **argv)
{
printInteraction();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (600, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow ("scaryRoom.cpp");
setup();
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glutSpecialFunc(specialKeyInput);
glutMainLoop();
return 0;
}
OpenGL is a state based drawing API. Once you've drawn something OpenGL doesn't remember it. Everything happens at the time of drawing, and if there's no lighting setup at the moment of drawing, that's it.
I have no idea why your room comes out blue; I'd have to see the full code for that. However I can give you the advice, that you should not try to "initialize" things at a certain time, and then "live" with that. OpenGL is a state machine, meant to have every attribute that matters being set right before you actually need it. So I suggest you move the lighting and color setup as close to the actual drawing as possible.
Update
You're setting material state in your drawScene function. Those will effect on everything drawn after setting those states until you change them. You intended them to affect only the sphere, but it will affect also the other stuff. Take note that glColor won't have an effect on illuminated drawing, unless you enable and set a so called color material state.
However I strongly suggest you don't bother with the arcane fixed function pipeline at all. You've run into a few pitfalls already :) I suggest you learn modern OpenGL, which also avoids all those weird peculiarities. A very good tutorial can be found at http://arcsynthesis.org/gltut
I am trying to draw spheres at the mouse locations everytime I click the screen.
I wrote a function to get the 3D mouse coordinates, everytime the mouse is clicked. It works like a charm.
Now how can I create spheres at those locations.
void display()
{
...
...
glColor3f(1,0,0)
glutWireSphere(3,100,100);
glTranslatef(X,Y,Z);
}
void MouseFunc()//where the 3D mouse coordinates are recieved
{
double X,Y,Z// where I store the coordinates.
.....
.....
glutDisplayFunc(display);//Because thats where I create the spheres
}
In MouseFunc store the position of the click into a array/list/vector visible to the drawing function, i.e. not in locally scoped variable. Then you call glutPostRedisplay to make GLUT call the display func you registered once in the initialization code using glutDisplayFunc.
In the display function itself you iterate over the array/list/vector and draw a sphere for each element according to the element's data.
Code sample due to request in comment
clicksphere.cc
#include <GL/glut.h>
#include <GL/gl.h>
#include <list>
typedef union v2f_t {
struct {
float x;
float y;
};
float v[2];
} v2f_t;
typedef std::list<v2f_t> v2flist_t;
v2flist_t sphere_centers;
void display(void)
{
int const window_width = glutGet(GLUT_WINDOW_WIDTH);
int const window_height = glutGet(GLUT_WINDOW_HEIGHT);
float const window_aspect = (float)window_width / (float)window_height;
glClearColor(0.5, 0.5, 1.0, 1.0);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(window_aspect > 1.) {
glOrtho(-window_aspect, window_aspect, -1, 1, -1, 1);
}
else {
glOrtho(-1, 1, -1/window_aspect, 1/window_aspect, -1, 1);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat const light_pos[4] = {-1.00, 1.00, 1.00, 0.};
GLfloat const light_color[4] = { 0.85, 0.90, 0.70, 1.};
GLfloat const light_ambient[4] = { 0.10, 0.10, 0.30, 1.};
glLightfv(GL_LIGHT0, GL_POSITION, light_pos),
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
for( v2flist_t::iterator sc = sphere_centers.begin();
sc != sphere_centers.end();
sc++ ) {
glPushMatrix();
glTranslatef(sc->x, sc->y, 0);
glutSolidSphere(0.1, 31, 10);
glPopMatrix();
}
glutSwapBuffers();
}
void mouseclick(
int button,
int state,
int mouse_x,
int mouse_y )
{
int const window_width = glutGet(GLUT_WINDOW_WIDTH);
int const window_height = glutGet(GLUT_WINDOW_HEIGHT);
float const window_aspect = (float)window_width / (float)window_height;
v2f_t const sc = {
(window_aspect > 1.0 ? window_aspect : 1.) *
( ((float)mouse_x / (float)window_width )*2. - 1.),
(window_aspect < 1.0 ? 1./window_aspect : 1.) *
( -((float)mouse_y / (float)window_height)*2. + 1.)
};
sphere_centers.push_back(sc);
glutPostRedisplay();
}
int main(
int argc,
char *argv[] )
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Click to place spheres");
glutDisplayFunc(display);
glutMouseFunc(mouseclick);
glutMainLoop();
return 0;
};
You need to first create the transformation matrix, then draw. In other words:
glTranslatef(X,Y,Z); /* everything from here below would be translated */
glutWireSphere(3,100,100); /* draw with the current transformation matrix */