I'm working on a little example, where I have loaded an object from a wavefront file - and am trying to get my picking right, I've gone over this and a few tutorials about 10 times... but must be missing something. Was wondering if anyone could provide an extra set of eyes.
I've used a saved list to draw the object, which appears fine on the screen... At the moment, when gl_select(x, y) runs, I get a hit no matter what, and if I enable the translate/rotate code (which is currently commented out) - I get no hits what-so-ever.
Relevant code blocks:
// gl_select, is called when the mouse is clicked, with its x and y coords
void gl_select(int x, int y)
{
GLuint buff[256];
GLint hits;
GLint view[4];
//Buffer to store selection data
glSelectBuffer(256, buff);
//Viewport information
glGetIntegerv(GL_VIEWPORT, view);
//Switch to select mode
glRenderMode(GL_SELECT);
//Clear the name stack!
glInitNames();
//Fill the stack with one element
glPushName(0);
//Restric viewing volume
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//Restrict draw area
gluPickMatrix(x, y, 1.0, 1.0, view);
gluPerspective(60, 1, 0.0001, 1000.0);
//Draw the objects onto the screen
glMatrixMode(GL_MODELVIEW);
//Draw only the names in the stack
glutSwapBuffers();
DrawSavedObject();
//Back into projection mode to push the matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
hits = glRenderMode(GL_RENDER);
cout << hits;
//Back to modelview mode
glMatrixMode(GL_MODELVIEW);
}
And the draw functions:
void DrawSavedObject()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1.0,0.0,0.0);
//translate and rotate
//glRotated(rotation,0.0,0.0,1.0);
//glTranslated(7.0, 7.0, 0.0);
//Draw the saved object
glLoadName(7);
glCallList(list_object);
glutSwapBuffers();
}
And where the list is saved:
void SaveDisplayList(){
glNewList(list_object, GL_COMPILE);
glVertexPointer(3, GL_DOUBLE, 3*sizeof(GLdouble), vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLES, verticesSize ,GL_UNSIGNED_INT, triangles);
glDisableClientState(GL_VERTEX_ARRAY);
glEndList();
}
Sorry again for the chunkiness of the code blocks.
A few things to consider here:
OpenGL selection mode is deprecated and never was HW accelerated, except on a few SGI boxes and 3DLabs GPUs.
DisplayLists don't mix with Vertex Arrays.
Why do you call glutSwapBuffers right before drawing your list of saved objects? Makes absolutely no sense at all.
I'm not sure if it's relevant but you're not supposed to store things like glVertexPointer in display lists. From the spec http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml:
Certain commands are not compiled into the display list but are
executed immediately, regardless of the display-list mode. These
commands are glAreTexturesResident, glColorPointer, glDeleteLists,
glDeleteTextures, glDisableClientState, glEdgeFlagPointer,
glEnableClientState, glFeedbackBuffer, glFinish, glFlush, glGenLists,
glGenTextures, glIndexPointer, glInterleavedArrays, glIsEnabled,
glIsList, glIsTexture, glNormalPointer, glPopClientAttrib,
glPixelStore, glPushClientAttrib, glReadPixels, glRenderMode,
glSelectBuffer, glTexCoordPointer, glVertexPointer, and all of the
glGet commands.
This could be what's causing your problem.
Related
I currently have some heat-map data in a database. I was successful in creating painting a heat-map using the same data [using some vertex shading] onto a plane. Example:
Heat-Map Image example for openGL
Name: Capture.jpg
Views: 0
Size: 8.5 KB
ID: 2667
Now, the problem is that I am currently using something like :
glBegin(GL_QUADS);
glColor4ub(point1.color.red(), point1.color.green(), point1.color.blue(), transparency);
glVertex3d(point1.xCood - 750, point1.yCood - 750, 0);
glColor4ub(point2.color.red(), point2.color.green(), point2.color.blue(), transparency);
glVertex3d(point2.xCood - 750, point2.yCood - 750, 0);
glColor4ub(point3.color.red(), point3.color.green(), point3.color.blue(), transparency);
glVertex3d(point3.xCood - 750, point3.yCood - 750, 0);
glColor4ub(point4.color.red(), point4.color.green(), point4.color.blue(), transparency);
glVertex3d(point4.xCood - 750, point4.yCood - 750, 0);
glEnd();
And what this does [at least in my theory] is that it creates another layer over the existing plane. This causes code on clicking the plane below to be rendered useless. Changing the existing code too much is not an option right now as I do not have access to edit it. I found that if I draw a texture (rather than color a plane) on the old plane, the code stays working.
Example(texture tile just defines number of repetitions required, value is 1 in this case):
glBegin(GL_QUADS);
glTexCoord2d(0.0, textureTile);
glVertex3d(gridRect.left(), gridRect.top(), 0.0);
glTexCoord2d(0.0, 0.0);
glVertex3d(gridRect.left(), gridRect.bottom(), 0.0);
glTexCoord2d(textureTile, 0.0);
glVertex3d(gridRect.right(), gridRect.bottom(), 0.0);
glTexCoord2d(textureTile, textureTile);
glVertex3d(gridRect.right(), gridRect.top(), 0.0);
glEnd();
That said, I was only successful in loading a texture from an image I made. Since the image is suppose to be calculated and painted during run time, I tried making an image from the data to load as a texture.
I used the Qt API functionality for achieving the same. I failed to recreate the same image. Might I be suggested a way to create a texture image from data owned.
Thanks
Sorry for the late answering(in case someone else wanted the answer).
I found the answer to be the use of QOpenGLFramebufferObject.
Final code looks something like:
glViewport(0, 0, VIEW_PORT_SIZE, VIEW_PORT_SIZE);
QOpenGLFramebufferObject fbObject(VIEW_PORT_SIZE, VIEW_PORT_SIZE);
fbObject.bind();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//Switch to Ortho Mode
glMatrixMode(GL_PROJECTION); // Select Projection
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
glOrtho(left, right, bottom, top, -100, 100); // Select Ortho Mode
glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
//Initialize variables
SPointData point1, point2, point3, point4;
//Paint on buffer
//.................<some painting task>................
//Switch to perspective mode
glMatrixMode(GL_PROJECTION); // Select Projection
glPopMatrix(); // Pop The Matrix
glMatrixMode(GL_MODELVIEW); // Select Modelview
glPopMatrix(); // Pop The Matrix
fbObject.release();
return fbObject.toImage();
So, I've been trying to rotate a single object in an OpenGL/GLUT environment.
After going through several questions on SO and the like, I've written what appears to be correct code, but no dice. Does anyone know how to make this work?
PS: I've tried changing the GLMatrixmode to Projection, but that just shows a black screen. Same thing happens if I use glLoadIdentity().
Here's my rendering code
void display()
{
preProcessEvents();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(Camera::position.x, Camera::position.y, Camera::position.z,
Camera::position.x+Math::sind(Camera::rotationAngles.x)*Math::cosd(Camera::rotationAngles.y),
Camera::position.y+Math::cosd(Camera::rotationAngles.x),
Camera::position.z+Math::sind(Camera::rotationAngles.x)*Math::sind(Camera::rotationAngles.y),
0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0);
glVertex3f(-1, 0,-3);
glColor3f(0, 1, 0);
glVertex3f(0.0f, 2.0f,-3);
glColor3f(0, 0, 1);
glVertex3f(1.0f, 0.0f,-3);
glEnd();
glBindTexture(GL_TEXTURE_2D, tex->textureID);
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
glTexCoord2f(100, 100);
glVertex3f(100,0,100);
glTexCoord2f(-100, 100);
glVertex3f(-100,0,100);
glTexCoord2f(-100,-100);
glVertex3f(-100,0,-100);
glTexCoord2f(100,-100);
glVertex3f(100,0,-100);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
object1.draw();
glTranslatef(-10.0, 10.0, 0.0);
glBindTexture(GL_TEXTURE_2D, tex2->textureID);
gluQuadricTexture(quad,1);
gluSphere(quad,10,20,20);
glBindTexture(GL_TEXTURE_2D, 0);
//RELEVANT CODE STARTS HERE
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(190, 0.0, 0.0, 1.0);
glPopMatrix();
glutSwapBuffers();
}
Are you aware what glPushMatrix and glPopMatrix do? They save and restore the "current" matrix.
By enclosing your rotation in that and then doing no actual drawing operation before restoring the matrix the entire sequence of code beginning with //RELEVANT CODE STARTS HERE is completely pointless.
Even if you did not push/pop, your rotation would only be applied the next time you draw something. Logically you might think that would mean the next time you call display (...), but one of the first things you do in display (...) is replace the current matrix with an identity matrix (line 3).
In all honesty, you should consider abandoning whatever resource you are currently using to learn OpenGL. You are using deprecated functionality and missing a few fundamentals. A good OpenGL 3.0 tutorial will usually touch on the basics of transformation matrices.
As for why changing the matrix mode to projection produces a black screen, that is because the next time you call display (...), gluLookAt operates on the projection matrix. In effect, you wind up applying the camera transformation twice. You should really add glMatrixMode (GL_MODELVIEW) to the beginning of display (...) to avoid this.
You do the rotation (and reset it with glPopMatrix) after you draw, do the rotation code before the glBegin/glEnd calls.
Or just move to the shader based pipeline and manage you own transformation matrices.
I have a 3D scene with an object and I would like to save a view of that object that is different from the one of the current screen I look at.
So I thought I'd just have to do something like this (pseudo code):
PushMatrix()
LoadIdentity()
TranslateAndRotate()
gluperspective()
setViewport()
DrawScene()
saveScreenshot()
PopMatrix()
But I only get a picture of the current view of my camera, not the one I specified.
Did I forget something?
EDIT:
Because of the answer below, I tried the following code:
void ScenePhotograph(GLubyte* Target, float *Translation, float RotationAroundY)
{
glMatrixMode(GL_PROJECTION);
gluPerspective(54.0f, (GLfloat)openGLControl1->Width / (GLfloat)openGLControl1->Height, 1.0f, 3000.0f);
glViewport(0,0,openGLControl1->Width, openGLControl1->Height);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(Translation[0],Translation[1],Translation[2]);
glRotatef(RotationAroundY, 0,1,0);
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glReadPixels(0, 0, openGLControl1->Width, openGLControl1->Height, GL_RGB, GL_UNSIGNED_BYTE, Target);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
cam->SetView();
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glutSwapBuffers();
}
That is giving me an access violation at glutSwapBuffers();
Any Ideas?
First, make sure you are not mixing diferent matrix in your code. To get a screenshot, you will need to position your camera exactly as you normally do to view it on your sccreen, but, before you swap the buffers, you read the pixels from the current framebuffer and store it as an image.
So, what you need is something like this:
glMatrixMode(GL_PROJECTION);
gluPerspective();
glMatrixMode(GL_MODELVIEW);
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
screenShot();
// do again to set your camera to correct position
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
swapBuffers();
as you can see, screenShot take care of reading the pixels from your current framebuffer and save it as an image. So do everything again to position your camera to the correct place
I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.
Hi I got 4 viewports and one large that I can switch between now I got an object namely the camera and the cameras target position that I show with rendering a sphere at those locations. I want to show the cameras position in 3 of my viewports but not in the last which is the camera display but at the moment I got an all or nothing scenario.
void display(int what)
{
if(what==5){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==1){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,0,0,0,1,0,0);}
if(what==3){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==4){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(185,75,25,0,28,0,0,1,0);}
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
////gluLookAt(cos(shared.time) * shared.distance, 10, sin(shared.time) * shared.distance, 0, 0, 0, 0, 1, 0);
////ca.orbitYaw(0.05);
//ca.lookAt();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawScene(); // scene that all views should render
drawCamera(); / camera position that only certain views should render
glutSwapBuffers();
}
I'm thinking that perhaps I could do one sweep for first the 3 viewports and then call glutSwapBuffers() and then do the other viewport without the camera position but some stuttering I previously had was traced to glutSwapBuffers() being called for each viewport so I guess there has to be another way only that I cant figure it out.
You have to render everything before swapping buffers.
As you do it - it is not going to work. Actually, it will work, but not you want.
EDIT
To render to a texture take a look into one of the links here.
After changing a view, render the image for the specific view to a texture. Then for the final image, set the final view and render all 3 textures. Only when the final image is rendered, swap buffers.
On the 2nd thought, it would be much better if you could set the vertices of all objects to render and render whole image in one pass.