I am in a class in which we will be learning OpenGL. The professor is using Visual Studio, but that isn't working too well with my install of Parallels, so I just decided to use XCode (which I prefer anyway). I have got basic example code working, but I am having issues running the example that the professor gave us. Here it is:
#include <glut.h> //must be included for OpenGL
#include <gl\gl.h> //must be included for OpenGL
#include <time.h> //must be included for time functions
#include <iostream> //must be included for console input/output
using namespace std;
#define WINDOW_WID 800
#define WINDOW_HEI 600
int randomPx, randomPy;
/////////////////////////////////////////
void myInit(void)
{
randomPx = 400;
randomPy = 300;
glClearColor (1.0, 1.0, 1.0, 0.0); // set background color to black
glShadeModel (GL_FLAT);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT); // clear the screen
glColor3f(1,0,0); //set the drawing color
glPointSize(10); //set the point size
glBegin(GL_POINTS);
glVertex2d(randomPx,randomPy); //Set the position of the vertex
glEnd();
glutSwapBuffers (); //put everything on your screen
}
void myReshape ( int w, int h)
{
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION); // set "camera type"
glLoadIdentity (); // clear the matrix
glOrtho(0.0, w, 0.0, h, -1.0, 1.0); // viewing transformation
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
void Animation()
{
srand(time(NULL)+rand()); //set the seed for your rand function
randomPx = rand()%WINDOW_WID;
randomPy = rand()%WINDOW_HEI;
Sleep(200); //put the program to sleep for 200 ms
myDisplay();
}
void myMouse(int button, int state, int x, int y)
{
y = WINDOW_HEI - y;
switch (button)
{
case GLUT_LEFT_BUTTON: //when left mouse button is clicked
if (state == GLUT_DOWN)
{
cout << "When mouse is up, animation starts\n";
}
else if(state == GLUT_UP)
{
glutIdleFunc(Animation); //do Animation when idle
}
break;
case GLUT_RIGHT_BUTTON: //when right mouse button is clicked
if (state == GLUT_DOWN)
{
glutIdleFunc(NULL); //do nothing when idle
}
break;
case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN)
{
exit (-1); //exit your program
}
break;
}
myDisplay();
}
void myMotion(int x, int y)
{
y = WINDOW_HEI - y;
myDisplay();
}
void myKeyboard(unsigned char key, int x, int y)
{
//TODO
myDisplay();
}
/*
* Request double buffer display mode.
* Register mouse input callback functions
*/
int main(int argc, char** argv)
{
glutInit(&argc, argv); // initialize the toolkit
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); // set display mode
// glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // set display mode
glutInitWindowSize (WINDOW_WID, WINDOW_HEI); // set screen window size
glutInitWindowPosition (100, 100); // set window position on screen
glutCreateWindow (argv[0]); // open the screen window
myInit ();
glutDisplayFunc(myDisplay); // register redraw function
glutReshapeFunc(myReshape); // register reshape function
glutMouseFunc(myMouse); //GLUT provides a way for you to register the function that will be responsable for processing events generated by mouse clicks.
glutMotionFunc(myMotion); //There are two types of motion that GLUT handles: active and passive motion. Active motion occurs when the mouse is moved and a button is pressed.
glutKeyboardFunc(myKeyboard);
//glutPassiveMotionFunc(myPassiveMotion); //Passive motion is when the mouse is moving but no buttons are pressed. If an application is tracking motion, an event will be generated per frame during the period that the mouse is moving.
//glutEntryFunc(processMouseEntry); //GLUT is also able to detect when the mouse leaves or enters the window region. A callback function can be registered to handle these two events.
glutMainLoop(); // go into a perpetual loop
return 0;
}
I took out the imports statements, and replaced them with the imports for example XCode OpenGL code:
#include <iostream>
#include <GLUT/glut.h>
#include <time.h>
And I don't get any error messages, but when I run the application, and click on the window, it does not start the animation it is supposed to. (I know it works, because in Visual Studio on every other computer in the class it worked fine.)
It does register the click on the screen by printing out: "When mouse is up, animation starts"
But after that, it just gives me the Spinning Beachball of Death until I stop it from running via XCode. So is there something else I have to adjust to get this working?
First of all, why are you using a backslash for your import gl.h? Secondly, you should link your code to the GLUT and OpenGL library, so you should include/import them as OpenGL/gl.h and GLUT/glut.h. But your main problem here is the sleep function. It doesn't exist on macs and thus, your code crashes when it tries to animate. Use [NSThread sleepForTimeInterval:0.2] instead if you want to wait for 200 ms. But you will have to change your file extension to .mm in order to use objective-c code and also import the Foundation library to use the NSThread class.
About the sleep.. use
#include <unistd.h> //FROM C
and use
sleep(0.2)
wich is at seconds.. so 2000 miliseconds = 0.2 seconds.. so
just switch from sleep(2000) to sleep(0.2)
Related
I've found an error in my code through std::cout-ing some of my small float values. I'm quite new to C++ but I don't think this is a feature on-purpose.
These values are between 1 and -1 and resemble a set of normalized coordinates I need for my OpenGL transformations.
I'm using SDL to get my windows coordinates and I offset each of them through:
...
case SDL_MOUSEMOTION:
{
xMouse=(event.motion.x-halfX)/(halfX);
yMouse=(event.motion.y-halfY)/(halfY);
std::cout<<"Mouse at: "<<xMouse<<','<<yMouse<<'\n';
}
...
halfX and halfY are half of my window's height and width, this is because I want my (0,0) to be at the centre.
Here are some prints for this cout:
Mouse at: 0.794444,-0.857639
Mouse at: 0.805556,-0.888889
Mouse at: 0.830556,-0.934028
Mouse at: 0.838889,-0.951389
Mouse at: 0.844444,-0.961806
Mouse at: 0.844444,-0.96875
Mouse at: 0.85,-0.972222
Mouse at: 0.852778,-0.979167
Mouse at: 0.855556,-0.982639
Mouse at: 0.861111,-0.986111
Mouse at: 0.863889,-0.989583
Mouse at: 0.866667,-0.993056
Mouse at: 0.869444,-0.996528
Mouse at: 0.872222,-1
Mouse at: 0.877778,-1
Looks fine. But when I pass the values into a function like this:
void draw(Ship &_player, GLfloat _rot,int _xMouse, int _yMouse)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
std::cout<<"From draw(Ship,GLfloat,int,int):"<<'\n'<<"Mouse at: "<<_xMouse<<','<<_yMouse<<'\n';
_player.followMouse(_xMouse,_yMouse);
}
And I get my parameter values as:
From SDL_MOUSEMOTION:
Mouse at: 0.688889,-0.982639
From draw(Ship,GLfloat,int,int):
Mouse at: 0,0
From SDL_MOUSEMOTION:
Mouse at: 0.694444,-0.993056
From draw(Ship,GLfloat,int,int):
Mouse at: 0,0
From SDL_MOUSEMOTION:
Mouse at: 0.713889,-1
From draw(Ship,GLfloat,int,int):
Mouse at: 0,-1
I haven't edited the values before the the function call, it looks a bit like my compiler trying to round down the values. But I'm not sure, and how to fix it.
here's my main if we need it
#ifdef WIN32
#include <Windows.h>
#endif
#if defined (__linux__) || defined (WIN32)
#include <GL/gl.h>
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#endif
#include <iostream>
#include <cstdlib>
#include "GameObjects.h"
#include "Ship.h"
#include "Camera.h"
#include "SDLOpenGL.h"
#undef main
// function to init the basic OpenGL scene for this demo
void initOpenGL();
// function to render our scene.
void draw(Ship &_player,GLfloat _rot,int _xMouse, int _yMouse);
int main(int argc, char *argv[])
{
int winXLeng=720;
int winYLeng=576;
float halfX=winXLeng/2;
float halfY=winYLeng/2;
// create our SDLWindow
SDLOpenGL win("GLFunctions Demo",100,100,winXLeng,winYLeng);
// this makes sure the window is active for OpenGL calls, if we have
// more than one window we need to call this for the window we want to
// set OpenGL for
win.makeCurrent();
// setup our default OpenGL window state
initOpenGL();
Ship player;
float xMouse=0.00f;
float yMouse=0.00f;
float newRot=0.00f;
bool quit=false;
while(!quit)
{
SDL_Event event;
// grab the event from the window (note this explicitly calls make current)
win.pollEvent(event);
switch (event.type)
{
// this is the window x being clicked.
case SDL_QUIT : quit = true; break;
// now we look for a keydown event
case SDL_KEYDOWN:
{
switch( event.key.keysym.sym )
{
// if it's the escape key quit
case SDLK_ESCAPE : quit = true; break;
// make OpenGL draw wireframe
case SDLK_e : glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
// make OpenGL draw solid
case SDLK_r : glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
default : break;
} // end of key process
} // end of keydown
//Now we look for Mouse movements
case SDL_MOUSEMOTION:
{
xMouse=(event.motion.x-halfX)/(halfX);
yMouse=(event.motion.y-halfY)/(halfY);
std::cout<<"From SDL_MOUSEMOTION:"<<'\n'<<"Mouse at: "<<xMouse<<','<<yMouse<<'\n';
}
default : break;
} // end of event switch
// draw scene
draw(player,newRot,xMouse,yMouse);
// update the buffer so we can see what we have drawn.
win.swapWindow();
}
return EXIT_SUCCESS;
}
void initOpenGL()
{
// this sets the background colour
glClearColor(0,0,0,1.0);
// this is how big our window is for drawing
glViewport(0,0,720,576);
Camera::perspective(60,float(720/576),0.01,500);
Camera::lookAt(Vec4(0,30,0.1),Vec4(0,0,0),Vec4(0,1,0));
glDisable(GL_LIGHTING);
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
glColor3f(1,1,0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
}
void draw(Ship &_player, GLfloat _rot,int _xMouse, int _yMouse)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
std::cout<<"From draw(Ship,GLfloat,int,int):"<<'\n'<<"Mouse at: "<<_xMouse<<','<<_yMouse<<'\n';
_player.followMouse(_xMouse,_yMouse);
}
Anyone have a clue?
Thanks in advance~
Edit: nvm...but I will remember to check my parameter type next time...
I read this tutorial and I execute it correctly.
However, I wanted to apply some changes. The first change was to see a different view of that circle, for example showing just the 1/4 of the circle. I know this is done by glViewPort(parameters). However, after changing the parameters, nothing happens. I have checked many forums to figure out why this problem occurs, but I couldn't figure out anything.
Can someone explain me more on this and how to use it? (To understand where the problem happens)
This is the code (Which is originally written on that tutorial)
Code:
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void init(void)
{
glClearColor(1.0,1.0,1.0,0.0);
glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
gluOrtho2D(0.0,200.0,0.0,200.0);
//glViewport(0, 0, 250, 250);
}
void setPixel(GLint x,GLint y)
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
}
void Circle(){
int xCenter=100,yCenter=100,r=50;
int x=0,y=r;
int p = 3/2 - r;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f( 1 ,0, 0);
while(x<=y){
setPixel(xCenter+x,yCenter+y);
setPixel(xCenter+y,yCenter+x);
setPixel(xCenter-x,yCenter+y);
setPixel(xCenter+y,yCenter-x);
setPixel(xCenter-x,yCenter-y);
setPixel(xCenter-y,yCenter-x);
setPixel(xCenter+x,yCenter-y);
setPixel(xCenter-y,yCenter+x);
if (p<0)
p += (2*x)+3;
else {
p += (2*(x-y))+5;
y -= 1;
}
x++;
}
glFlush();
}
int main(int argc,char **argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
glutCreateWindow("My Circl2e");
init();
glViewport(0,0,250,250);
//glLoadIdentity();
glutDisplayFunc(Circle);
glutMainLoop();
return 0;
}
p.s: In some examples I see they use setWindow(parameters) before using glViewPort(parameters). but setWindow() needs library which is not available for ubuntu.
The default GLUT reshape function calls glViewport() with the window size. From the documentation:
If a reshape callback is not registered for a window or NULL is passed to glutReshapeFunc (to deregister a previously registered callback), the default reshape callback is used. This default callback will simply call glViewport(0,0,width,height) on the normal plane (and on the overlay if one exists).
Since you call glViewport() so early, the window will be shaped after you make your call, overriding the viewport you specified.
You either need to register your own reshape function, and call glViewport() with your desired viewport parameters there, or call glViewport() at the start of your Circle() function.
The code is designed to load a .obj file, draw, rotate camera around mesh (this is ongoing) and display rotation value when the mouse button is clicked. I am using eclipse C++ IDE with FLTK. When the mouse button is clicked the window crashes. The error message when debugging is "no source available for gl_draw".
The code is as follows:
void onMouseButton(int button, int state, int x, int y)
{
switch(button){
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN){
// Print value on object
char s[40];
sprintf(s, "ROT=%.2f", g_rotation);
glRasterPos2f(60,40);
gl_draw(s, strlen(s));
}
}
}
The main code:
int main(int argc, char **argv)
{
Fl_Window win(WIDTH,HEIGHT, "Wavefront");
win.resizable(win);
win.show(argc, argv);
// Docs say to add glut subwindow /after/ calling win.show()
win.begin();
// initialize and run program
//glutInit(&argc, argv); // GLUT initialization
glutInitWindowSize(WIDTH-20, HEIGHT-20);
glutInitWindowPosition(10,10); // place inside parent window
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutCreateWindow("Ear");
glutDisplayFunc(display); // register Display Function
glutIdleFunc( display ); // register Idle Function
glutMouseFunc( onMouseButton );
glutKeyboardFunc( keyboard ); // register Keyboard Handler
initialize();
obj.Load("Ear_obj.obj");
//gl_draw(s, strlen(s));
glutMainLoop();
win.end();// run GLUT mainloop
return 0;
}
If gl_draw(s, strlen(s)); is removed code run as expected , therefore loads the mesh, draws it, displays the mesh as the camera is rotated but would do nothing if the mouse is clicked.
Is the a way to display any text when the mouse is clicked or is there a step I am missing that is causing the error?
I am having some issues with GLFW's window creation. I am wanting to have a program capable of toggling between windowed and fullscreen mode. To do this in GLFW 2.7.8 one must first destroy the active window, then create a new one. I read that version 3.0 has support for multiple windows, but it is still in development.
I have provided my own function to handle keyboard input. Using the initial 400 by 400 window, the program functions as expected; it will enter fullscreen on f or F, will exit when the escape key is pressed, and will complain when anything else is pressed.
However, when fullscreen mode is entered, the window becomes unresponsive with regards to my provided keyboard function. It will continue to run through the loop in main() and will respond to something like the glfwGetKey(GLFW_KEY_ESC) test. Regardless of if I have the mouse cursor enabled or not, the cursor does not appear.
Again, the fullscreen window is created and the KeyboardCallback function returns back into the main loop. I wish to understand why the fullscreen window is not working with my keyboard function, and why it is not displaying properly.
I am not drawing anything to the window, as I am trying to get some experience with various window abstraction libraries specifically. Drawing a simple triangle did nothing to solve he problem, and the fullscreen window remains black.
My code is as follows:
#include <stdio.h>
#include <stdlib.h>
// glfw32 - 2.7.8
#include <GL\glfw.h>
#pragma comment (lib, "GLFW.lib")
#pragma comment (lib, "opengl32.lib")
using namespace std;
// constants and globals
const int WINDOW_WIDTH=400, WINDOW_HEIGHT=400;
static bool fullscreen=false;
// function declarations
void GLFWCALL KeyboardCallback(int key, int action);
void FatalError(const char* msg) {
fprintf(stderr, "ERROR: Failure in \"%s\"\n", msg);
exit(1);
}
int main() {
// ititialize GLFW
glfwInit();
glfwEnable(GLFW_MOUSE_CURSOR);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
// initial window, 400x400 with 32-bit depth buffer in windowed mode
glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0, GLFW_WINDOW);
glfwSetWindowTitle("Simple Title");
glfwSetWindowPos(0, 0);
// set custom keyboard callback
glfwSetKeyCallback(KeyboardCallback);
while (true) { // loop until exit
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers();
// debug
//printf("Looping...\n");
if ( glfwGetKey(GLFW_KEY_ESC) ) {break;}
}
glfwTerminate();
printf("\nHave a nice day\n");
return 0;
}
void GLFWCALL KeyboardCallback(int key, int action) {
//printf("In keyboard function\n");
if (action) { // if key DOWN,
switch(key) { // do something...
case 'f':
case 'F': {
fullscreen = !fullscreen;
printf("Toggle Fullscreen: %s\n", (fullscreen ? "On" : "Off"));
glfwCloseWindow();
if (! glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0,
fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW)) {
FatalError("toggle fullscreen");
}
glfwSetWindowTitle("New Title");
break;
}
case GLFW_KEY_ESC: {
printf("\nGoodbye cruel world...\n");
glfwTerminate();
exit(0);
}
default: {
printf("Key not implemented: %c\n", key);
break;
}
}
}
printf("Exiting keyboard function\n");
}
I tried James' approach from here but to no effect. Are there GLFW flags I am forgetting to set?
EDIT------- 5/20
I had a thought. Perhaps my callback was being unregistered when the window is destroyed. Turns out that re-registering my function when the new window is created made the window responsive.
While this solves my original problem, I now face a new one. I cannot render to the new window properly. I can insert glClear( GL_COLOR_BUFFER_BIT ); into my main loop, which will successfully set a background colour for the new window. For some reason it does not interact with my arrays and buffers to draw the image.
Code with attempted drawing
EDIT------- 5/21
I converted my code to GLFW 3.0.0. The window management is much cleaner (albeit more complex) and I do not have the rendering issue. Probably because I explicitly have to state the current context to use.
I would still like to solve the rendering issue, both out of curiosity and for if/when I return to 2.7.
Right now the event queue of GLFW is not pumped. You must either set the GLFW_AUTO_POLL_EVENTS option so that glfwSwapBuffers pumps the event queue, or you call glfwPollEvents at the start of a main event loop iteration.
I am creating a gui on opengl in qt4 IDE.I have created an widget with opengl window and there I became able to display the [b]curves[/b]. Here I use [b]paintGL()[/b] and within this I call my Drawing function for display.But my problem is that, I here use the[b] mousePressEvent(QMouseEvent *event)[/b] for getting the pixel coordinates so that clicking on the opengl window I can generate the curve at that particular clicking position. but after running the program I found that the initial drawing function and the curve generated. but after clicking the window could not be updated, but in the console application all calculations executed, only the display is not updated.
So how can I update the opengl window after clicking mouse on this window?
Here is my source code:
GlWidget.cpp
//////Mouse Click Event for finding the pixel values//////
void GLWidget::mousePressEvent(QMouseEvent *event)
{
float window_width,window_height;
float ratio_x,ratio_y,cy;
click_x=event->x();
click_y=event->y();
// qDebug()<<"screen cx1==="<<cx1;
// qDebug()<<"screen cy1==="<<cy1;
window_width = 800;
window_height = 600;
ratio_x=30.0/window_width;
ratio_y=30.0/window_height;
cy=window_height-click_y;
click_x=click_x*ratio_x-10;
click_y=cy*ratio_y-10;
qDebug()<<"original_position_on_screen x==="<<click_x;
qDebug()<<"original_position_on_screen y==="<<click_y;
count=count+1;
qDebug()<<"count==="<<count;
func();
}
void GLWidget::func()
{
Draw_Curve(); //Drawing function
}
void GLWidget::Draw_Curve()
{
//Draw The Curve
}
void GLWidget:: paintGL() // paintGL() function
{
glClear(GL_COLOR_BUFFER_BIT);
Draw_Axes(); //Draw 3d coordinate axes
func(); //in this function we get the pixel coordinates everytime the mouse is clicked in the window
}
There are few things:
instead of calling a function to render anything from the mouse event handler, you should request update
void GLWidget::mousePressEvent(QMouseEvent *event)
{
float window_width,window_height;
float ratio_x,ratio_y,cy;
click_x=event->x();
click_y=event->y();
// qDebug()<<"screen cx1==="<<cx1;
// qDebug()<<"screen cy1==="<<cy1;
window_width = 800;
window_height = 600;
ratio_x=30.0/window_width;
ratio_y=30.0/window_height;
cy=window_height-click_y;
click_x=click_x*ratio_x-10;
click_y=cy*ratio_y-10;
qDebug()<<"original_position_on_screen x==="<<click_x;
qDebug()<<"original_position_on_screen y==="<<click_y;
count=count+1;
qDebug()<<"count==="<<count;
update(); // to request image update
}
your paintGL() method does all the rendering. So, whatever you want to display goes here.