Example #1
0
void display(void)
{
	kuhl_limitfps(100);
	dgr_update();
	// Make sure slaves get updates ASAP
	dgr_setget("currentTex", &currentTexture, sizeof(int));


	/* If the texture has changed since we were previously in display() */
	if(alreadyDisplayedTexture != currentTexture)
	{
		// Load the new texture
		loadTexture(currentTexture);
		// Keep a record of which texture we are currently displaying
		// so we can detect when DGR changes currentTexture on a
		// slave.
		alreadyDisplayedTexture = currentTexture;
	}

	/* The view frustum is an orthographic frustum for this
	 * application. The size of the frustum doesn't matter much, but
	 * the aspect ratio of the frustum should match the aspect ratio
	 * of the screen/window. */
	float frustum[6], masterFrustum[6];
	
	/* The following two methods will get the master view frustum and
	 * the current process view frustum. If we are running in a
	 * standalone version, these two frustums will be the same. */
	projmat_get_master_frustum(masterFrustum);
	projmat_get_frustum(frustum, -1, -1); // frustum of this process (master or slave)

	/* Set this view frustum for this process. */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(frustum[0],frustum[1],
	        frustum[2],frustum[3],
	        -1, 1);
	glMatrixMode(GL_MODELVIEW);

	// Middle of master frustum in the vertical direction. It divides the top
	// tiles from the bottom tiles.
	float masterFrustumMid = (masterFrustum[2]+masterFrustum[3])/2;
	// Dimensions of the master view frustum
	float masterFrustumWidth  = masterFrustum[1]-masterFrustum[0];
	float masterFrustumHeight = masterFrustum[3]-masterFrustum[2];

	// The width of the quad (in frustum units). Since the image will
	// be stretched to fit the screen vertically, and our units are in
	// frustum units, the width of the tile is the height of the
	// frustum times the aspect ratio divided by the number of tiles
	// in the horizontal direction.
	float quadWidth = aspectRatio * masterFrustumHeight;
	float tileWidth = quadWidth/numTiles;

// TODO: Maybe just scale the image vertically if the image almost fits in the screen horizontally?

	int msSincePictureDisplayed = glutGet(GLUT_ELAPSED_TIME)-lastAdvance;
	int scrollStatus = 0; // 0=don't need to scroll or done scrolling, 1=currently scrolling
	if(masterFrustumWidth < quadWidth)// do we need to scroll on this image
	{
		// Do we still need to scroll?
		if(scrollAmount < quadWidth-masterFrustumWidth)
			scrollStatus = 1;

		if(scrollStatus == 1)
		{
			// Wait a few seconds before scrolling. It takes a while
			// for all slaves on IVS to get the images.
			if(msSincePictureDisplayed > 5000)
				scrollAmount = ((msSincePictureDisplayed-5000) / (SCROLL_SPEED*1000.0))*masterFrustumWidth;
			else
				scrollAmount = 0;

			// If we calculated the scroll amount to be the largest
			// scrollAmount we'll need
			if(scrollAmount > quadWidth-masterFrustumWidth)
			{
				// dwell at the end of the image even if autoadvance is on.
				int now = glutGet(GLUT_ELAPSED_TIME);
				// make sure we still have a few seconds before advancing
				if(SLIDESHOW_WAIT*1000-(now-lastAdvance) < 3000)
				{
					// Go back and set lastAdvance time so we have
					// some time to dwell here.
					lastAdvance = now-SLIDESHOW_WAIT*1000+3000;
				}
			}
		}
	}

	dgr_setget("scrollAmount", &scrollAmount, sizeof(float));

	/* If autoadvance is set and we are not scrolling (or done
	 * scrolling) figure out if it is now time to advance to the next
	 * image. */
	if(autoAdvance == 1 && scrollStatus != 1)
	{
//		printf("time since last advance %d\n", glutGet(GLUT_ELAPSED_TIME)-lastAdvance);
		if(glutGet(GLUT_ELAPSED_TIME)-lastAdvance > SLIDESHOW_WAIT*1000) // time to show new image:
		{
			currentTexture = getNextTexture();
			loadTexture(currentTexture);
			return;
		}
	}

	glClear(GL_COLOR_BUFFER_BIT);
	glEnable(GL_TEXTURE_2D);
	glColor3f(1,1,1); // color of quad

	// Draw the top and bottom quad for each of the tiles going across the screen horizontally. */
	for(GLuint i=0; i<numTiles*2; i=i+2)
	{
		float tileLeft  = (i/2  )*tileWidth + masterFrustum[0];
		float tileRight = (i/2+1)*tileWidth + masterFrustum[0];
		
		// Draw bottom tile
		glBindTexture(GL_TEXTURE_2D, texNames[i]);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0, 0.0); glVertex2d(tileLeft -scrollAmount, masterFrustum[2]); // lower left
		glTexCoord2f(1.0, 0.0); glVertex2d(tileRight-scrollAmount, masterFrustum[2]); // lower right
		glTexCoord2f(1.0, 1.0); glVertex2d(tileRight-scrollAmount, masterFrustumMid); // upper right
		glTexCoord2f(0.0, 1.0); glVertex2d(tileLeft -scrollAmount, masterFrustumMid); // upper left
		glEnd();

		// Draw top tile
		glBindTexture(GL_TEXTURE_2D, texNames[i+1]);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0, 0.0); glVertex2d(tileLeft -scrollAmount, masterFrustumMid); // lower left
		glTexCoord2f(1.0, 0.0); glVertex2d(tileRight-scrollAmount, masterFrustumMid); // lower right
		glTexCoord2f(1.0, 1.0); glVertex2d(tileRight-scrollAmount, masterFrustum[3]); // upper right
		glTexCoord2f(0.0, 1.0); glVertex2d(tileLeft -scrollAmount, masterFrustum[3]); // upper left
		glEnd();
	}

	glDisable(GL_TEXTURE_2D);

	/* Draw filename label on top of a quad. */
	glColor4f(0,0,0,.3);
	glBegin(GL_QUADS);
	glVertex2d(-1,-1);
	glVertex2d(-.5,-1);
	glVertex2d(-.5,-.96);
	glVertex2d(-1,-.96);
	glEnd();

	glColor4f(1,1,1,.9);
	glRasterPos2f(-.98,-.98);
	void *font = GLUT_BITMAP_TIMES_ROMAN_24;
	char *str = globalargv[currentTexture];
	for(GLuint i=0; i<strlen(str); i++)
		glutBitmapCharacter(font, str[i]);

	/* Flush and swap the OpenGL buffers. */
	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();
}
Example #2
0
/* Called by GLUT whenever the window needs to be redrawn. This
 * function should not be called directly by the programmer. Instead,
 * we can call glutPostRedisplay() to request that GLUT call display()
 * at some point. */
void display()
{
	/* If we are using DGR, send or receive data to keep multiple
	 * processes/computers synchronized. */
	dgr_update();

	dgr_setget("style", &renderStyle, sizeof(int));

	
	/* Render the scene once for each viewport. Frequently one
	 * viewport will fill the entire screen. However, this loop will
	 * run twice for HMDs (once for the left eye and once for the
	 * right. */
	viewmat_begin_frame();
	for(int viewportID=0; viewportID<viewmat_num_viewports(); viewportID++)
	{
		viewmat_begin_eye(viewportID);

		/* Where is the viewport that we are drawing onto and what is its size? */
		int viewport[4]; // x,y of lower left corner, width, height
		viewmat_get_viewport(viewport, viewportID);
		glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);

		/* Clear the current viewport. Without glScissor(), glClear()
		 * clears the entire screen. We could call glClear() before
		 * this viewport loop---but on order for all variations of
		 * this code to work (Oculus support, etc), we can only draw
		 * after viewmat_begin_eye(). */
		glScissor(viewport[0], viewport[1], viewport[2], viewport[3]);
		glEnable(GL_SCISSOR_TEST);
		glClearColor(.2,.2,.2,0); // set clear color to grey
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		glDisable(GL_SCISSOR_TEST);
		glEnable(GL_DEPTH_TEST); // turn on depth testing
		kuhl_errorcheck();

		/* Turn on blending (note, if you are using transparent textures,
		   the transparency may not look correct unless you draw further
		   items before closer items.). */
		glEnable(GL_BLEND);
		glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

		/* Get the view or camera matrix; update the frustum values if needed. */
		float viewMat[16], perspective[16];
		viewmat_get(viewMat, perspective, viewportID);

		glUseProgram(program);
		kuhl_errorcheck();
		/* Send the perspective projection matrix to the vertex program. */
		glUniformMatrix4fv(kuhl_get_uniform("Projection"),
		                   1, // number of 4x4 float matrices
		                   0, // transpose
		                   perspective); // value

		float modelMat[16];
		get_model_matrix(modelMat);
		float modelview[16];
		mat4f_mult_mat4f_new(modelview, viewMat, modelMat); // modelview = view * model

		/* Send the modelview matrix to the vertex program. */
		glUniformMatrix4fv(kuhl_get_uniform("ModelView"),
		                   1, // number of 4x4 float matrices
		                   0, // transpose
		                   modelview); // value

		glUniform1i(kuhl_get_uniform("renderStyle"), renderStyle);
		// Copy far plane value into vertex program so we can render depth buffer.
		float f[6]; // left, right, bottom, top, near>0, far>0
		projmat_get_frustum(f, viewport[2], viewport[3]);
		glUniform1f(kuhl_get_uniform("farPlane"), f[5]);

		kuhl_errorcheck();

		kuhl_limitfps(60);
		update();
		kuhl_geometry_draw(modelgeom); /* Draw the model */
		kuhl_errorcheck();

		glUseProgram(0); // stop using a GLSL program.

	} // finish viewport loop
	viewmat_end_frame();
	

	/* Check for errors. If there are errors, consider adding more
	 * calls to kuhl_errorcheck() in your code. */
	kuhl_errorcheck();

	// kuhl_video_record("videoout", 30);
	
	/* Ask GLUT to call display() again. We shouldn't call display()
	 * ourselves recursively because it will not leave time for GLUT
	 * to call other callback functions for when a key is pressed, the
	 * window is resized, etc. */
	glutPostRedisplay();
}