Ejemplo n.º 1
0
void clampPaddles()
{
	float frustum[6];
	projmat_get_frustum(frustum, -1, -1);

    // left screen boundary
	if(paddleA.xpos < frustum[0]+paddleA.width/2)
		paddleA.xpos = frustum[0]+paddleA.width/2;
	if(paddleB.xpos < frustum[0]+paddleB.width/2)
		paddleB.xpos = frustum[0]+paddleB.width/2;
	// right screen boundary
	if(paddleA.xpos > frustum[1]-paddleA.width/2)
		paddleA.xpos = frustum[1]-paddleA.width/2;
	if(paddleB.xpos > frustum[1]-paddleB.width/2)
		paddleB.xpos = frustum[1]-paddleB.width/2;
}
Ejemplo n.º 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();

	glClearColor(.2,.2,.2,0); // set clear color to grey
	// Clear the screen to black, clear the depth buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST); // turn on depth testing
	kuhl_errorcheck();

	/* 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. */
	for(int viewportID=0; viewportID<viewmat_num_viewports(); 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]);

		/* Get the frustum information which will be later used to generate a perspective projection matrix. */
		float f[6]; // left, right, top, bottom, near>0, far>0
		projmat_get_frustum(f, viewport[2], viewport[3]);
	    
		/* Get the view or camera matrix; update the frustum values if needed. */
		float viewMat[16];
		viewmat_get(viewMat, f, viewportID);

		/* Create a 4x4 perspective projection matrix from the frustum values. */
		float perspective[16];
		mat4f_frustum_new(perspective,f[0], f[1], f[2], f[3], f[4], f[5]);
	    
		/* Calculate an angle to rotate the
		 * object. glutGet(GLUT_ELAPSED_TIME) is the number of
		 * milliseconds since glutInit() was called. */
		int count = glutGet(GLUT_ELAPSED_TIME) % 10000; // get a counter that repeats every 10 seconds
		float angle = count / 10000.0 * 360; // rotate 360 degrees every 10 seconds
		/* Make sure all computers/processes use the same angle */
		dgr_setget("angle", &angle, sizeof(GLfloat));
		/* Create a 4x4 rotation matrix based on the angle we computed. */
		float rotateMat[16];
		mat4f_rotateAxis_new(rotateMat, angle, 0,1,0);

		/* Create a scale matrix. */
		float scaleMatrix[16];
		mat4f_scale_new(scaleMatrix, 3, 3, 3);

		// Modelview = (viewMatrix * scaleMatrix) * rotationMatrix
		float modelview[16];
		mat4f_mult_mat4f_new(modelview, viewMat, scaleMatrix);
		mat4f_mult_mat4f_new(modelview, modelview, rotateMat);

		kuhl_errorcheck();
		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
		/* Send the modelview matrix to the vertex program. */
		glUniformMatrix4fv(kuhl_get_uniform("ModelView"),
		                   1, // number of 4x4 float matrices
		                   0, // transpose
		                   modelview); // value
		kuhl_errorcheck();
		/* Draw the geometry using the matrices that we sent to the
		 * vertex programs immediately above */
		kuhl_geometry_draw(&triangle);
		kuhl_geometry_draw(&quad);

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

	} // finish viewport loop

	/* Check for errors. If there are errors, consider adding more
	 * calls to kuhl_errorcheck() in your code. */
	kuhl_errorcheck();
    
	/* Display the buffer we just drew (necessary for double buffering). */
	glutSwapBuffers();

	/* 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();
}
Ejemplo n.º 3
0
void display()
{
	/* If we are using DGR, send or receive data to keep multiple
	 * processes/computers synchronized. */
	dgr_update();

	/* Get current frames per second calculations. */
	float fps = kuhl_getfps(&fps_state);

	if(dgr_is_enabled() == 0 || dgr_is_master())
	{
		// If DGR is being used, only display dgr counter if we are
		// the master process.

		// Check if FPS value was just updated by kuhl_getfps()
		if(fps_state.frame == 0)
		{
			char label[1024];
			snprintf(label, 1024, "FPS: %0.1f", fps);

			/* Delete old label if it exists */
			if(fpsLabel != 0) 
				glDeleteTextures(1, &fpsLabel);

			/* Make a new label */
			float labelColor[3] = { 1,1,1 };
			float labelBg[4] = { 0,0,0,.3 };
			/* Change the last parameter (point size) to adjust the
			 * size of the texture that the text is rendered in to. */
			fpsLabelAspectRatio = kuhl_make_label(label,
			                                      &fpsLabel,
			                                      labelColor, labelBg, 24);

			if(fpsLabel != 0)
				kuhl_geometry_texture(&labelQuad, fpsLabel, "tex", 1);
		}
	}
	
	/* Ensure the slaves use the same render style as the master
	 * process. */
	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_geometry_draw(modelgeom); /* Draw the model */
		kuhl_errorcheck();
		if(showOrigin)
		{
			/* Save current line width */
			GLfloat origLineWidth;
			glGetFloatv(GL_LINE_WIDTH, &origLineWidth);
			glLineWidth(4); // make lines thick
			
			/* Object coordinate system origin */
			kuhl_geometry_draw(origingeom); /* Draw the origin marker */

			/* World coordinate origin */
			mat4f_copy(modelview, viewMat);
			glUniformMatrix4fv(kuhl_get_uniform("ModelView"),
			                   1, // number of 4x4 float matrices
			                   0, // transpose
			                   modelview); // value
			kuhl_geometry_draw(origingeom); /* Draw the origin marker */

			/* Restore line width */
			glLineWidth(origLineWidth);
		}


		if(dgr_is_enabled() == 0 || dgr_is_master())
		{

			/* The shape of the frames per second quad depends on the
			 * aspect ratio of the label texture and the aspect ratio of
			 * the window (because we are placing the quad in normalized
			 * device coordinates). */
			int windowWidth, windowHeight;
			viewmat_window_size(&windowWidth, &windowHeight);
			float windowAspect = windowWidth / (float)windowHeight;
			
			float stretchLabel[16];
			mat4f_scale_new(stretchLabel, 1/8.0 * fpsLabelAspectRatio / windowAspect, 1/8.0, 1);

			/* Position label in the upper left corner of the screen */
			float transLabel[16];
			mat4f_translate_new(transLabel, -.9, .8, 0);
			mat4f_mult_mat4f_new(modelview, transLabel, stretchLabel);
			glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, 0, modelview);

			/* Make sure we don't use a projection matrix */
			float identity[16];
			mat4f_identity(identity);
			glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, 0, identity);

			/* Don't use depth testing and make sure we use the texture
			 * rendering style */
			glDisable(GL_DEPTH_TEST);
			glUniform1i(kuhl_get_uniform("renderStyle"), 1);
			kuhl_geometry_draw(&labelQuad); /* Draw the quad */
			glEnable(GL_DEPTH_TEST);
			kuhl_errorcheck();
		}

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

	} // finish viewport loop
	viewmat_end_frame();
	
	/* Update the model for the next frame based on the time. We
	 * convert the time to seconds and then use mod to cause the
	 * animation to repeat. */
	int time = glutGet(GLUT_ELAPSED_TIME);
	dgr_setget("time", &time, sizeof(int));
	kuhl_update_model(modelgeom, 0, ((time%10000)/1000.0));

	/* 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();
}
Ejemplo n.º 4
0
void display()
{
	/* If we are using DGR, send or receive data to keep multiple
	 * processes/computers synchronized. */
	dgr_update();
		
	/* Syncronize the DGR objects */
	dgr_setget("paddleA", &paddleA, sizeof(Paddle));
	dgr_setget("paddleB", &paddleB, sizeof(Paddle));
	dgr_setget("ball", &ball, sizeof(Ball));
	dgr_setget("planet", planet, sizeof(float)*3);
	dgr_setget("state", &gameState, sizeof(int));

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_NORMALIZE);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_TEXTURE_2D);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glColor3f(1,1,1);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	float frustum[6];
	projmat_get_frustum(frustum, -1, -1);
	glOrtho(frustum[0], frustum[1], frustum[2], frustum[3], frustum[4], frustum[5]);
	  
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Pick a depth that is between the near and far planes.
	float depth = -(frustum[4] + frustum[5])/2.0;

	// Move the light source
	GLfloat position[] = { 1.0f, -1.0f, depth+5.5f, 1.0f };
	glLightfv(GL_LIGHT0, GL_POSITION, position);
	

	// Draw the background stars
	float masterfrust[6];
	projmat_get_master_frustum(masterfrust);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindTexture(GL_TEXTURE_2D, texIdStars);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	
	// Draw the background quad with the scrolling star texture
	float tickmod = ticks / 200.0f;
	glBegin(GL_QUADS);
	glTexCoord2f(tickmod+1.0f, -tickmod);
	glVertex3f(masterfrust[1], masterfrust[3], depth-3.0);
	glTexCoord2f(tickmod, -tickmod);
	glVertex3f(masterfrust[0], masterfrust[3], depth-3.0);
	glTexCoord2f(tickmod, 1.0f-tickmod);
	glVertex3f(masterfrust[0], masterfrust[2], depth-3.0);
	glTexCoord2f(tickmod+1.0f, 1.0f-tickmod);

	glVertex3f(masterfrust[1], masterfrust[2], depth-3.0);
	glEnd();
	
	//Draw the earth   
   	glMatrixMode(GL_MODELVIEW);
   	glPushMatrix();
    glBindTexture(GL_TEXTURE_2D, texIdEarth);
	glTranslatef(planet[0], planet[1], depth-3.0);
	glRotatef(25.0f, 0.0f, 0.0f, 1.0f);
	glRotatef(-90, 1.0f, 0.0f, 0.0f);
	glRotatef(ticks, 0.0f, 0.0f, 1.0f);
	ticks += .005;
	if(ticks > 360.0f)ticks = 0.0f;
	gluSphere(earth, planet[2]*1.65f, 200, 200);
	glPopMatrix();
    
    //Draw the clouds
   	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);   
   	glPushMatrix();
    glBindTexture(GL_TEXTURE_2D, texIdClouds);
    glLoadIdentity();
	glTranslatef(planet[0], planet[1], depth-3.0);
	glRotatef(25.0f, 0.0f, 0.0f, 1.0f);
	glRotatef(-90, 1.0f, 0.0f, 0.0f);
	glRotatef(ticks, 1.0f, 0.0f, 1.0f);
	gluSphere(clouds, planet[2]*1.652f, 200, 200);
	glPopMatrix();
	
    // Reset somethings for the rest of the scene
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   
	
	// top player (player 1) paddle	
	drawPaddle(paddleA, depth+5.0f);

	// bottom player (player 2) paddle
	drawPaddle(paddleB, depth+5.0f);
	
	glDisable(GL_BLEND);
	
	// ball
	glEnable(GL_LIGHTING);
    glColor3fv(ball.color);
	glPushMatrix();
	glTranslatef(ball.xpos, ball.ypos, depth+4.0f);
	glutSolidSphere(ball.radius, 100, 100);
	glPopMatrix();
	
	/* If DGR is enabled, only do this in the master*/
	if(dgr_is_enabled() == 0 || dgr_is_master())
	{
		// Run the game code
		game();	
	}
	
	glFlush();
	glutSwapBuffers();
	glutPostRedisplay(); // call display() repeatedly
}
Ejemplo n.º 5
0
int main( int argc, char* argv[] )
{	
	/* Initialize glut */
	glutInit(&argc, argv); //initialize the toolkit
	glEnable(GL_POINT_SMOOTH);
	glutSetOption(GLUT_MULTISAMPLE, 4); // set msaa samples; default to 4
	
	/* Ask GLUT to for a double buffered, full color window that includes a depth buffer */
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE);  //set display mode
	glutInitWindowSize(768, 512); //set window size
	glutInitWindowPosition(0, 0); //set window position on screen
	glutCreateWindow(argv[0]); //open the screen window
	glEnable(GL_MULTISAMPLE);
	
	/* Initialize glew */
	int glew_err = glewInit();
	if(glew_err != GLEW_OK)
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(glew_err));

	/* Initialize call backs */
	glutDisplayFunc(display);
	glutKeyboardFunc(keyboard);
	
	/* Initialize DGR */
	dgr_init();     /* Initialize DGR based on environment variables. */
	projmat_init(); /* Figure out which projection matrix we should use based on environment variables */

	float frustum[6]; // left, right, bottom, top, near, far
	                  // 0     1      2       3    4     5
	projmat_get_frustum(frustum, -1, -1);
	ball.xpos = (frustum[0] + frustum[1])/2.0;
	ball.ypos = (frustum[2] + frustum[3])/2.0;
	ball.speed = ball.minSpeed = (frustum[3]-frustum[2]) / 178.462f;
	
	paddleA.xpos = ball.xpos;
	paddleA.ypos = frustum[3]-(frustum[3]-frustum[2])/20.0;
	paddleA.width = (frustum[1]-frustum[0])/10.0;
	paddleA.increment = paddleA.width / 3.0;
	paddleA.thickness = (frustum[3]-frustum[2])/25.0;
	
	paddleB.xpos = paddleA.xpos;
	paddleB.ypos = frustum[2]+(frustum[3]-frustum[2])/20.0;
	paddleB.width = paddleA.width;
	paddleB.increment = paddleA.increment;
	paddleB.thickness = -paddleA.thickness;
	
	msg(INFO, "Initial ball position %f %f\n", ball.xpos, ball.ypos);
	msg(INFO, "Initial Ball speed: %f\n", frustum[3]-frustum[2], ball.speed);
	msg(INFO, "Initial paddle A position %f %f\n", paddleA.xpos, paddleA.ypos);
	msg(INFO, "Initial paddle B position %f %f\n", paddleB.xpos, paddleB.ypos);

	ball.radius = (frustum[1]-frustum[0])/50.0;
	
	planet[0] = ((frustum[0] + frustum[1])/2.0f) - ((frustum[1] - frustum[0])/2.4f);
	planet[1] = ((frustum[2] + frustum[3])/2.0f) - ((frustum[1] - frustum[0])*1.7f);
	planet[2] = (frustum[1] - frustum[0]);
	
	earth = gluNewQuadric();
	clouds = gluNewQuadric();
	gluQuadricDrawStyle(earth, GLU_FILL);
	gluQuadricTexture(earth, GL_TRUE);
	gluQuadricNormals(earth, GLU_SMOOTH);
	gluQuadricDrawStyle(clouds, GLU_FILL);
	gluQuadricTexture(clouds, GL_TRUE);
	gluQuadricNormals(clouds, GLU_SMOOTH);
		
	kuhl_read_texture_file(EARTH, &texIdEarth);
	kuhl_read_texture_file(CLOUDS, &texIdClouds);
	kuhl_read_texture_file(STARS, &texIdStars);

	glutMainLoop();
	
}
Ejemplo n.º 6
0
void game()
{
	float frustum[6];
	projmat_get_frustum(frustum, -1, -1);

	if(USE_VRPN)
	{
		vrpn_get(TRACKED_OBJ_A, NULL, vrpnPos, vrpnOrient);
		paddleA.xpos = vrpnPos[0];
		if(vrpnPos[1] <= .5)
			paddleA.ready = true;
		
		vrpn_get(TRACKED_OBJ_B, NULL, vrpnPos, vrpnOrient);
		paddleB.xpos = vrpnPos[0];
		if(vrpnPos[1] <= .5)
			paddleB.ready = true;
	}
	
	//Preform the action based on the game state
	switch(gameState)
	{
		//This state indicates that atleast one player is not ready
		case GS_WAITING:
	
			//When both players are ready, shift to the ready state
			if(paddleA.ready && paddleB.ready)
			{
				startTime = time(NULL);
				gameState = GS_READY;
			}
			else
			{
				// Reset the ball to it's starting state
				ball.xpos = (frustum[0]+frustum[1])/2.0;
				ball.ypos = (frustum[2]+frustum[3])/2.0;
				ball.xdir = 0;
				ball.ydir = 0;
				ball.color[0] = ball.baseColor[0];
				ball.color[1] = ball.baseColor[1];
				ball.color[2] = ball.baseColor[2];
			}
			break;
			
		//This state indicates that both players are ready to play
		case GS_READY:
		
			//We should wait in this state for 2 seconds
			if(time(NULL)-startTime >= 2)
			{
				//Start the ball moving either up or down.
				srand48(startTime);
				ball.ydir = 1;
				if(drand48() < .5)
					ball.ydir = -1;
				gameState = GS_PLAYING;
			}
			break;
			
		//This state indicates that the game is currently being played
		case GS_PLAYING:
			
			// Move the ball
			ball.xpos += ball.xdir * ball.speed;
			ball.ypos += ball.ydir * ball.speed;
	
			//Make sure the ball has not slowed down too much
			if(ball.speed < ball.minSpeed)
			{
				ball.speed = ball.minSpeed;
			}

			bool isBounce = false;
	
			//Handle the sides of the play area
			if(ball.xpos-ball.radius < frustum[0]) // left wall
			{
				ball.xpos = frustum[0]+ball.radius;
				ball.xdir = -ball.xdir;
				isBounce = true;
			}

			if(ball.xpos+ball.radius > frustum[1]) // right wall
			{
				ball.xpos = frustum[1]-ball.radius;
				ball.xdir = -ball.xdir;
				isBounce = true;
			}
	
	
			// Handle the Top and the bottom of the play area
			if(ball.ypos > frustum[3] || ball.ypos < frustum[2]) // top orr bottom wall
			{
				gameState = GS_SCORED;
				break;
			}

			
			// check for player 1 (top) paddle hit
			if(ball.ypos > paddleA.ypos-ball.radius && ball.ydir > 0)
			{
				// if we hit paddle
				if(ball.xpos+ball.radius*.9 > paddleA.xpos-paddleA.width/2 &&
				   ball.xpos-ball.radius*.9 < paddleA.xpos+paddleA.width/2)
				{
					ball.ypos = paddleA.ypos-ball.radius;
					ball.ydir = -ball.ydir;
					isBounce = true;
					ball.bounceCount++;
				}
			}

			// check for player 2 (bottom) paddle hit
			if(ball.ypos < paddleB.ypos+ball.radius && ball.ydir < 0)
			{
				// if we hit paddle
				if(ball.xpos+ball.radius*.9 > paddleB.xpos-paddleB.width/2 &&
				   ball.xpos-ball.radius*.9 < paddleB.xpos+paddleB.width/2)
				{
					ball.ypos = paddleB.ypos+ball.radius;
					ball.ydir = -ball.ydir;
					isBounce = true;
					ball.bounceCount++;
				}
			}
	
			// speedup the ball periodically
			if(ball.bounceCount == ball.speedUp)
			{
				ball.bounceCount = 0;
				ball.speed = ball.speed / .7; // speed up
				ball.speedUp++;
				ball.color[0] = ball.fastColor[0];
				ball.color[1] = ball.fastColor[1];
				ball.color[2] = ball.fastColor[2];
			}
			else // If a speedup didn't happen, make the ball more green
			{
				float step = (float)ball.bounceCount / ((float)ball.speedUp-1);
				ball.color[0] = ball.baseColor[0] + ((ball.fastColor[0] - ball.baseColor[0]) * step);
				ball.color[1] = ball.baseColor[1] + ((ball.fastColor[1] - ball.baseColor[1]) * step);
				ball.color[2] = ball.baseColor[2] + ((ball.fastColor[2] - ball.baseColor[2]) * step);
			}
	
			// add noise to bounces so they don't bounce perfectly.
			if(isBounce)
			{
				// add more noise as game speeds up.
				int scale = ball.speedUp;
				if(scale > 3)
					scale = 3;

				double newXdir;
				double newYdir;
				do
				{
					newXdir = ball.xdir + (drand48()-.5) / 8.0 * scale;
					newYdir = ball.ydir + (drand48()-.5) / 8.0 * scale;
			
					// normalize direction vector
					float dirLength = sqrtf(newXdir*newXdir + newYdir*newYdir);
					newXdir /= dirLength;
					newYdir /= dirLength;

					// Keep trying new values until we find something that
					// isn't moving too much left/right. Also, force bounces
					// to keep the ball bouncing in the same direction
					// vertically.
				} while(fabs(newYdir) < .2 || ball.ydir * newYdir < 0);
				ball.xdir = newXdir;
				ball.ydir = newYdir;
			}
			
			break;
			
		//This state indicates that one player just scored
		case GS_SCORED:
			
			//Reset the bounce count, then figure out who scored
			ball.bounceCount = 0;
			bool paddleAScored = (ball.ypos < frustum[2]);
			
			//Change the paddle widths based on who scored
			paddleA.width += paddleA.increment * (paddleAScored ? 1 :-1);
			paddleB.width += paddleB.increment * (paddleAScored ? -1 :1);
			
			if(paddleA.width < 0.001 || paddleB.width < 0.001)//Check if some one lost the game
			{
				msg(WARNING, "%s Player wins!\n", (paddleAScored ? "Red" : "Blue"));
				
				//Reset the paddles for the next game
				paddleA.width = paddleB.width = (frustum[1]-frustum[0])/10.0;
				
				//Reset the ball for the next game
				ball.speed = ball.minSpeed = (frustum[3]-frustum[2]) / 178.462f;
				ball.speedUp = ball.baseSpeedUp;
			}
			else // Only lost the point, not the game;
			{
				ball.speed *= .7; // slow down
				ball.speedUp--;
			}
			
			//Set the players to not ready and transition to the waiting state
			paddleA.ready = paddleB.ready = false;
			gameState = GS_WAITING;
			break;
	}
}
Ejemplo n.º 7
0
void display()
{
	dgr_update();

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

	// Clear the screen to black, clear the depth buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	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);
	
	/* 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. */
	for(int viewportID=0; viewportID<viewmat_num_viewports(); 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]);

		/* Get the frustum information which will be later used to generate a perspective projection matrix. */
		float f[6]; // left, right, top, bottom, near>0, far>0
		projmat_get_frustum(f, viewport[2], viewport[3]);
	    
		/* Get the view or camera matrix; update the frustum values if needed. */
		float viewMat[16];
		viewmat_get(viewMat, f, viewportID);

		glUseProgram(program);
		/* Communicate matricies to OpenGL */
		float perspective[16];
		mat4f_frustum_new(perspective,f[0], f[1], f[2], f[3], f[4], f[5]);
		glUniformMatrix4fv(kuhl_get_uniform("Projection"),
		                   1, // count
		                   0, // transpose
		                   perspective); // value
		float modelMat[16];
		get_model_matrix(modelMat);
		
		// modelview = view * model
		float modelview[16];
		mat4f_mult_mat4f_new(modelview, viewMat, modelMat);

		glUniformMatrix4fv(kuhl_get_uniform("ModelView"),
		                   1, // count
		                   0, // transpose
		                   modelview); // value

		glUniform1i(kuhl_get_uniform("renderStyle"), renderStyle);
		// Copy far plane value into vertex program so we can render depth buffer.
		glUniform1f(kuhl_get_uniform("farPlane"), f[5]);
		
		kuhl_errorcheck();

		kuhl_draw_model_file_ogl3(modelFilename, modelTexturePath, program);
		kuhl_errorcheck();

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

	} // finish viewport loop

	int time = glutGet(GLUT_ELAPSED_TIME);
	float fps = kuhl_getfps(time);
	if(time % 1000 == 0)
		printf("Frames per second: %0.1f\n", fps);
		
	
	/* Check for errors. If there are errors, consider adding more
	 * calls to kuhl_errorcheck() in your code. */
	kuhl_errorcheck();

	glFlush();
	glFinish();
	
	/* Display the buffer we just drew (necessary for double buffering). */
	glutSwapBuffers();

	// 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();
}
Ejemplo n.º 8
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();
}
Ejemplo n.º 9
0
/** Get a 4x4 view matrix. Some types of systems also need to update
 * the frustum based on where the virtual camera is. For example, on
 * the IVS display wall, the frustum is adjusted dynamically based on
 * where a person is relative to the screens.
 *
 * @param viewmatrix A 4x4 view matrix for viewmat to fill in.
 *
 * @param projmatrix A 4x4 projection matrix for viewmat to fill in.
 *
 * @param viewportID If there is only one viewport, set this to
 * 0. This value must be smaller than the value reported by
 * viewmat_num_viewports(). In an HMD, typically viewportID=0 is the
 * left eye and viewportID=1 is the right eye. However, some Oculus
 * HMDs will result in this being swapped. To definitively know which
 * eye this view matrix corresponds to, examine the return value of
 * this function.
 *
 * @return A viewmat_eye enum which indicates if this view matrix is
 * for the left, right, middle, or unknown eye.
 *
 */
viewmat_eye viewmat_get(float viewmatrix[16], float projmatrix[16], int viewportID)
{
	viewmat_eye eye = viewmat_viewport_to_eye(viewportID);
	
	int viewport[4]; // x,y of lower left corner, width, height
	viewmat_get_viewport(viewport, viewportID);

	/* Get the view or camera matrix; update the frustum values if needed. */
	float f[6]; // left, right, bottom, top, near>0, far>0
	projmat_get_frustum(f, viewport[2], viewport[3], viewportID);

	/* If we are running in IVS mode and using the tracking systems,
	 * all computers need to update their frustum differently. The
	 * master process will be controlled by VRPN, and all slaves will
	 * have their controllers set to "none". Here, we detect for this
	 * situation and make sure all processes work correctly.
	 */
	if(viewmat_display_mode == VIEWMAT_IVS &&
	   viewmat_control_mode == VIEWMAT_CONTROL_VRPN)
	{
		// Will update view matrix and frustum information
		viewmat_get_ivs(viewmatrix, f);
		mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]);
	}
	else
	{
		switch(viewmat_control_mode)
		{
			case VIEWMAT_CONTROL_MOUSE:    // mouse movement
				viewmat_get_mouse(viewmatrix, viewportID);
				mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]);
				break;
			case VIEWMAT_CONTROL_NONE:
				// Get the view matrix from the mouse movement code...but
				// we haven't registered mouse movement callback
				// functions, so mouse movement won't work.
				viewmat_get_mouse(viewmatrix, viewportID);
				mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]);
				break;
			case VIEWMAT_CONTROL_ORIENT:
				viewmat_get_orient_sensor(viewmatrix, viewportID);
				mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]);
				break;
			case VIEWMAT_CONTROL_OCULUS:
				viewmat_get_hmd_oculus(viewmatrix, projmatrix, viewportID);
				// previous function sets projmatrix for us...
				break;
			case VIEWMAT_CONTROL_VRPN:
				viewmat_get_vrpn(viewmatrix, viewportID);
				mat4f_frustum_new(projmatrix, f[0], f[1], f[2], f[3], f[4], f[5]);
				break;

			default:
				msg(MSG_FATAL, "Unknown viewmat control mode: %d\n", viewmat_control_mode);
				exit(EXIT_FAILURE);
		}
	}

	/* Send the view matrix to DGR. At some point in the future, we
	 * may have multiple computers using different view matrices. For
	 * now, even in IVS mode, all processes will use the same view
	 * matrix (IVS uses different view frustums per process). */
	char dgrkey[128];
	snprintf(dgrkey, 128, "!!viewmat%d", viewportID);
	dgr_setget(dgrkey, viewmatrix, sizeof(float)*16);

	/* Sanity checks */
	viewmat_validate_ipd(viewmatrix, viewportID);
	return eye;
}
Ejemplo n.º 10
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();
}