Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /examples/vr-demo/main.c
ViewVC logotype

Annotation of /examples/vr-demo/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3214 - (view) (download) (as text)

1 : jhr 2058 /*! \file main.c
2 :     *
3 :     * \author John Reppy
4 :     *
5 :     * Main program for Diderot VR viewer.
6 :     */
7 :    
8 :     /*
9 :     * COPYRIGHT (c) 2012 The Diderot Project (http://diderot-language.cs.uchicago.edu)
10 :     * All rights reserved.
11 :     */
12 :    
13 : jhr 3213 #define GL_GLEXT_PROTOTYPES
14 :     #define GLFW_INCLUDE_GLCOREARB
15 :     #include <GLFW/glfw3.h>
16 :     #if defined(__APPLE_CC__)
17 :     #include <OpenGL/glext.h>
18 :     #else
19 :     # include <GL/glext.h>
20 :     #endif
21 :    
22 : jhr 2058 #include "util.h"
23 : jhr 2063 #include "vr.h"
24 : jhr 2058 #include <unistd.h>
25 : jhr 2079 #include "teem/air.h"
26 : jhr 2058
27 : jhr 2061 /* minimum and maximum values from */
28 :     #define MIN_VALUE 0
29 :     #define MAX_VALUE 2632
30 :    
31 :     /* half the width of the opacity range */
32 :     #define OPAC_HALF_WID 150
33 :    
34 :     #define MIN_OPAC_MID ((float)(MIN_VALUE+OPAC_HALF_WID))
35 :     #define MAX_OPAC_MID ((float)(MAX_VALUE-OPAC_HALF_WID))
36 :    
37 : jhr 2079 #define OPAC_DELTA 25
38 : jhr 2067
39 : jhr 2079 /* reduced-size inputs */
40 :     #define REDUCED_WID 256
41 :     #define REDUCED_HT 184
42 :     #define REDUCED_STEP 1
43 : jhr 2058
44 :    
45 : jhr 2079 /* full-size inputs */
46 :     #define FULL_WID 512
47 :     #define FULL_HT 368
48 :     #define FULL_STEP 0.5
49 :    
50 :     #define WIDTH (2*FULL_WID)
51 :     #define HEIGHT (2*FULL_HT)
52 :    
53 : jhr 3214 void ReportError (GLenum err, const char *file, int line, const char *msg)
54 : jhr 2058 {
55 : jhr 3214 const char *error;
56 :    
57 :     switch (err) {
58 :     case GL_INVALID_ENUM: error = "invalid enum"; break;
59 :     case GL_INVALID_VALUE: error = "invalid value"; break;
60 :     case GL_INVALID_OPERATION: error = "invalid operation"; break;
61 :     case GL_INVALID_FRAMEBUFFER_OPERATION: error = "invalid framebuffer operation"; break;
62 :     case GL_OUT_OF_MEMORY: error = "out of memory"; break;
63 :     default: error = "unknown"; break;
64 :     }
65 :    
66 :     fprintf (stderr, "[%s:%d] %s; %s\n", file, line, error, msg);
67 :    
68 :     exit (1);
69 :     }
70 :    
71 :     static inline void CheckError (const char *file, int line, const char *msg)
72 :     {
73 : jhr 2058 GLenum errCode;
74 :     if ((errCode = glGetError()) != GL_NO_ERROR) {
75 : jhr 3214 ReportError (errCode, file, line, msg);
76 : jhr 2058 }
77 :     }
78 :    
79 : jhr 3214 #define CHECK(cmd) \
80 :     do { \
81 :     cmd; \
82 :     CheckError (__FILE__, __LINE__, "executing " #cmd); \
83 :     } while (0)
84 :    
85 : jhr 2058 /***** Globals for viewing, etc. *****/
86 :    
87 : jhr 2079 typedef struct {
88 :     bool init;
89 :     GLuint wid;
90 :     GLuint ht;
91 :     GLuint id;
92 :     } TexInfo_t;
93 :    
94 : jhr 2067 VR_World_t *World;
95 : jhr 2058 unsigned int Width; // view window width
96 :     unsigned int Height; // view window height
97 : jhr 2079 TexInfo_t ReducedTexure = { // Texture ID of reduced image
98 :     false, REDUCED_WID, REDUCED_HT, 0
99 :     };
100 :     TexInfo_t FullTexture = { // Texture ID of full image
101 :     false, FULL_WID, FULL_HT, 0
102 :     };
103 : jhr 3213 struct {
104 :     GLuint vaoId;
105 :     GLuint coordId;
106 :     GLuint ebufId;
107 :     } QuadMesh;
108 : jhr 2063 bool NeedsRedraw;
109 :     bool NeedsRecompute;
110 : jhr 2067 float OpacMid = 550.0;
111 : jhr 2079 int Dir = 0; /* -1, 0, 1 */
112 : jhr 2058
113 :    
114 : jhr 2079 // initialize a texture from a grayscale Nrrd file
115 :     void InitTexture (TexInfo_t *txt, Nrrd *img)
116 :     {
117 :     if (! txt->init) {
118 :     // generate the TeXID
119 : jhr 3214 CHECK( glGenTextures (1, &(txt->id)) );
120 : jhr 2079
121 :     // load the texture data
122 : jhr 3214 CHECK( glBindTexture (GL_TEXTURE_2D, txt->id) );
123 :     CHECK( glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, txt->wid, txt->ht, 0, GL_RGBA, GL_FLOAT, img->data) );
124 :     CHECK( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) );
125 :     CHECK( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) );
126 : jhr 2079 }
127 :     else {
128 :     // reload the texture data
129 : jhr 3214 CHECK( glBindTexture (GL_TEXTURE_2D, txt->id) );
130 :     CHECK( glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, txt->wid, txt->ht, GL_RGBA, GL_FLOAT, img->data) );
131 : jhr 2079 }
132 :     }
133 :    
134 : jhr 3213 #define COORD_ATTR 0
135 :    
136 :     // vertex shader
137 :     static const char *VertexShaderSrc = "\
138 :     #version 410\n\
139 :     uniform mat4 modelView;\n\
140 :     uniform mat4 projection;\n\
141 :     layout (location = 0) in vec2 coord;\n\
142 : jhr 3214 smooth out vec2 texCoord;\n\
143 : jhr 3213 \n\
144 :     void main ()\n\
145 :     {\n\
146 :     gl_Position = projection * modelView * vec4(coord, 0, 1);\n\
147 :     texCoord = coord;\n\
148 :     }\n\
149 :     ";
150 :    
151 :     // fragment shader
152 :     static const char *FragShaderSrc = "\
153 :     #version 410\n\
154 :     uniform sampler2D image;\n\
155 : jhr 3214 smooth in vec2 texCoord;\n\
156 : jhr 3213 layout (location = 0) out vec4 fragColor;\n\
157 :     void main ()\n\
158 :     {\n\
159 :     fragColor = vec4(texture(image, texCoord).rgb, 1);\n\
160 :     }\n\
161 :     ";
162 :    
163 : jhr 3214 static void CheckCompileStatus (const char *shader, GLuint id)
164 :     {
165 :     GLint sts;
166 :    
167 :     glGetShaderiv (id, GL_COMPILE_STATUS, &sts);
168 :     if (sts != GL_TRUE) {
169 :     /* the compile failed, so report an error */
170 :     glGetShaderiv (id, GL_INFO_LOG_LENGTH, &sts);
171 :     if (sts != 0) {
172 :     GLchar *log = (GLchar *) malloc(sts);
173 :     glGetShaderInfoLog (id, sts, 0, log);
174 :     fprintf (stderr, "Error compiling %s shader:\n%s\n", shader, log);
175 :     free (log);
176 :     }
177 :     else {
178 :     fprintf (stderr, "Error compiling %s shader:\n no log\n", shader);
179 :     }
180 :     exit (1);
181 :     }
182 :     }
183 :    
184 : jhr 3213 // Initialize the rendering context
185 :     //
186 :     static void InitGraphics ()
187 :     {
188 :     float coords[4 * 2] = {
189 :     0.0f, 0.0f,
190 :     1.0f, 0.0f,
191 :     1.0f, 1.0f,
192 :     0.0f, 1.0f,
193 :     };
194 :     unsigned short indices[4] = {0, 1, 2, 3};
195 :    
196 :     // initialize the shader program
197 :     GLuint vsh = glCreateShader (GL_VERTEX_SHADER);
198 :     glShaderSource (vsh, 1, &VertexShaderSrc, 0);
199 :     glCompileShader (vsh);
200 : jhr 3214 CheckCompileStatus ("vertex", vsh);
201 : jhr 3213
202 :     GLuint fsh = glCreateShader (GL_FRAGMENT_SHADER);
203 :     glShaderSource (fsh, 1, &FragShaderSrc, 0);
204 :     glCompileShader (fsh);
205 : jhr 3214 CheckCompileStatus ("fragment", fsh);
206 : jhr 3213
207 :     GLuint shaderProg = glCreateProgram ();
208 : jhr 3214 CHECK( glAttachShader (shaderProg, vsh) );
209 :     CHECK( glAttachShader (shaderProg, fsh) );
210 :     CHECK( glLinkProgram (shaderProg) );
211 : jhr 3213
212 : jhr 3214 CHECK( glUseProgram (shaderProg) );
213 : jhr 3213
214 :     // initialize the VBO
215 :     GLuint vaoId, buffers[2];
216 : jhr 3214 CHECK( glGenVertexArrays (1, &vaoId) );
217 :     CHECK( glGenBuffers (2, buffers) );
218 :     CHECK( glBindVertexArray (vaoId) );
219 : jhr 3213
220 : jhr 3214 CHECK( glBindBuffer (GL_ARRAY_BUFFER, buffers[0]) );
221 :     CHECK( glBufferData (GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW) );
222 :     CHECK( glVertexAttribPointer (COORD_ATTR, 2, GL_FLOAT, GL_FALSE, 0, 0) );
223 :     CHECK( glEnableVertexAttribArray (COORD_ATTR) );
224 : jhr 3213
225 : jhr 3214 CHECK( glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffers[1]) );
226 :     CHECK( glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW) );
227 : jhr 3213
228 :     QuadMesh.vaoId = vaoId;
229 :     QuadMesh.coordId = buffers[0];
230 :     QuadMesh.ebufId = buffers[1];
231 :    
232 :     // initialize the transformation matrices
233 :     float projMat[16] = { // gluOrtho2D (0.0, 1.0, 0.0, 1.0);
234 :     2, 0, 0, 0,
235 :     0, 2, 0, 0,
236 :     0, 0, -2, 0,
237 :     -1, -1, 0, 1,
238 :     };
239 :     float modelViewMat[16] = { // gluLookAt (0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
240 :     1, 0, 0, 0,
241 :     0, 1, 0, 0,
242 :     0, 0, -1, 0,
243 :     0, 0, 0, 1,
244 :     };
245 :     glUniformMatrix4fv (glGetUniformLocation (shaderProg, "projection"), 1, GL_FALSE, projMat);
246 :     glUniformMatrix4fv (glGetUniformLocation (shaderProg, "modelView"), 1, GL_FALSE, modelViewMat);
247 :    
248 :     // initialize texture binding
249 :     glUniform1i (glGetUniformLocation (shaderProg, "image"), 0); // texture unit 0
250 :     }
251 :    
252 : jhr 2058 // Callback function called by GLUT to render screen
253 : jhr 2079 void Draw (GLuint txtId)
254 : jhr 2058 {
255 :     // Clear frame buffer
256 :     glClearColor (0, 0, 0, 1);
257 :     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
258 :    
259 :     glDisable(GL_DEPTH_TEST);
260 :     glDisable(GL_CULL_FACE);
261 :    
262 :     // Draw image
263 : jhr 2079 glActiveTexture (GL_TEXTURE0);
264 :     glBindTexture (GL_TEXTURE_2D, txtId);
265 : jhr 3214
266 : jhr 3213 glBindVertexArray (QuadMesh.vaoId);
267 :     glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, QuadMesh.ebufId);
268 :     glDrawElements (GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0);
269 : jhr 2058
270 :     }
271 :    
272 :     // Callback function called by GLFW when window size changes
273 : jhr 3213 void WindowSizeCB (GLFWwindow *win, int width, int height)
274 : jhr 2058 {
275 :     // Set OpenGL viewport and camera
276 :     glViewport(0, 0, width, height);
277 :    
278 :     // remember width and height
279 :     Width = width;
280 :     Height = height;
281 :    
282 : jhr 2080 NeedsRedraw = true;
283 : jhr 2058 }
284 :    
285 : jhr 3213 void KeyCB (GLFWwindow *win, int key, int scancode, int action, int mods)
286 : jhr 2067 {
287 : jhr 2079 switch (key) {
288 : jhr 3213 case GLFW_KEY_ESCAPE:
289 :     glfwSetWindowShouldClose (win, GL_TRUE);
290 :     break;
291 :     case GLFW_KEY_EQUAL: // with shift is '+'
292 :     if ((mods == GLFW_MOD_SHIFT) && (action == GLFW_PRESS) && (Dir >= 0)) {
293 : jhr 2079 Dir++;
294 : jhr 3213 }
295 : jhr 2079 break;
296 : jhr 3213 case GLFW_KEY_KP_ADD:
297 :     if ((mods == 0) && (action == GLFW_PRESS) && (Dir >= 0))
298 :     Dir++;
299 :     break;
300 :     case GLFW_KEY_MINUS:
301 :     case GLFW_KEY_KP_SUBTRACT:
302 :     if ((mods == 0) && (action == GLFW_PRESS) && (Dir <= 0))
303 : jhr 2079 Dir--;
304 :     break;
305 :     default:
306 :     break;
307 : jhr 2067 }
308 :     }
309 :    
310 : jhr 2079 void Compute (VR_World_t *wrld, bool fullSize, Nrrd *nRGB)
311 : jhr 2058 {
312 : jhr 3214 printf ("computing %s... ", fullSize ? "" : "(fast) "); fflush(stdout);
313 : jhr 2079 double t0 = airTime();
314 :     // setup raycast parameters
315 :     if (fullSize) {
316 :     VR_InVarSet_imgResU (wrld, FULL_WID);
317 :     VR_InVarSet_imgResV (wrld, FULL_HT);
318 :     VR_InVarSet_rayStep (wrld, FULL_STEP);
319 :     }
320 :     else {
321 :     VR_InVarSet_imgResU (wrld, REDUCED_WID);
322 :     VR_InVarSet_imgResV (wrld, REDUCED_HT);
323 :     VR_InVarSet_rayStep (wrld, REDUCED_STEP);
324 :     }
325 :     // recompute
326 :     if (VR_Initially (wrld)) {
327 :     // error
328 :     fprintf(stderr, "Error initializing world: %s", VR_GetErrors(wrld));
329 :     exit(1);
330 :     }
331 :     int nSteps = VR_Run (wrld, 0);
332 :     printf(" %d steps in %5.3f seconds\n", nSteps, airTime() - t0);
333 :     // get output image
334 : jhr 2063 if (VR_OutputGet_outRGBA (wrld, nRGB)) {
335 : jhr 2058 // error
336 : jhr 2079 fprintf(stderr, "Error getting nrrd data: %s", VR_GetErrors(wrld));
337 : jhr 2063 exit(1);
338 : jhr 2058 }
339 :     }
340 :    
341 : jhr 3213 static void Error (int err, const char *msg)
342 :     {
343 :     fprintf(stderr, "[GLFW ERROR %d] %s\n", err, msg);
344 :     }
345 :    
346 : jhr 2058 int main (int argc, const char **argv)
347 :     {
348 : jhr 3213 glfwSetErrorCallback (Error);
349 :    
350 : jhr 2058 // Initialize GLFW
351 :     if (0 == glfwInit()) {
352 :     // An error occured
353 :     fprintf(stderr, "GLFW initialization failed\n");
354 :     return 1;
355 :     }
356 :    
357 : jhr 3213 glfwWindowHint (GLFW_RESIZABLE, GL_TRUE);
358 :     glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 4);
359 :     glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 1);
360 :     glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
361 :     glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
362 :     GLFWwindow *win = glfwCreateWindow(WIDTH, HEIGHT, "Diderot VR Demo", NULL, NULL);
363 :     if (win== 0) {
364 : jhr 2058 // A fatal error occured
365 :     fprintf(stderr, "Cannot open GLFW window\n");
366 :     glfwTerminate();
367 :     return 1;
368 :     }
369 : jhr 3213 glfwMakeContextCurrent (win);
370 : jhr 2058
371 : jhr 3213 InitGraphics ();
372 :    
373 : jhr 2058 // Set GLFW event callbacks
374 : jhr 3213 glfwSetWindowSizeCallback (win, WindowSizeCB);
375 :     glfwSetKeyCallback (win, KeyCB);
376 : jhr 2058
377 :     // initialize the Diderot program
378 : jhr 3213 VR_World_t *wrld = VR_New ();
379 :     if (wrld == 0) {
380 :     fprintf(stderr, "Cannot create world\n");
381 :     glfwTerminate();
382 :     return 1;
383 :     }
384 : jhr 2067 World = wrld;
385 : jhr 3213 VR_Init (wrld);
386 : jhr 2058
387 : jhr 2067 // initialize inputs
388 : jhr 3213 VR_InVarSet_valOpacMid (wrld, OpacMid);
389 : jhr 2079 VR_InVarSetByName_hand (wrld, "data/vfrhand-nohip.nhdr");
390 : jhr 2067
391 : jhr 2058 // nrrd for getting computational state
392 : jhr 2061 Nrrd *nRGB = nrrdNew();
393 : jhr 2058
394 :     // Main loop (repeated while window is not closed and [ESC] is not pressed)
395 : jhr 2062 NeedsRecompute = true;
396 : jhr 2079 GLuint txtId;
397 : jhr 3213 while (! glfwWindowShouldClose(win)) {
398 : jhr 2079 if (Dir < 0) {
399 :     Dir++;
400 :     float mid = OpacMid - OPAC_DELTA;
401 :     if (mid >= MIN_OPAC_MID) {
402 :     OpacMid = mid;
403 :     VR_InVarSet_valOpacMid(World, mid);
404 :     NeedsRecompute = true;
405 :     }
406 :     }
407 :     else if (Dir > 0) {
408 :     Dir--;
409 :     float mid = OpacMid + OPAC_DELTA;
410 :     if (mid <= MAX_OPAC_MID) {
411 :     OpacMid = mid;
412 :     VR_InVarSet_valOpacMid(World, mid);
413 :     NeedsRecompute = true;
414 :     }
415 :     }
416 : jhr 2061 if (NeedsRecompute) {
417 : jhr 2079 if (Dir != 0) {
418 :     Compute(wrld, false, nRGB);
419 :     InitTexture(&ReducedTexure, nRGB);
420 :     txtId = ReducedTexure.id;
421 : jhr 2067 }
422 : jhr 2079 else {
423 :     Compute (wrld, true, nRGB);
424 :     InitTexture(&FullTexture, nRGB);
425 :     NeedsRecompute = false;
426 :     txtId = FullTexture.id;
427 :     }
428 : jhr 2063 NeedsRedraw = true;
429 : jhr 2061 }
430 :     if (NeedsRedraw) {
431 : jhr 2079 Draw (txtId);
432 : jhr 3213 // Present frame buffer
433 :     glfwSwapBuffers(win);
434 : jhr 2063 NeedsRedraw = false;
435 : jhr 2061 }
436 : jhr 2079 if (NeedsRecompute)
437 :     glfwPollEvents();
438 :     else
439 :     glfwWaitEvents();
440 : jhr 2058 }
441 :    
442 :     // shutdown the world
443 : jhr 2061 VR_Shutdown (wrld);
444 : jhr 2058
445 : jhr 2063 // Terminate GLFW
446 : jhr 2058 glfwTerminate();
447 :    
448 :     return 0;
449 :     }

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0