Пример #1
0
/** Get a view matrix from VRPN and adjust the view frustum
 * appropriately.
 * @param viewmatrix The location where the viewmatrix should be stored.
 * @param frustum The location of the view frustum that should be adjusted.
 */
static void viewmat_get_ivs(float viewmatrix[16], float frustum[6])
{
	/* Only get information from VRPN if we are DGR master, or if DGR
	 * is being used at all. */
	float pos[3];
	if((dgr_is_enabled() && dgr_is_master()) || dgr_is_enabled()==0)
	{
		if(viewmat_control_mode == VIEWMAT_CONTROL_VRPN &&
		   viewmat_vrpn_obj != NULL)
		{
			/* get information from vrpn */
			float orient[16];
			vrpn_get(viewmat_vrpn_obj, NULL, pos, orient);
		}
		else
		{
			/* If no head tracking is available, assume the person is
			 * standing at the origin with a normal eye height */
			pos[0] = 0;
			pos[1] = 1.5; // normal eye height
			pos[2] = 0;
		}
	}
	
	/* Make sure all DGR hosts can get the position so that they
	 * can update the frustum appropriately */
	dgr_setget("!!viewMatPos", pos, sizeof(float)*3);

	/* Update view frustum if it was provided. */
	if(frustum != NULL)
	{
		frustum[0] -= pos[0];
		frustum[1] -= pos[0];
		frustum[2] -= pos[1];
		frustum[3] -= pos[1];
		frustum[4] += pos[2];
		frustum[5] += pos[2];
	}

	/* calculate a lookat point */
	float lookat[3];
	float forwardVec[3] = { 0, 0, -1 };
	for(int i=0; i<3; i++)
		lookat[i] = pos[i]+forwardVec[i];
		
	float up[3] = {0, 1, 0};
	mat4f_lookatVec_new(viewmatrix, pos, lookat, up);
}
Пример #2
0
static void viewmat_get_vrpn(float viewmatrix[16], int viewportNum)
{
	if(viewmat_vrpn_obj == NULL)
		return;
			
	float pos[3] = { 0,0,0 };
	float rotMat[16], posMat[16];
	vrpn_get(viewmat_vrpn_obj, NULL, pos, rotMat);
	mat4f_translate_new(posMat, -pos[0], -pos[1], -pos[2]); // position
	viewmat_fix_rotation(rotMat);
	mat4f_transpose(rotMat); /* orientation sensor rotates camera, not world */

	float cyclopsViewMatrix[16];
	mat4f_mult_mat4f_new(cyclopsViewMatrix, rotMat, posMat);

	viewmat_get_generic(viewmatrix, cyclopsViewMatrix, viewportNum);
}
Пример #3
0
/** Checks if VIEWMAT_VRPN_OBJECT environment variable is set. If it
    is, use VRPN to control the camera position and orientation.
    
    @return Returns 1 if VRPN is set up, 0 otherwise.
*/
static int viewmat_init_vrpn(void)
{
	viewmat_vrpn_obj = NULL;
	
	const char* vrpnObjString = getenv("VIEWMAT_VRPN_OBJECT");
	if(vrpnObjString != NULL && strlen(vrpnObjString) > 0)
	{
		viewmat_vrpn_obj = vrpnObjString;
		msg(MSG_INFO, "View is following tracker object: %s\n", viewmat_vrpn_obj);
		
		/* Try to connect to VRPN server */
		float vrpnPos[3];
		float vrpnOrient[16];
		vrpn_get(viewmat_vrpn_obj, NULL, vrpnPos, vrpnOrient);
		return 1;
	}
	return 0;
}
Пример #4
0
/** Draw a object at the location and orientation of the tracked vrpn object */
void drawObject(const int objectIndex, float viewMat[16])
{
	const char *vrpnObject = global_argv[objectIndex];
	const float scaleFactor = .5;
	
	float pos[4], orient[16];
	vrpn_get(vrpnObject, NULL, pos, orient);
	float modelMat[16],translate[16],scale[16];
	mat4f_scale_new(scale, scaleFactor, scaleFactor, scaleFactor);
	mat4f_translateVec_new(translate, pos);
	mat4f_mult_mat4f_many(modelMat, translate, orient, scale, NULL);

	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"), 2);

	kuhl_errorcheck();
	kuhl_geometry_draw(modelgeom); /* Draw the model */
	kuhl_errorcheck();

	/* Transparency of labels may not appear right because we aren't
	 * sorting them by depth. */
	float labelScale[16];
	mat4f_scale_new(labelScale, 1, 1/labelAspectRatio[objectIndex-1], 1);
	mat4f_mult_mat4f_new(modelview, modelview, labelScale);
	glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, 0, modelview);
	glUniform1i(kuhl_get_uniform("renderStyle"), 1);
	kuhl_geometry_texture(&quad, label[objectIndex-1], "tex", 1);
	kuhl_geometry_draw(&quad);

#if 0
	printf("%s is at\n", vrpnObject);
	vec3f_print(pos);
	mat4f_print(orient);
#endif
}
Пример #5
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;
	}
}
Пример #6
0
/** Get view and projection matrices appropriate for the Oculus HMD */
static void viewmat_get_hmd_oculus(float viewmatrix[16], float projmatrix[16], int viewportID)
{
#ifndef MISSING_OVR
	/* Oculus recommends the order that we should render eyes. We
	 * assume that smaller viewportIDs are rendered first. So, we need
	 * to map the viewportIDs to the specific Oculus HMD eye. The
	 * "eye" variable will be set to either ovrEye_Left (if we are
	 * rendering the left eye) or ovrEye_Right (if we are rendering
	 * the right eye). */
	ovrEyeType eye = hmd->EyeRenderOrder[viewportID];

	/* Oculus doesn't provide us with easy access to the view
	 * frustum information. We get the projection matrix directly
	 * from libovr. */
	ovrMatrix4f ovrpersp = ovrMatrix4f_Projection(hmd->DefaultEyeFov[eye], 0.5, 500, 1);
	mat4f_setRow(projmatrix, &(ovrpersp.M[0][0]), 0);
	mat4f_setRow(projmatrix, &(ovrpersp.M[1][0]), 1);
	mat4f_setRow(projmatrix, &(ovrpersp.M[2][0]), 2);
	mat4f_setRow(projmatrix, &(ovrpersp.M[3][0]), 3);
	
	float offsetMat[16], rotMat[16], posMat[16], initPosMat[16];
	mat4f_identity(offsetMat);  // Viewpoint offset (IPD, etc);
	mat4f_identity(rotMat);     // tracking system rotation
	mat4f_identity(posMat);     // tracking system position
	mat4f_identity(initPosMat); // camera starting location
	
	/* Construct posMat and rotMat matrices which indicate the
	 * position and orientation of the HMD. */
	if(viewmat_vrpn_obj) // get position from VRPN
	{
		/* Get the offset for the left and right eyes from
		 * Oculus. If you are using a separate tracking system, you
		 * may also want to apply an offset here between the tracked
		 * point and the eye location. */
		mat4f_translate_new(offsetMat,
		                    eye_rdesc[eye].HmdToEyeViewOffset.x, // left & right IPD offset
		                    eye_rdesc[eye].HmdToEyeViewOffset.y, // vertical offset
		                    eye_rdesc[eye].HmdToEyeViewOffset.z); // forward/back offset

		float pos[3] = { 0,0,0 };
		vrpn_get(viewmat_vrpn_obj, NULL, pos, rotMat);
		mat4f_translate_new(posMat, -pos[0], -pos[1], -pos[2]); // position
		viewmat_fix_rotation(rotMat);
	}
	else // get position from Oculus tracker
	{
		pose[eye] = ovrHmd_GetHmdPosePerEye(hmd, eye);
		mat4f_translate_new(posMat,                           // position (includes IPD offset)
		                    -pose[eye].Position.x,
		                    -pose[eye].Position.y,
		                    -pose[eye].Position.z);
		mat4f_rotateQuat_new(rotMat,                          // rotation
		                     pose[eye].Orientation.x,
		                     pose[eye].Orientation.y,
		                     pose[eye].Orientation.z,
		                     pose[eye].Orientation.w);

		// Starting point:
		
		// Translate the world based on the initial camera position
		// specified in viewmat_init(). You may choose to initialize the
		// camera position with y=1.5 meters to approximate a normal
		// standing eyeheight.
		float initPosVec[3];
		vec3f_scalarMult_new(initPosVec, oculus_initialPos, -1.0f);
		mat4f_translateVec_new(initPosMat, initPosVec);
		// TODO: Could also get eyeheight via ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, 1.65)
	}
	mat4f_transpose(rotMat); /* orientation sensor rotates camera, not world */

	// viewmatrix = offsetMat * rotMat *  posMat * initposmat
	mat4f_mult_mat4f_new(viewmatrix, offsetMat, rotMat); // offset is identity if we are using Oculus tracker
	mat4f_mult_mat4f_new(viewmatrix, viewmatrix, posMat);
	mat4f_mult_mat4f_new(viewmatrix, viewmatrix, initPosMat);

	if(0)
	{
		printf("ViewportID=%d; eye=%s\n", viewportID, eye == ovrEye_Left ? "left" : "right");
		printf("Eye offset according to OVR (only used if VRPN is used): ");
		mat4f_print(offsetMat);
		printf("Rotation sensing (from OVR or VRPN): ");
		mat4f_print(rotMat);
		printf("Position tracking (from OVR or VRPN): ");
		mat4f_print(posMat);
		printf("Initial position (from set in viewmat_init()): ");
		mat4f_print(initPosMat);
		printf("Final view matrix: ");
		mat4f_print(viewmatrix);
	}
#else
	/* We shouldn't ever get here, but we'll generate a generic view
	 * and projection matrix just in case... */
	mat4f_lookat_new(viewmatrix,
	                 0,1.55,0,
	                 0,1.55,-1,
	                 0,1,0);
	mat4f_perspective_new(projmatrix, 50, 1, 0.5, 500);
#endif
}