I am drawing a quad in OpenGL and then using glReadPixels to access the depth buffer. But, the problem is I'm always getting 1 from all the position of the OpenGL window. For example, for zbuffer[0][0] (please see the code below), the value should be 0, because that part of the window has no object. Again, for zbuffer[639][470], the value should also be 0, but I am receiving 1 for both the case.
Could you please point me what I am doing wrong here?
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include <fstream>
using namespace std;
void display ( ) // Create The Display Function
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluLookAt(0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,-1.0 ,0.0 ,1.0 ,0.0);
glBegin(GL_QUADS);
glColor3f(0.813205,0.813205,0.813205);
glVertex3f(-0.389662380802125,0.249152038469432, -1.12528215173346); // top left corner
glColor3f(0.309385,0.309385,0.309385);
glVertex3f(0.433401472883409,0.272288002674917, -0.923754348668237); // top right corner
glColor3f(0.288292,0.288292,0.288292);
glVertex3f(0.441173907261717,-0.296124431126115, -0.915317251508196);// bottom right corner
glColor3f(0.74028,0.74028,0.74028);
glVertex3f(-0.388657135983495,-0.317680965994535, -1.09611219327051); // bottom left corner
glEnd();
GLfloat zbuffer[640][480];
glReadPixels(0,0,640,480,GL_DEPTH_COMPONENT,GL_FLOAT, zbuffer);
cout<<"Depth1:"<<zbuffer[0][0]<<endl;
cout<<"Depth2:"<<zbuffer[639][470]<<endl;
glFlush();
glutSwapBuffers ( );
}
void reshape ( int w, int h ) // Create The Reshape Function (the viewport)
{
glViewport(0 ,0 ,(GLsizei)w,( GLsizei)h);
glMatrixMode (GL_PROJECTION );
glLoadIdentity ( );
gluPerspective(48.6f, (GLfloat) 640 / 480, 0.01f, 1000.0f);
glMatrixMode (GL_MODELVIEW) ;
}
void keyboard ( unsigned char key, int x, int y ) // Create Keyboard Function
{
switch ( key ) {
case 27: // When Escape Is Pressed...
exit ( 0 ); // Exit The Program
break; // Ready For Next Case
default: // Now Wrap It Up
break;
}
}
void mouse(int button, int state, int x, int y) {
float mx = x ;
float my = y ;
// ox = (mx/320-1.0);
// oy = -(my/240 -1.0);
switch(button){
case GLUT_LEFT_BUTTON:
if(state==GLUT_DOWN){
printf("%f,",mx);
printf("%f\n",my);
}
break;
}
}
int main ( int argc, char** argv )
{
glutInit ( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (640, 480);
glutInitWindowPosition(0, 0);
glutCreateWindow ( "My Window" ); directory as title)
glutReshapeFunc ( reshape ) ;
glutDisplayFunc ( display ); // Matching Earlier Functions To Their Counterparts
glutKeyboardFunc ( keyboard );
glutMouseFunc(mouse);
glutMainLoop ( ); // Initialize The Main Loop
return 0;
}
And here is the object drawn in OpenGL:
For example, for zbuffer[0][0] (please see the code below), the value should be 0, because that part of the window has no object.
No, it shouldn't. THe default glClearDepth value is 1.0, so glClear( GL_DEPTH_BUFFER_BIT) sets every pixel in the depth buffer to 1.0. This also makes sense because using the dfeault conventions, the near plane is mapped to z=0 in window space, and the far plane to z=1, and the depth test is set to GL_LESS, so that fragments will pass which are nearer that what is currently drawn at that position.
Related
Hey everyone so I was given this code by my professor to look over for using videocapture with OpenCV but it's not wokring for me. The proffessor was able to run it in class and he used his laptop camera, but the same code is not working for me. Is there anything wrong with this code? Or do I have to do some sort of initial setup with my laptop camera using openCV? Any help would be appreciated.
#include <opencv2/opencv.hpp> //for OpenCV 3.x
#include <opencv/highgui.h> //for OpenCV 3.x
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/gl.h>
#include <GL/glut.h>
#endif
#include <cstdio>
cv::VideoCapture *cap = NULL;
int width = 640;
int height = 480;
cv::Mat image;
/*------------ function displaying x,y,z coordinate system ----------*/
void drawAxes(float length)
{
glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT) ;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
glDisable(GL_LIGHTING) ;
glBegin(GL_LINES) ;
glColor3f(1,0,0) ; //x: red
glVertex3f(0,0,0) ;
glVertex3f(length,0,0);
glColor3f(0,1,0) ; //y: blue
glVertex3f(0,0,0) ;
glVertex3f(0,length,0);
glColor3f(0,0,1) ; //z: green
glVertex3f(0,0,0) ;
glVertex3f(0,0,length);
glEnd() ;
glPopAttrib() ;
}
/*---------------- display --------------*/
void display()
{
glClear( GL_COLOR_BUFFER_BIT ); // clear window
// cv::Mat stores data, has to flip it before displaying it
cv::Mat tempimage;
/*
flip(image, image, 0); // vertically
flip(image, image, +1); // horizontally
// or 90 degree clock wise
transpose(image, image);
flip(image, image, +1);
// or 90 degree counter clock wise
transpose(image, image);
flip(image, image, 0);
*/
cv::flip(image, tempimage, 0);
glDrawPixels(tempimage.size().width,tempimage.size().height,GL_BGR,GL_UNSIGNED _BYTE,tempimage.ptr());
//set viewport
glViewport(0, 0, tempimage.size().width, tempimage.size().height);
//set projection matrix using intrinsic camera params
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/*
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
*/
gluPerspective(60, tempimage.size().width*1.0/tempimage.size().height, 1, 20);
//you will have to set modelview matrix using extrinsic camera params
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/*gluLookAt (cameraX, cameraY, cameraZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ);
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/ gluLookAt.xml
*/
gluLookAt(3, 3, 3, 0, 0, 0, 0, 1, 0); //(upX, upY, upZ) = (0, 1, 0) always
//now that the camera params have been set, draw your 3D shapes
//first, save the current matrix
glPushMatrix();
//move to the position where you want the 3D object to go
glTranslatef(0, 0, 0); //this is an arbitrary position for demonstration
//you will need to adjust your transformations to match the positions where
//you want to draw your objects(i.e. chessboard center, chessboard corners)
glutSolidTeapot(0.2);
glutSolidSphere(.3, 100, 100);
drawAxes(1.0);
glPopMatrix();
// show the rendering on the screen
glutSwapBuffers();
// post the next redisplay
glutPostRedisplay();
}
void reshape( int w, int h )
{
// set OpenGL viewport (drawable area)
glViewport( 0, 0, w, h );
}
void mouse( int button, int state, int x, int y )
{
if ( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
{
}
}
void keyboard( unsigned char key, int x, int y )
{
switch ( key )
{
case 'q':
// quit when q is pressed
exit(0);
break;
default:
break;
}
}
void idle()
{
// grab a frame from the camera
(*cap) >> image;
}
int main( int argc, char **argv )
{
int w,h;
if ( argc == 1 ) {
// start video capture from camera
cap = new cv::VideoCapture(0);
} else if ( argc == 2 ) {
// start video capture from file
cap = new cv::VideoCapture(argv[1]);
} else {
fprintf( stderr, "usage: %s [<filename>]\n", argv[0] );
return 1;
}
// check that video is opened
if ( cap == NULL || !cap->isOpened() ) {
fprintf( stderr, "could not start video capture\n" );
return 1;
}
// get width and height
w = (int) cap->get( CV_CAP_PROP_FRAME_WIDTH );
h = (int) cap->get( CV_CAP_PROP_FRAME_HEIGHT );
// On Linux, there is currently a bug in OpenCV that returns
// zero for both width and height here (at least for video from file)
// hence the following override to global variable defaults:
width = w ? w : width;
height = h ? h : height;
// initialize GLUT
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowPosition( 20, 20 );
glutInitWindowSize( width, height );
glutCreateWindow( "OpenGL / OpenCV Example" );
// set up GUI callback functions
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutMouseFunc( mouse );
glutKeyboardFunc( keyboard );
glutIdleFunc( idle );
// start GUI loop
glutMainLoop();
return 0;
}
EDIT:
I think i know the problem. It's because Im running a VM and the VM doesnt detect the camera. But how would I run this code with a video file? I also tried that but it didnt work.
The triangle doesn't appear on the screen.
I am using Dev c++ 4.9.9.2(i know that you don't like it, but for me it's still the best :) with free glut.
Here's the code:
#include <GL/glut.h>
void display(){
glClear ( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
glBegin ( GL_TRIANGLES );
glColor3f ( 0.0, 1.0, 0.0);
glVertex2f (-0.5,-0.5);
glVertex2f (0.5,-0.5);
glVertex2f (0.0, 0.5);
glEnd();
}
void reshape ( int width, int height ){
glViewport ( 0, 0, width, height );
}
void initOpenGL(){
glClearColor ( 1.0, 0.1, 0.0, 1.0 );
}
int main (int argc, char **argv){
glutInit ( &argc , argv );
glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
glutInitWindowSize ( 500, 500 );
glutInitWindowPosition ( 100, 100 );
glutCreateWindow ( "OpenGl" );
initOpenGL();
glutDisplayFunc ( display );
glutIdleFunc ( display );
glutReshapeFunc ( reshape );
glutMainLoop ();
return 0;
}
Let's take a closer look at your display function:
display()
{
glClear();
glutSwapBuffers();
drawTriangle();
}
glClear() clears the backbuffer to a constant color. glutSwapBuffers() swaps frontbuffer and backbuffer. This will show the current content of the backbuffer (which is just the clear color) on the screen. The content of the new backbuffer will be undefined. Every draw call will draw to the backbuffer.
As you see, the program has never a chance to display something other than the clear color on screen. Just move glutSwapBuffers() to the end of the function:
display()
{
glClear();
drawTriangle();
glutSwapBuffers();
}
And please pick a more recent tutorial. You are using the fixed function pipeline, which has been deprecated for about 10 years. You can recognize it by calls like glBegin() or glVertex3f(). There is no reason to learn something that is dying (or already dead on some platforms).
I want to make a space invader game in opengl. So I thought of creating the enemies using triangles. Before making the game, I want to try out my hand in animation. I have triangle. i want to translate it left upto some point with animation(i.e, triangle is translated after some interval of time. It should look as if it is moving).After reaching some point in the left, I want to translate it back to the same position or some distances right. The process should go on till the screen is open. I used sleep function. But it is not working. No animation is shown. Only the translated triangle is drawn at different translated position. Help me.
Here is my code-
#include "windows.h"
#include <gl/glut.h>
#include<stdio.h>
void init( void )
{
printf( "OpenGL version: %s\n", (char*)glGetString(GL_VERSION));
printf( "OpenGL renderer: %s\n", (char*)glGetString(GL_RENDERER));
//Configure basic OpenGL settings
glClearColor(1.0, 1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,640.0,0.0,480.0);
glColor3f(1.0,0.0,0.0);
glPointSize(3);
}
void house(int x, int y,int z)
{
glPushMatrix();
glTranslatef(x, y,z);
glBegin (GL_LINES);
glVertex2i (0,30);
glVertex2i (15,60);
glVertex2i (15,60);
glVertex2i (30,30);
glVertex2i (30,30);
glVertex2i (0,30);
glEnd();
//Sleep(200);
glPopMatrix();
//glutSwapBuffers();
}
// Main drawing routine. Called repeatedly by GLUT's main loop
void display( void )
{
//Clear the screen and set our initial view matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
int i;
for(i = 10; i < 350; i = i + 50)
{
house(i,20,0);
Sleep(200);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glFlush();
}
// Entry point - GLUT setup and initialization
int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode (GLUT_DEPTH | GLUT_SINGLE| GLUT_RGB);
glutInitWindowSize (800, 600);
glutInitWindowPosition (100, 100);
glutCreateWindow( "OpenGL Test" );
glutDisplayFunc( display );
init();
glutMainLoop();
return 0;
}
In main() you have declared your display() as display callback function. GLUT will call this function either when it determines that the window need to be redrawn or when it is told to redraw it for example by the function glutPostRedisplay().
The display function is expected to call redraw the windows at a specific point in time. The glFlush() will force the execution of the GL commands.
The problem is that your animation loop is inside the redraw function and glFlush() is called at the end, showing the result at once. And you don't tell GLUT to redraw the windows. This is why you don't seee the animation.
For the purpose of the tutorial, I propose you to define a global variable for the initial position of the house drawing. Of course, you'll have to improve this as soon as you understood how all this works.
static int pos = 10; // temporary work around, just for the demo
Then define a timer function, that gets called after a time interval. This will be the core of your animation, organizing the moving, and the redrawing of the window by calling glutPostRedisplay() :
void timerfunc(int value) // handle animation
{
pos += 50; // update the postion
if (pos<350) // as in your originial loop
glutTimerFunc(200, timerfunc, 0); // plan next occurence
glutPostRedisplay(); // redraw the window
}
Activate your timer function, in main() just before launching glutMainLoop():
glutTimerFunc(200, timerfunc, 0); // call a timer function
glutMainLoop(); // this call is already in your code
Your display function can then be changed into:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
house(pos, 20, 0); // draw the house at its last calculated position
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glFlush();
}
Then it works in animated modus !
Using SCREEN_WIDTH = 1200, and SCREEN_HEIGHT = 800.
First, I draw a box to the screen at (x = 0, y = 0, w = 40, h = 40);
Then I use the handleMouse Function to return the x and y coordinates of where the mouse is clicked.
The problem is, when the program starts in non-Maximized windowed mode, when I click on (What appears to be) the very bottom right corner of the box the coordinates returned are x = 40, y = 32. When I think it should be returning x = 40, y = 40.
I don't know whether the problem is if its not being drawn right, or the functions is returning the wrong x/y.
I believe I understand how openGL rendering, transformation and glOrth work, but I could be completely wrong. I have seen a few suggestions online saying that the Windows Decor(Using windows 7) can cause this problem, but have done very little explaining and provided no solution.
This is my entire source code. I have stripped off everything from my game down to the basics, and the problem still persists :( . I added two pictures so people could see my problem. In NON-MAXIMIZED WINDOW(the top picture), when clicking the bottom-right corner, the coordinates returned are 41,32; The y coordinate is smaller than it should be. And in the MAXIMIZED WINDOW(the bottom picture), when clicking the same corner, It returns the correct coordinates 40, 40. These results occur for both my original source code and genpfault's suggested code.
//Turns out I can't post Pictures :(, links instead.
non-Maximized Windowed!
Maximized Windowed!
main.cpp
int main( int argc, char* args[] )
{
//Initialize FreeGLUT
glutInit( &argc, args );
//Create OpenGL 2.1 context
glutInitContextVersion( 2, 1 );
//Create Double Buffered Window
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
glutCreateWindow( "OpenGL" );
//Do post window/context creation initialization
if( !initGL() )
{
printf( "Unable to initialize graphics library!\n" );
return 1;
}
//initGame();
glutMouseFunc(handleMouse);
glutDisplayFunc( render );
glutMainLoop();
return 0;
}
Functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
bool initGL();
void render();
void handleMouse(int button, int state, int x, int y);
#endif
Functions.cpp
bool initGL()
{
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
//cout <<"Error initializing OpenGL! " << gluErrorString( error ) << endl;
return false;
}
return true;
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
glColor3f(1.f,1.f,1.f);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(0, 41);
glVertex2f(41, 41);
glVertex2f(41, 0);
glEnd();
glutSwapBuffers();
}
void handleMouse(int button, int state, int x, int y)
{
std::cout << x << '\t' << y << std::endl;
}
constants.h
const int SCREEN_WIDTH = 1200;
const int SCREEN_HEIGHT = 800;
This works fine for me on Windows 7 on Aero and Classic:
#include <GL/glut.h>
#include <iostream>
void render()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho(0, w, h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3ub( 255, 255, 255 );
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(41, 0);
glVertex2f(41, 41);
glVertex2f(0, 41);
glEnd();
glutSwapBuffers();
}
void handleMouse(int button, int state, int x, int y)
{
std::cout << x << '\t' << y << std::endl;
}
int main( int argc, char* args[] )
{
glutInit( &argc, args );
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "OpenGL" );
glutMouseFunc(handleMouse);
glutDisplayFunc( render );
glutMainLoop();
return 0;
}
Most notably I added the runtime glutGet() window size queries to render().
Try moving the quad away from the edge of the display because when I tryed to do something like that the edge of the screen was very odd
glBegin(GL_QUADS);
glVertex2f(20,20);
glVertex2f(20, 61);
glVertex2f(61, 61);
glVertex2f(61, 20);
glEnd();
I'm doing 2D drawing in a glut window, and I'm having trouble making the window resize properly.
My glutDisplayFunc and glutReshapeFunc are below. As it is, the drawing disappears when the window is resized. If I delete the glClear() from displayFunc(), new pixels don't "initialize" and there are clipping problems. How do I fix this?
glutDisplayFunc:
void displayFunc() {
glDisable( GL_DEPTH_TEST );
glClear( GL_COLOR_BUFFER_BIT );
glPointSize ( 3.0 );
glFlush();
}
glutReshapeFunc:
void windowReshapeFunc( GLint newWidth, GLint newHeight ) {
glViewport( 0, 0, newWidth, newHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, GLdouble (newWidth), 0, GLdouble (newHeight) );
windowWidth = newWidth;
windowHeight = newHeight;
}
I'd try adding a call to glutPostRedisplay() around the end of your reshape function.
This is basic template that I use...
#include <GL/glut.h>
#include <stdio.h>
#include <stdarg.h>
#define WINDOW_WIDTH 300
#define WINDOW_HEIGHT 300
// current Window width and height
int win_width, win_height;
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
// write your code here
//
//
glutSwapBuffers();
}
void on_resize(int w, int h)
{
win_width = w;
win_height = h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-w / 2, w / 2, -h / 2, h / 2, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
display(); // refresh window.
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("basic resize template");
glutDisplayFunc(display);
glutReshapeFunc(on_resize);
glutMainLoop();
}
You can not call gluOrtho2D twice with the same window, it will break the graphics and so nothing shows up. You would have to init window size and set Ortho to the size of the screen (current display resolution), then draw relative to the size of the window.
I guess your code does not draw everything on scene in display func, you see, if no events occcur ever you have to call display one time and in the first time it has your drawing. But your problem rises when there is an event which says the window is resized! try putting your drawing part in display function. Like so,
void displayFunc() {
glDisable( GL_DEPTH_TEST );
glClear( GL_COLOR_BUFFER_BIT );
glPointSize ( 3.0 );
glBegin(GL_POINTS);
{
//Blah blah blah some points here which you expect to draw
}
glEnd();
glFlush();
}
Please post the full code if this was not helpful.
You're not setting the matrix mode back to GL_MODELVIEW at the end of your reshape function.
void reshape(int width, int height) {
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, GLdouble (width), 0, GLdouble (height) );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
It's hard to say if there's something else in your display function without seeing more code. I hope that helps.