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

SCM Repository

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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3213 - (download) (as text) (annotate)
Tue Jul 14 17:16:25 2015 UTC (3 years, 8 months ago) by jhr
File size: 10239 byte(s)
  working on porting the vr-demo code to use GLFW3 and modern OpenGL.
/*! \file main.c
 *
 * \author John Reppy
 *
 * Main program for Diderot VR viewer.
 */

/*
 * COPYRIGHT (c) 2012 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * 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)

static inline void CheckError (const char *msg)
{
    GLenum errCode;
    if ((errCode = glGetError()) != GL_NO_ERROR) {
	fprintf(stderr, "[GL ERROR %04x] %s\n", errCode, msg);
	exit (1);
    }
}

/***** 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
	glGenTextures (1, &(txt->id));

      // load the texture data
	glBindTexture (GL_TEXTURE_2D, txt->id);
	glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, txt->wid, txt->ht, 0, GL_RGBA, GL_FLOAT, img->data);
	CheckError("texture initialization");
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	CheckError("texture parameter initialization");
    }
    else {
      // reload the texture data
	glBindTexture (GL_TEXTURE_2D, txt->id);
	glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, txt->wid, txt->ht, GL_RGBA, GL_FLOAT, img->data);
	CheckError("texture binding");
    }
}

#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\
out smooth 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\
in smooth vec2	texCoord;\n\
layout (location = 0) out vec4 fragColor;\n\
void main ()\n\
{\n\
    fragColor = vec4(texture(image, texCoord).rgb, 1);\n\
}\n\
    ";

// 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);

    GLuint fsh = glCreateShader (GL_FRAGMENT_SHADER);
    glShaderSource (fsh, 1, &FragShaderSrc, 0);
    glCompileShader (fsh);

    GLuint shaderProg = glCreateProgram ();
    glAttachShader (shaderProg, vsh);
    glAttachShader (shaderProg, fsh);
    glLinkProgram (shaderProg);

    glUseProgram (shaderProg);

  // initialize the VBO
    GLuint vaoId, buffers[2];
    glGenVertexArrays (1, &vaoId);
    glGenBuffers (2, buffers);
    glBindVertexArray (vaoId);

    glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
    glBufferData (GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW);
    glVertexAttribPointer (COORD_ATTR, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray (COORD_ATTR);

    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
    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);

    CheckError ("drawing");
}

// 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");

  // create initial strands
    VR_Initially (wrld);

  // 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