Add the picking feature.

We can now select a LED on the screen and get the index of the LED.
To get the right index, we use the color picking technique mentioned
in the OpenGL RedBook. This works suprisingly pretty well (and fast!).
This commit is contained in:
Aaron Mueller 2011-10-30 23:55:53 +01:00
parent b2d11488fa
commit 37e885f02e
6 changed files with 59 additions and 13 deletions

View file

@ -10,8 +10,12 @@
#define PI 3.1415926535897932
#define TOP_ORIENTATION 1
#define SIDE_ORIENTATION 2
// Poor Man's enums
#define TOP_ORIENTATION 0x01
#define SIDE_ORIENTATION 0x02
#define RENDER_MODE 0x01
#define PICKING_MODE 0x02
// Materials
extern float ledOnMaterial[];

View file

@ -5,21 +5,23 @@
#include "display.h"
void drawLEDCube(orientation) {
void drawLEDs(int orientation, int mode) {
int x, y, z;
int colorIndex = 0;
if (orientation == TOP_ORIENTATION) {
glRotatef(90, 2, 0, 0);
}
// LEDs
glMaterialfv(GL_FRONT, GL_AMBIENT, ledOnMaterial);
for (z=-10; z<=10; z+=10) // Ebene
for (y=-10; y<=10; y+=10) // Zeile
for (x=-10; x<=10; x+=10) { // Spalte
// TODO: Test different colors
glMaterialfv(GL_FRONT, GL_AMBIENT, (z == 0 ? ledOnMaterial : ledOffMaterial));
if (mode == PICKING_MODE) {
glColor3ub(0, 0, colorIndex*8);
colorIndex++;
} else {
glMaterialfv(GL_FRONT, GL_AMBIENT, (z == 0 ? ledOnMaterial : ledOffMaterial));
}
glPushMatrix();
glTranslatef(x, y, z-0.8);
@ -35,8 +37,10 @@ void drawLEDCube(orientation) {
glPopMatrix();
}
}
// Wires
void drawWires() {
int x, y;
for (y=-10; y<=10; y+=10)
for (x=-10; x<=10; x+=10) {
glMaterialfv(GL_FRONT, GL_AMBIENT, ((x == 0 || y == 0) ? innerWireMaterial : wireMaterial));
@ -61,9 +65,8 @@ void drawLEDCube(orientation) {
}
}
void display() {
void setScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(ZOOM_LEVEL, WINDOW_WIDTH/WINDOW_HEIGHT, 1.0, 350.0);
@ -71,8 +74,25 @@ void display() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(lookX, eyeAngle, lookZ, 0, 0, 0, 0, 1, 0);
}
drawLEDCube(TOP_ORIENTATION);
// OpenGL Display function
void display() {
setScene();
drawLEDs(TOP_ORIENTATION, RENDER_MODE);
drawWires();
glutSwapBuffers();
}
// Picking function
void displayPickingObjects() {
setScene();
glDisable(GL_DITHER);
glDisable(GL_LIGHTING);
drawLEDs(TOP_ORIENTATION, PICKING_MODE);
glEnable(GL_LIGHTING);
glEnable(GL_DITHER);
}

View file

@ -2,8 +2,13 @@
#define _DISPLAY_H
void drawLEDCube();
void drawLEDs(int orientation, int mode);
void drawWires();
void display();
void displayPickingObjects();
void setScene();
#endif

View file

@ -4,6 +4,7 @@
#include "config.h"
#include "input.h"
#include "display.h"
void moveCameraPosition(float direction) {
eyePos += direction;
@ -46,3 +47,16 @@ void keyboard_special(int key, int x, int y) {
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
int viewport[4];
GLubyte pixel[3];
displayPickingObjects();
glGetIntegerv(GL_VIEWPORT, viewport);
glReadPixels(x, viewport[3]-y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, (void*)pixel);
printf("%d\n", pixel[2]/8); // Selected LED
}
}

View file

@ -7,5 +7,7 @@ void moveCameraAngle(float angle);
void keyboard(unsigned char key, int x, int y);
void keyboard_special(int key, int x, int y);
void mouse(int button, int state, int x, int y);
#endif

View file

@ -33,6 +33,7 @@ int main(int argc, char* argv[]) {
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutSpecialFunc(keyboard_special);
glutMouseFunc(mouse);
glClearColor(0.0, 0.0, 0.0, 1.0);
glShadeModel(GL_SMOOTH);