SCM Repository
View of /examples/vr-demo/main.c
Parent Directory
|
Revision Log
Revision 3349 -
(download)
(as text)
(annotate)
Tue Oct 27 15:16:36 2015 UTC (6 years, 8 months ago) by jhr
File size: 11634 byte(s)
Tue Oct 27 15:16:36 2015 UTC (6 years, 8 months ago) by jhr
File size: 11634 byte(s)
making copyrights consistent for all code in the repository
/*! \file main.c * * \author John Reppy * * Main program for Diderot VR viewer. */ /* * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu) * * COPYRIGHT (c) 2015 The University of Chicago * All rights reserved. */ #define GL_GLEXT_PROTOTYPES #define GLFW_INCLUDE_GLCOREARB #include <GLFW/glfw3.h> #if defined(__APPLE_CC__) #include <OpenGL/glext.h> #else # include <GL/glext.h> #endif #include "util.h" #include "vr.h" #include <unistd.h> #include "teem/air.h" /* minimum and maximum values from */ #define MIN_VALUE 0 #define MAX_VALUE 2632 /* half the width of the opacity range */ #define OPAC_HALF_WID 150 #define MIN_OPAC_MID ((float)(MIN_VALUE+OPAC_HALF_WID)) #define MAX_OPAC_MID ((float)(MAX_VALUE-OPAC_HALF_WID)) #define OPAC_DELTA 25 /* reduced-size inputs */ #define REDUCED_WID 256 #define REDUCED_HT 184 #define REDUCED_STEP 1 /* full-size inputs */ #define FULL_WID 512 #define FULL_HT 368 #define FULL_STEP 0.5 #define WIDTH (2*FULL_WID) #define HEIGHT (2*FULL_HT) void ReportError (GLenum err, const char *file, int line, const char *msg) { const char *error; switch (err) { case GL_INVALID_ENUM: error = "invalid enum"; break; case GL_INVALID_VALUE: error = "invalid value"; break; case GL_INVALID_OPERATION: error = "invalid operation"; break; case GL_INVALID_FRAMEBUFFER_OPERATION: error = "invalid framebuffer operation"; break; case GL_OUT_OF_MEMORY: error = "out of memory"; break; default: error = "unknown"; break; } fprintf (stderr, "[%s:%d] %s; %s\n", file, line, error, msg); exit (1); } static inline void CheckError (const char *file, int line, const char *msg) { GLenum errCode; if ((errCode = glGetError()) != GL_NO_ERROR) { ReportError (errCode, file, line, msg); } } #define CHECK(cmd) \ do { \ cmd; \ CheckError (__FILE__, __LINE__, "executing " #cmd); \ } while (0) /***** Globals for viewing, etc. *****/ typedef struct { bool init; GLuint wid; GLuint ht; GLuint id; } TexInfo_t; VR_World_t *World; unsigned int Width; // view window width unsigned int Height; // view window height TexInfo_t ReducedTexure = { // Texture ID of reduced image false, REDUCED_WID, REDUCED_HT, 0 }; TexInfo_t FullTexture = { // Texture ID of full image false, FULL_WID, FULL_HT, 0 }; struct { GLuint vaoId; GLuint coordId; GLuint ebufId; } QuadMesh; bool NeedsRedraw; bool NeedsRecompute; float OpacMid = 550.0; int Dir = 0; /* -1, 0, 1 */ // initialize a texture from a grayscale Nrrd file void InitTexture (TexInfo_t *txt, Nrrd *img) { if (! txt->init) { // generate the TeXID CHECK( glGenTextures (1, &(txt->id)) ); // load the texture data CHECK( glBindTexture (GL_TEXTURE_2D, txt->id) ); CHECK( glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, txt->wid, txt->ht, 0, GL_RGBA, GL_FLOAT, img->data) ); CHECK( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) ); CHECK( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ); } else { // reload the texture data CHECK( glBindTexture (GL_TEXTURE_2D, txt->id) ); CHECK( glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, txt->wid, txt->ht, GL_RGBA, GL_FLOAT, img->data) ); } } #define COORD_ATTR 0 // vertex shader static const char *VertexShaderSrc = "\ #version 410\n\ uniform mat4 modelView;\n\ uniform mat4 projection;\n\ layout (location = 0) in vec2 coord;\n\ smooth out vec2 texCoord;\n\ \n\ void main ()\n\ {\n\ gl_Position = projection * modelView * vec4(coord, 0, 1);\n\ texCoord = coord;\n\ }\n\ "; // fragment shader static const char *FragShaderSrc = "\ #version 410\n\ uniform sampler2D image;\n\ smooth in vec2 texCoord;\n\ layout (location = 0) out vec4 fragColor;\n\ void main ()\n\ {\n\ fragColor = vec4(texture(image, texCoord).rgb, 1);\n\ }\n\ "; static void CheckCompileStatus (const char *shader, GLuint id) { GLint sts; glGetShaderiv (id, GL_COMPILE_STATUS, &sts); if (sts != GL_TRUE) { /* the compile failed, so report an error */ glGetShaderiv (id, GL_INFO_LOG_LENGTH, &sts); if (sts != 0) { GLchar *log = (GLchar *) malloc(sts); glGetShaderInfoLog (id, sts, 0, log); fprintf (stderr, "Error compiling %s shader:\n%s\n", shader, log); free (log); } else { fprintf (stderr, "Error compiling %s shader:\n no log\n", shader); } exit (1); } } // Initialize the rendering context // static void InitGraphics () { float coords[4 * 2] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, }; unsigned short indices[4] = {0, 1, 2, 3}; // initialize the shader program GLuint vsh = glCreateShader (GL_VERTEX_SHADER); glShaderSource (vsh, 1, &VertexShaderSrc, 0); glCompileShader (vsh); CheckCompileStatus ("vertex", vsh); GLuint fsh = glCreateShader (GL_FRAGMENT_SHADER); glShaderSource (fsh, 1, &FragShaderSrc, 0); glCompileShader (fsh); CheckCompileStatus ("fragment", fsh); GLuint shaderProg = glCreateProgram (); CHECK( glAttachShader (shaderProg, vsh) ); CHECK( glAttachShader (shaderProg, fsh) ); CHECK( glLinkProgram (shaderProg) ); CHECK( glUseProgram (shaderProg) ); // initialize the VBO GLuint vaoId, buffers[2]; CHECK( glGenVertexArrays (1, &vaoId) ); CHECK( glGenBuffers (2, buffers) ); CHECK( glBindVertexArray (vaoId) ); CHECK( glBindBuffer (GL_ARRAY_BUFFER, buffers[0]) ); CHECK( glBufferData (GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW) ); CHECK( glVertexAttribPointer (COORD_ATTR, 2, GL_FLOAT, GL_FALSE, 0, 0) ); CHECK( glEnableVertexAttribArray (COORD_ATTR) ); CHECK( glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffers[1]) ); CHECK( glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW) ); QuadMesh.vaoId = vaoId; QuadMesh.coordId = buffers[0]; QuadMesh.ebufId = buffers[1]; // initialize the transformation matrices float projMat[16] = { // gluOrtho2D (0.0, 1.0, 0.0, 1.0); 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, -2, 0, -1, -1, 0, 1, }; float modelViewMat[16] = { // gluLookAt (0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, }; glUniformMatrix4fv (glGetUniformLocation (shaderProg, "projection"), 1, GL_FALSE, projMat); glUniformMatrix4fv (glGetUniformLocation (shaderProg, "modelView"), 1, GL_FALSE, modelViewMat); // initialize texture binding glUniform1i (glGetUniformLocation (shaderProg, "image"), 0); // texture unit 0 } // Callback function called by GLUT to render screen void Draw (GLuint txtId) { // Clear frame buffer glClearColor (0, 0, 0, 1); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Draw image glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, txtId); glBindVertexArray (QuadMesh.vaoId); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, QuadMesh.ebufId); glDrawElements (GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0); } // Callback function called by GLFW when window size changes void WindowSizeCB (GLFWwindow *win, int width, int height) { // Set OpenGL viewport and camera glViewport(0, 0, width, height); // remember width and height Width = width; Height = height; NeedsRedraw = true; } void KeyCB (GLFWwindow *win, int key, int scancode, int action, int mods) { switch (key) { case GLFW_KEY_ESCAPE: glfwSetWindowShouldClose (win, GL_TRUE); break; case GLFW_KEY_EQUAL: // with shift is '+' if ((mods == GLFW_MOD_SHIFT) && (action == GLFW_PRESS) && (Dir >= 0)) { Dir++; } break; case GLFW_KEY_KP_ADD: if ((mods == 0) && (action == GLFW_PRESS) && (Dir >= 0)) Dir++; break; case GLFW_KEY_MINUS: case GLFW_KEY_KP_SUBTRACT: if ((mods == 0) && (action == GLFW_PRESS) && (Dir <= 0)) Dir--; break; default: break; } } void Compute (VR_World_t *wrld, bool fullSize, Nrrd *nRGB) { printf ("computing %s... ", fullSize ? "" : "(fast) "); fflush(stdout); double t0 = airTime(); // setup raycast parameters if (fullSize) { VR_InVarSet_imgResU (wrld, FULL_WID); VR_InVarSet_imgResV (wrld, FULL_HT); VR_InVarSet_rayStep (wrld, FULL_STEP); } else { VR_InVarSet_imgResU (wrld, REDUCED_WID); VR_InVarSet_imgResV (wrld, REDUCED_HT); VR_InVarSet_rayStep (wrld, REDUCED_STEP); } // recompute if (VR_Initially (wrld)) { // error fprintf(stderr, "Error initializing world: %s", VR_GetErrors(wrld)); exit(1); } int nSteps = VR_Run (wrld, 0); printf(" %d steps in %5.3f seconds\n", nSteps, airTime() - t0); // get output image if (VR_OutputGet_outRGBA (wrld, nRGB)) { // error fprintf(stderr, "Error getting nrrd data: %s", VR_GetErrors(wrld)); exit(1); } } static void Error (int err, const char *msg) { fprintf(stderr, "[GLFW ERROR %d] %s\n", err, msg); } int main (int argc, const char **argv) { glfwSetErrorCallback (Error); // Initialize GLFW if (0 == glfwInit()) { // An error occured fprintf(stderr, "GLFW initialization failed\n"); return 1; } glfwWindowHint (GLFW_RESIZABLE, GL_TRUE); glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); GLFWwindow *win = glfwCreateWindow(WIDTH, HEIGHT, "Diderot VR Demo", NULL, NULL); if (win== 0) { // A fatal error occured fprintf(stderr, "Cannot open GLFW window\n"); glfwTerminate(); return 1; } glfwMakeContextCurrent (win); InitGraphics (); // Set GLFW event callbacks glfwSetWindowSizeCallback (win, WindowSizeCB); glfwSetKeyCallback (win, KeyCB); // initialize the Diderot program VR_World_t *wrld = VR_New (); if (wrld == 0) { fprintf(stderr, "Cannot create world\n"); glfwTerminate(); return 1; } World = wrld; VR_Init (wrld); // initialize inputs VR_InVarSet_valOpacMid (wrld, OpacMid); VR_InVarSetByName_hand (wrld, "data/vfrhand-nohip.nhdr"); // nrrd for getting computational state Nrrd *nRGB = nrrdNew(); // Main loop (repeated while window is not closed and [ESC] is not pressed) NeedsRecompute = true; GLuint txtId; while (! glfwWindowShouldClose(win)) { if (Dir < 0) { Dir++; float mid = OpacMid - OPAC_DELTA; if (mid >= MIN_OPAC_MID) { OpacMid = mid; VR_InVarSet_valOpacMid(World, mid); NeedsRecompute = true; } } else if (Dir > 0) { Dir--; float mid = OpacMid + OPAC_DELTA; if (mid <= MAX_OPAC_MID) { OpacMid = mid; VR_InVarSet_valOpacMid(World, mid); NeedsRecompute = true; } } if (NeedsRecompute) { if (Dir != 0) { Compute(wrld, false, nRGB); InitTexture(&ReducedTexure, nRGB); txtId = ReducedTexure.id; } else { Compute (wrld, true, nRGB); InitTexture(&FullTexture, nRGB); NeedsRecompute = false; txtId = FullTexture.id; } NeedsRedraw = true; } if (NeedsRedraw) { Draw (txtId); // Present frame buffer glfwSwapBuffers(win); NeedsRedraw = false; } if (NeedsRecompute) glfwPollEvents(); else glfwWaitEvents(); } // shutdown the world VR_Shutdown (wrld); // Terminate GLFW glfwTerminate(); return 0; }
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |