程序代写案例-CITS 3003

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top


Lecture 11:
Interactive Programs
with Callbacks and Menus
CITS 3003 Graphics & Animation
Slides: E. Angel and D. Shreiner: Interactive Computer Graphics 6E © Addison-Wesley 2012
Breakdown of Lectures
1. Introduction & Image Formation
2. Programming with OpenGL
3. OpenGL: Pipeline Architecture
4. OpenGL: An Example Program
5. Vertex and Fragment Shaders 1
6. Vertex and Fragment Shaders 2
7. Representation and Coordinate
Systems
8. Coordinate Frame Transformations
9. Transformations and Homogeneous
Coordinates
10. Input, Interaction and Callbacks
11. More on Callbacks
12. Mid-semester Test
Study break
13. 3D Hidden Surface Removal
14. Mid term-test solution and project
discussion
15. Computer Viewing
16. Shading
17. Shading Models
18. Shading in OpenGL
19. Texture Mapping
20. Texture Mapping in OpenGL
21. Hierarchical Modelling
22. 3D Modelling: Subdivision Surfaces
23. Animation Fundamentals and
Quaternions
24. Skinning
4
Content
• How to build interactive programs using GLUT
callbacks
o Mouse
o Keyboard
o Reshape
o Idle
• Introduce menus in GLUT
5
Using a Pointing Device (Mouse)
• Mouse Event: When one of the mouse
buttons is depressed or released or the scroll
wheel is moved. glutMouseFunc()
• Motion Event: When the mouse is moved
within the window with one of the buttons
depressed. glutMotionFunc()
• Passive Motion Event: When the mouse is
moved within the window without a button
being held down. glutPassiveMotionFunc()
6
The mouse callback
glutMouseFunc(mymouse);
void mymouse(GLint button, GLint state,
GLint x, GLint y)
• The parameters passed to the function are:
• button - which mouse button
(GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON) caused the event
• state - state of that button (GLUT_UP, GLUT_DOWN)
• x, y – the mouse click position (in pixels) in the
window
7
The mouse callback
glutMouseFunc(mymouse);
void mymouse(GLint button, GLint state,
GLint x, GLint y)
• The parameters passed to the function are:
• button - which mouse button
(GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON) caused the event
• state - state of that button (GLUT_UP, GLUT_DOWN)
• x, y – the mouse click position (in pixels) in the
window
8
Mouse Scroll/Wheel
• button
– GLUT_LEFT_BUTTON
– GLUT_MIDDLE_BUTTON
– GLUT_RIGHT_BUTTON
• state
– GLUT_UP
– GLUT_DOWN
• Wheel is still a button
– button == 3 (scroll forward)
– button == 4 (scroll backwards)
– every scroll registers as a “button down + button up”
– you may use only one of them (up or down)
9
Mouse Positioning (x, y)
• The position on the screen window is usually measured in pixels
with the origin at the top-left corner
– When the window is refreshed, it is done from top to bottom
• OpenGL uses a world coordinate system with the origin at the
bottom left corner. Thus,
– you must invert the y coordinate passed to your callback
function by the height of the window
– i.e., y = h – y;
– x remains the same
(0,0)
h
w 10
How to obtain the window size
• To invert the y position we need to know the
window height
• Note that the window height value can change
during program execution
• We can use a global variable to keep track of the
window height value
• glutGet(GLUT_WINDOW_WITDH)
glutGet(GLUT_WINDOW_HEIGHT)
11
Terminating a program
• We can also use the simple mouse callback:
• Note that we ignore the x and y parameters in
the example above.
void mymouse(int btn, int state, int x, int y)
{
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
exit(0);
}
12
Using the mouse position
• In the next example, we show how to draw a
small square at the location of the mouse
each time the left mouse button is clicked
13
Example 1: Drawing squares at
clicked location of cursor
void mymouse(int btn, int state, int x, int y)
{
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
exit(0);
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
drawSquare(x, y);
}
void drawSquare(int x, int y)
{
y = h-y; /* invert y position */
points[i] = vec2(x+size, y+size);
points[i+1] = vec2(x-size, y+size);
points[i+2] = vec2(x-size, y-size);
points[i+3] = vec2(x+size, y-size);
i += 4;
}
Note that in the drawSquare function, variable h is a global variable storing
the height (in pixels) of the window.
h, size, and i
are 3 global
variables.
14
x,y
x+size,y+size
Using the motion callback
• We can draw squares (or anything else) using the motion callback
– glutMotionFunc(mymotion);
• We can also draw squares without depressing a button using the
passive motion callback
– glutPassiveMotionFunc(mypassivemotion);
15
Example 2: Drawing a triangle by
specifying 3 vertices
int w, h; //the width and height of window
int count = 0;
void mymouse(int btn, int state, int x, int y)
{
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
exit(0);
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
y = h-y;
points[count].x = (float) x/(w/2)-1.0;
points[count].y = (float) y/(h/2) – 1.0;
count++;
}
if (count == 3)
{
glutPostRedisplay();
count = 0;
}
}
16
Using the keyboard callback
glutKeyboardFunc(mykey);
void mykey(unsigned char key, int x, int y)
Parameters passed to the mykey callback function are:
• key – the ASCII code of the key depressed
• x, y - and mouse location at the time the key was pressed
•Example:
void mykey(unsigned char key, int x, int y)
{
if (key == ’Q’ | key == ’q’)
exit(0);
}
17
Special and Modifier Keys
• GLUT defines the special keys in glut.h
– Function key 1: GLUT_KEY_F1
– Up arrow key: GLUT_KEY_UP
– e.g., if (key == GLUT_KEY_F1 ……
• Can also check whether one of the modifiers
– GLUT_ACTIVE_SHIFT
– GLUT_ACTIVE_CTRL
– GLUT_ACTIVE_ALT
is depressed by
glutGetModifiers()
This allows emulation of a three-button mouse with
one- or two-button mice
18
Reshaping the window
• We can reshape and resize the display window
by pulling the corner of the window
• What happens to the display?
• The window in the application must be redrawn
• There are three possibilities:
1. We can display the whole world but force it to fit in the
new window (this can alter the aspect ratio).
2. We can display part of the world.
3. We can display the scale the whole world to fit in the
window and keep the aspect ratio.
19
Reshape possiblities
• Three reshape possibilities
original
Default
reshaped
20
The Reshape callback
glutReshapeFunc(myreshape);
void myreshape(int w, int h)
• Parameters passed to the function:
w, h – the width and height of new window (in pixels)
• What happens when the window is resized:
o A redisplay is posted automatically at end of execution of
the callback
o GLUT has a default reshape callback but you probably
want to define your own
21
The Reshape callback (cont.)
Suppose that the our original window is 500 (width) x 500 (height)
pixels and the clipping volume is: left=-0.2, right=0.2, bottom=-0.2,
top=0.2, near=2.0, far=20.0.
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
//glOrtho(left,right,bottom,top,near,far)
glOrtho(-0.2*(float)w/(float)h,
0.2*(float)w/(float)h,
-0.2, 0.2, 2.0, 20.0);
}
Note that near and far clipping planes
should be positive; otherwise the clipping
volume would be taken as behind the
camera.
No need to call glutPostRedisplay( ) here (see previous slide)
22
right
left
far
top
viewer
The Reshape callback (cont.)
Same setting as described on the previous slide. What does the
following reshape callback function do?
void reshape(int w, int h) {
glViewport(0, 0, w, h);
//glOrtho(left,right,bottom,top,near,far)
if (w > h)
glOrtho(-0.2*(float)w/(float)h,
0.2*(float)w/(float)h,
-0.2, 0.2, 2.0, 20.0);
else
glOrtho(-0.2, 0.2, -0.2*(float)h/(float)w,
0.2*(float)h/(float)w, 2.0, 20.0);
}
23
https://www.youtube.com/watch?v=V87lLvKscIY
The Idle Callback
• Invoked when there are no other events. Its
default is the null function pointer.
• Uses:
– continue to generate graphical primitives through
a display function while nothing else is happening
– to produce an animated display.
• In main, we specify an idle callback,
– glutIdleFunc(idle);
24
Example : Idle Callback
Void display()
{
// update/recalculate x, y, z locations of vertices
// based on previous x, y, z locations and/or time
}
void idle()
{
glutPostRedisplay();
//sometimes you just have to call the redisplay
//because what needs to change is already in there
}
25
Toolkits and Widgets
• Most window systems provide a toolkit or library
of functions for building user interfaces that use
special types of windows called widgets
• Widget sets include tools such as
o Menus
o Slidebars
o Dials
o Input boxes
But toolkits tend to be platform dependent
• GLUT provides a few widgets including menus
26
Menus
• GLUT supports pop-up menus
o A menu can have submenus
• Three steps for setting up a menu:
1) Define entries for the menu
2) Define action for each menu item
o Action carried out if an entry is selected
3) Attach menu to a mouse button
27
Defining a simple menu
• In the main or init function:
menu_id = glutCreateMenu(mymenu);
glutAddmenuEntry(”clear Screen”, 1);
glutAddmenuEntry(”exit”, 2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
entries that will appear when
right button is pressed
identifiers
clear screen
exit
name of the callback
functiona unique ID returned by glut
28
Menu actions
• Example of a simple menu callback function:
• Note when each menu is created, a unique id is
returned by glut
• To add a submenu, use glutAddSubMenu:
glutAddSubMenu(char *submenuName, int submenuId)
• To add a menu entry, use glutAddMenuEntry:
glutAddMenuEntry(char *entryname, int entryID)
• To attach the current menu, use glutAttachMenu.
void mymenu(int id)
{
if (id == 1) glClear();
if (id == 2) exit(0);
}
29
Menu – an example
// submenu for two light sources
int lightMenuId = glutCreateMenu(lightMenu);
glutAddMenuEntry("Move Light 1", 11);
glutAddMenuEntry("Change RGB of Light 1", 12);
glutAddMenuEntry("Move Light 2", 21);
glutAddMenuEntry("Change RGB of Light 2", 22);
// submenu for camera
int cameraMenuId = glutCreateMenu(cameraMenu);
// add these submenus to the main menu
glutCreateMenu(mainMenu);
glutAddSubMenu("Light sources", lightMenuId);
glutAddSubMenu("Camera", cameraMenuId);
glutAttachMenu(GLUT_RIGHT_BUTTON);
Put these lines of code
in an init function
Callback functions
Always create the
submenus before the
main menu
30
Menu – an example
// callback function for the light menu
void lightMenu(int id) {
switch (id) {
case 11: // action for moving light 1
case 12: // action for changing RGB of light 1
...
}
}
// callback function for the camera menu
void cameraMenu(int id) {
...
}
31
Further Reading
“Interactive Computer Graphics – A Top-Down Approach with Shader-Based
OpenGL” by Edward Angel and Dave Shreiner, 6th Ed, 2012
• Sec. 2.7 Control Functions
• Sec. 2.11 Adding Interaction up to
Sec 2.11.4 The Idle Callback
• Sec 2.12 Menus
• C++ code in the Chapter04 - Chapter09 folders
32

欢迎咨询51作业君
51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468