e4fc596b1e818c1d049c1e3c94a326b77c6db2c8
[freeglut] / progs / demos / multi-touch / multi-touch.c
1 /**
2  * Sample multi-touch program that displays a square where a cursor
3  * clicks, with a different color for each cursor.
4  *
5  * Copyright (C) 2012  Sylvain Beucler
6  * 
7  * Permission is hereby granted, free of charge, to any person
8  * obtaining a copy of this software and associated documentation
9  * files (the "Software"), to deal in the Software without
10  * restriction, including without limitation the rights to use, copy,
11  * modify, merge, publish, distribute, sublicense, and/or sell copies
12  * of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <GL/freeglut.h>
33 #include <GL/gl.h>
34
35 #define NUM_DEVICES 16
36 #define NUM_CURSORS 64
37 typedef struct cursor {
38     char on;
39     float x;
40     float y;
41 } *Cursor;
42 struct cursor cursors[NUM_DEVICES][NUM_CURSORS];
43
44
45 static float square[] = {
46         -.5, -.5,
47          .5, -.5,
48         -.5,  .5,
49          .5,  .5,
50     };
51
52 void onDisplay(void) {
53     int d;
54     glClearColor(0,0,0,1);
55     glClear(GL_COLOR_BUFFER_BIT);
56
57     glEnableClientState(GL_VERTEX_ARRAY);
58     glVertexPointer(2, GL_FLOAT, 0, square);
59     for (d = 0; d < NUM_DEVICES; d++) {
60         int c;
61         for (c = 0; c < NUM_CURSORS; c++) {
62             Cursor C = &cursors[d][c];
63             if (C->on) {
64                 glMatrixMode(GL_MODELVIEW);
65                 glLoadIdentity();
66                 glTranslatef(C->x, C->y, 0);
67                 glScalef(30, 30, 1);
68                 
69                 switch(c) {
70                 case 0:
71                     glColor4f(0,0,1,1);
72                     break;
73                 case 1:
74                     glColor4f(0,1,0,1);
75                     break;
76                 case 2:
77                     glColor4f(1,0,0,1);
78                     break;
79                 case 3:
80                     glColor4f(1,1,1,1);
81                     break;
82                 default:
83                     glColor4d(.5,.5,.5,1);
84                     break;
85                 }
86                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
87             }
88         }
89     }
90     glDisableClientState(GL_VERTEX_ARRAY);
91
92     glutSwapBuffers();
93 }
94
95 void onMouse(int button, int state, int x, int y) {
96     if (button == 0) {
97         cursors[0][0].on = (state == GLUT_DOWN);
98         cursors[0][0].x = (float)x;
99         cursors[0][0].y = (float)y;
100         printf("normal click\n");
101     }
102 }
103
104 void onMotion(int x, int y) {
105     cursors[0][0].x = (float)x;
106     cursors[0][0].y = (float)y;
107 }
108
109 /* Using FG2.8 (reversed) prototype for now */
110 /* void onMultiButton(int cursor_id, int button, int state, int x, int y) { */
111 void onMultiButton(int cursor_id, int x, int y, int button, int state) {
112     if (cursor_id > NUM_CURSORS) {
113         fprintf(stderr, "cursor_id (%d) > NUM_CURSORS (%d)\n", cursor_id, NUM_CURSORS);
114         return;
115     }
116     if (button == 0) {
117         cursors[0][cursor_id].on = (state == GLUT_DOWN);
118         cursors[0][cursor_id].x = (float)x;
119         cursors[0][cursor_id].y = (float)y;
120         printf("multi-touch %d click\n", cursor_id);
121     }
122 }
123
124 void onMultiMotion(int cursor_id, int x, int y) {
125     if (cursor_id > NUM_CURSORS) {
126         fprintf(stderr, "cursor_id (%d) > NUM_CURSORS (%d)\n", cursor_id, NUM_CURSORS);
127         return;
128     }
129     cursors[0][cursor_id].x = (float)x;
130     cursors[0][cursor_id].y = (float)y;
131 }
132
133 void onReshape(int width, int height) {
134     glViewport(0, 0, width, height);
135     
136     glMatrixMode(GL_PROJECTION);
137     glOrtho(0, width, height, 0, -1, 1);
138 }
139
140 void onIdle(void) {
141     glutPostRedisplay();
142 }
143
144 int main(int argc, char* argv[]) {
145     memset(cursors, 0, sizeof(cursors));
146
147     glutInit(&argc, argv);
148     glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
149     glutInitWindowSize(640, 480);
150     glutCreateWindow("Multi-touch test");
151
152     glutDisplayFunc(onDisplay);
153     glutReshapeFunc(onReshape);
154     glutIdleFunc(onIdle);
155     glutMouseFunc(onMouse);
156     glutMotionFunc(onMotion);
157     glutMultiButtonFunc(onMultiButton);
158     glutMultiMotionFunc(onMultiMotion);
159
160     glutMainLoop();
161
162     return EXIT_SUCCESS;
163 }