2023/09/25
Absolute devices vs Relative devices
GLUT event types
- window
→ resize, expose , iconify
- mouse
- motion
- keyboard
- idle
→ define what should be done if there is no event in the queue
We have to register callback functions to define these events
- When an event occurs, the appropriate callbackfunction executes
- last line in main.c for GLUT must be glutMainLoop(); which puts the program in an infinite event loop
→ in each cycle thru the loop, glut looks at events in the queue and picks the appropriate callback based on the type
→ glutDisplayFunc
⇒ window first opened
⇒ window is exposed
⇒ user program decides it needs to redraw the scene - animation
⇒ we can force it to update display with glutPostRedisplay. can call this in any callback function except the display on
→ glutMouseFunc
→ glutMotionFunc
→ glutPassiveMotionFunc
→ glutReshapeFunc
→ glutKeyFunc
→ glutIdleFunc
⇒ useful for animation
⇒ can call glutPostRedisplay
⇒ dont draw in this function, but change some animation variables, and then call the redraw function
• this has to be a global because myIdle() doesnt take parameters
⇒ will call as often as it can based on ur hardware (frame rate)
First Animation
#include <math.h>
#define PI 3.14159265
#define DEG_TO_RAD PI/180.0
//updated in myIdle, used in myDisplay
GLFloat theta = 0.0;
void myIdle(){
theta += 0.002;
if(theta >= 360){
theta -= 360;
}
}
void myDisplay(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(cos(DEG_TO_RAD * theta), sin(DEG_TO_RAD*theta));
glVertex2f(cos(DEG_TO_RAD * theta + 90), sin(DEG_TO_RAD*theta + 90));
glVertex2f(cos(DEG_TO_RAD * theta + 180), sin(DEG_TO_RAD*theta + 180));
glVertex2f(cos(DEG_TO_RAD * theta + 270), sin(DEG_TO_RAD*theta + 270));
glEnd();
glFlush();
}
Partially drawn scenes
- we can't always draw the scne fast enough before the hardware refreshes memory
- partially drawn scene happen when u get a video memory dump to the screen before we've finished drawing
- double buffering solves this problem
→ we don't draw directly to video memory, we're going to draw into an unseen back buffer
→ front buffer is displayed but not written to
→ when openGL has finished drawing, it will send a signal to that it can be sent to the screen
→ transfer from back to front buffer is a fixed time operation. it doesnt matter how long it took the draw the pixels, when they're done theyre just an area of memory. it is a fixed time operation to switch the memory to the other buffer. no longer a function of the scene complexity, its just a fixed time operation
→ call glutSwapBuffers instead of glFlush
→ start off by calling glutInitDisplayMode(GL_RGBA | GL_DOUBLE | GL_DEPTH)
⇒ bitwise OR
typedef GLFloat point2[2];
point2 pointA = {-0.5, -0.2}
point2 pointB = {0.9, 0.7}
GLFloat interp = 0.0;
void myIdle(){
interp += 0.005;
if(interp >= 1){
interp = 0;
}
glPostRedisplay()
}
void myDisplay(){
glClear()
glBegin(GL_POINTS)
glColor3f(1,0,0)
glVertex2fv(pointA)
glColor3f(0,0,1)
glVertex2fv(pointB)
glColor(1,1,1)
glVertex2f((1-interp)*pointA[0] + interp*pointB[0], (1-interp)*pointA[1] + interp*pointB[1])
glEnd()
glutSwapBuffers()
}
2023/09/27 - 12:43
Callbacks
- can exit the program with a simple mouse callback
- must invert the y coordinate returned by the mouse callback
→ openGL drawing coordinates have an origin in the bottom left
→ mouse coordinates start from the top of the screen for some reason
- typically openGL drawing corrdinates are independent from window size
GLint mousePressed = 0;
GLFloat mouseX, mouseY;
GLint windowHeight = 400;
GLint windowWidth = 500;
void myDisplay(){
glColor(GL_COLOR_BUFFER_BIT)
if(mousePressed){
glBegin(GL_POINTS);
glVertex(mouseX,mouseY);
gnEnd();
}
glFlush()
}
void myMouseButton(int button, int state, int x, int y){
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
mousePressed = 1;
mouseX = (GLFloat) x/ (GLFloat)windowWidth
mouseY = (GLFloat)windowHeight - (GLFloat)y;
mouseY = mouseY / (GLFloat)windowHeight;
glPostRedisplay();
}
}
Changes to the window size
- have to decide whether you want to react to window size change or not
- if we don't react, object will get distorted
- in addition to changing openGL drawing parameters we also have to fix the viewport
- viewport: subset of the application window
- when we have a reshape event we have to adjust the viewport to the new available size
void myReshape(int newWidth, int newHeight){
glViewport(0,0,newWidth,newHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //"dont worry about it yet"
gluOrtho2D(0, (GLFloat)newWidth / (GLFloat)originalWidth, 0, (GLFloat) newHeight/ (GLFloat) originalHeight)
}
Using the keyboard
- define a callback
→ glutKeyboardFunc(myKey)
→ myKey(unsigned char key, int x, int y)
- key release doesnt count as an event
- can also create:
→ menus
→ dynamic windows
→ sub-windows
→ multiple windows
→ changing callbacks during execution Index