reprap: Added opengl renderer
[simavr] / examples / board_reprap / src / reprap_gl.c
1 /*
2         reprap_gl.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #if __APPLE__
23 #include <GLUT/glut.h>
24 #else
25 #include <GL/glut.h>
26 #endif
27
28 #include <stdio.h>
29
30 #include "reprap.h"
31 #include "reprap_gl.h"
32
33 #include "c3/c3.h"
34 #include "c3/c3camera.h"
35 #include "c3/c3arcball.h"
36
37 int _w = 800, _h = 600;
38 c3cam cam;
39 c3arcball arcball;
40 c3object_p root;
41 c3object_p head;
42 c3geometry_array_t geo_sorted = C_ARRAY_NULL;
43
44 extern reprap_t reprap;
45
46 static void
47 _gl_key_cb(
48                 unsigned char key,
49                 int x,
50                 int y)  /* called on key press */
51 {
52         switch (key) {
53                 case 'q':
54                 //      avr_vcd_stop(&vcd_file);
55                         exit(0);
56                         break;
57                 case 'r':
58                         printf("Starting VCD trace; press 's' to stop\n");
59                 //      avr_vcd_start(&vcd_file);
60                         break;
61                 case 's':
62                         printf("Stopping VCD trace\n");
63                 //      avr_vcd_stop(&vcd_file);
64                         break;
65         }
66 }
67
68
69 static void
70 _gl_display_cb(void)            /* function called whenever redisplay needed */
71 {
72         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
73
74         // Set up projection matrix
75         glMatrixMode(GL_PROJECTION); // Select projection matrix
76         glLoadIdentity(); // Start with an identity matrix
77
78         gluPerspective(45, _w / _h, 0, 10000);
79
80 //      glEnable(GL_TEXTURE_2D);
81         glShadeModel(GL_SMOOTH);
82
83         glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
84         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
85
86         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
87         glEnable(GL_BLEND);                         // Enable Blending
88         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);          // Type Of Blending To Use
89
90     glMatrixMode( GL_MODELVIEW );
91     glLoadIdentity();
92    // glMultMatrixf(arcball.rot.n);
93     glMultMatrixf(cam.mtx.n);
94     glTranslatef( -cam.eye.n[VX], -cam.eye.n[VY], -cam.eye.n[VZ] );
95   //  glMultMatrixf(arcball.rot.n);
96
97         c3vec3 headp = c3vec3f(
98                         stepper_get_position_mm(&reprap.step_x),
99                         stepper_get_position_mm(&reprap.step_y),
100                         stepper_get_position_mm(&reprap.step_z));
101         c3mat4 headmove = translation3D(headp);
102         c3transform_set(head->transform.e[0], &headmove);
103
104         if (root->dirty) {
105                 printf("reproject\n");
106                 c3mat4 m = identity3D();
107                 c3object_project(root, &m);
108                 c3geometry_array_clear(&geo_sorted);
109                 c3object_get_geometry(root, &geo_sorted);
110         }
111
112         for (int gi = 0; gi < geo_sorted.count; gi++) {
113                 c3geometry_p g = geo_sorted.e[gi];
114                 glColor4fv(g->mat.color.n);
115             glVertexPointer(3, GL_FLOAT, 0, g->projected.count ? g->projected.e : g->vertice.e);
116             glEnableClientState(GL_VERTEX_ARRAY);
117
118             glDrawArrays(g->type, 0, g->vertice.count);
119
120             glDisableClientState(GL_VERTEX_ARRAY);
121
122         }
123
124         glMatrixMode(GL_PROJECTION); // Select projection matrix
125         glLoadIdentity(); // Start with an identity matrix
126         glOrtho(0, _w, 0, _h, 0, 10);
127         glScalef(1,-1,1);
128         glTranslatef(0, -1 * _h, 0);
129
130         glMatrixMode(GL_MODELVIEW); // Select modelview matrix
131
132         #if 0
133         glPushMatrix();
134         glLoadIdentity(); // Start with an identity matrix
135         glScalef(3, 3, 1);
136         hd44780_gl_draw(
137                 &hd44780,
138                         colors[color][0], /* background */
139                         colors[color][1], /* character background */
140                         colors[color][2], /* text */
141                         colors[color][3] /* shadow */ );
142         glPopMatrix();
143 #endif
144     glutSwapBuffers();
145 }
146
147 int button;
148 c3vec2 move;
149 c3cam startcam;
150
151 static
152 void _gl_button_cb(
153                 int b,
154                 int s,
155                 int x,
156                 int y)
157 {
158         button = s == GLUT_DOWN ? b : 0;
159         startcam = cam;
160         move = c3vec2f(x, y);
161         if (s == GLUT_DOWN)
162                 c3arcball_mouse_down(&arcball, x, y);
163         else
164                 c3arcball_mouse_up(&arcball);
165 }
166
167 void
168 _gl_motion_cb(
169                 int x,
170                 int y)
171 {
172         c3vec2 m = c3vec2f(x, y);
173         c3vec2 delta = c3vec2_sub(move, m);
174
175 //      printf("%s b%d click %.1f,%.1f now %d,%d\n",
176 //                      __func__, button, move.n[0], move.n[1], x, y);
177
178         switch (button) {
179                 case GLUT_LEFT_BUTTON: {
180
181                 //      c3cam_eye_yaw(&cam, delta.n[0] / 4);
182                 //      c3cam_eye_pitch(&cam, delta.n[1] / 4);
183
184                         c3mat4 rotx = rotation3D(c3vec3f(1.0, 0, 0), delta.n[1] / 4);
185                         c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4);
186                         rotx = c3mat4_mul(&rotx, &roty);
187                         c3cam_rot_about_lookat(&cam, &rotx);
188
189                     c3cam_update_matrix(&cam);
190 //                  c3arcball_mouse_motion(&arcball, x, y, 0,0,0);
191                 }       break;
192                 case GLUT_RIGHT_BUTTON: {
193
194                 }       break;
195         }
196         move = m;
197 }
198
199 // gl timer. if the lcd is dirty, refresh display
200 static void
201 _gl_timer_cb(
202                 int i)
203 {
204         //static int oldstate = -1;
205         // restart timer
206         c3arcball_idle(&arcball);
207         glutTimerFunc(1000 / 24, _gl_timer_cb, 0);
208         glutPostRedisplay();
209 }
210
211 int
212 gl_init(
213                 int argc,
214                 char *argv[] )
215 {
216         glutInit(&argc, argv);          /* initialize GLUT system */
217
218         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
219         glutInitWindowSize(_w, _h);             /* width=400pixels height=500pixels */
220         /*window =*/ glutCreateWindow("Press 'q' to quit");     /* create window */
221
222         glutDisplayFunc(_gl_display_cb);                /* set window's display callback */
223         glutKeyboardFunc(_gl_key_cb);           /* set window's key callback */
224         glutTimerFunc(1000 / 24, _gl_timer_cb, 0);
225
226         glutMouseFunc(_gl_button_cb);
227         glutMotionFunc(_gl_motion_cb);
228
229         glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
230         glEnable(GL_LINE_SMOOTH);
231         cam = c3cam_new();
232         cam.lookat = c3vec3f(100.0, 100.0, 0.0);
233     cam.eye = c3vec3f(100.0, -100.0, 100.0);
234     c3cam_update_matrix(&cam);
235
236     c3arcball_init_center(&arcball, c3vec2f(_w/2, _h/2), 100);
237 //      hd44780_gl_init();
238
239     root = c3object_new(NULL);
240
241     c3object_p grid = c3object_new(root);
242     {
243         c3geometry_p g = c3geometry_new(GL_LINES, grid);
244         g->mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0);
245         for (int x = 0; x < 20; x++) {
246                 for (int y = 0; y < 20; y++) {
247                         c3vec3 p[4] = {
248                                 c3vec3f(-1+x*10,y*10,0), c3vec3f(1+x*10,y*10,0),
249                                 c3vec3f(x*10,-1+y*10,0), c3vec3f(x*10,1+y*10,0),
250                         };
251                         c3vertex_array_insert(&g->vertice,
252                                         g->vertice.count, p, 4);
253                 }
254         }
255     }
256     head = c3object_new(root);
257     c3transform_new(head);
258     {
259         c3geometry_p g = c3geometry_new(GL_LINES, head);
260         g->mat.color = c3vec4f(1.0, 0.0, 0.0, 1.0);
261                 c3vec3 p[4] = {
262                         c3vec3f(-1, 0, 0), c3vec3f(1, 0, 0),
263                         c3vec3f(0, -1, 0), c3vec3f(0, 1, 0),
264                 };
265         c3vertex_array_insert(&g->vertice,
266                         g->vertice.count, p, 4);
267     }
268         return 1;
269 }
270
271 int
272 gl_runloop()
273 {
274         glutMainLoop();
275         return 0;
276 }