ValveIntersenseTransforms

From DigitalBlacksmith

Jump to: navigation, search

[edit] Intersense in Valve

OK this isn't a complete explanation..but holds most the key points..


[edit] Console variable

These specify the transform from the tracker to the head.

//These variables capture the transform from the tracker to the feet
ConVar armar_tracker_head_x( "armar_tracker_head_x", "0", 0);
ConVar armar_tracker_head_y( "armar_tracker_head_y", "0", 0);
ConVar armar_tracker_head_z( "armar_tracker_head_z", "0", 0);
ConVar armar_tracker_head_pitch( "armar_tracker_head_pitch", "0", 0);
ConVar armar_tracker_head_yaw( "armar_tracker_head_yaw", "0", 0);
ConVar armar_tracker_head_roll( "armar_tracker_head_roll", "0", 0);

These specify the transform from the lab coordinate space to a local space center on the fwd right upright..

//These transalte the IS1200/900 coord frame to map coord frame
ConVar armar_coord_frame_x( "armar_coord_frame_x", "-284.64", 0);
ConVar armar_coord_frame_y( "armar_coord_frame_y", "-139.3", 0);
ConVar armar_coord_frame_z( "armar_coord_frame_z", "-23.5", 0);

This is the special sauce method. Note the technique of grabbing the local client player entity and using it as a transformation workbench. Allows you to use all the handy matrix and transformation methods common the CBaseEntity:

/**
* Given tracker position and orientation, return the feet
*/
matrix3x4_t getHeadTransfrom(float tx, float ty, float tz, float tp, float tyaw, float tr) {

	//Get a copy of the player to use as a temporary tracker
	C_BasePlayer* tracker = C_BasePlayer::GetLocalPlayer();

	//Set the virtual tracker to the real tracker
	tracker->SetAbsOrigin(Vector(tx,ty,tz));

	//TODO:  Are these in the right order?
	tracker->SetAbsAngles(QAngle(tp, tyaw, tr));	

	

	Vector p_offset(armar_tracker_head_x.GetFloat(), armar_tracker_head_y.GetFloat(), armar_tracker_head_z.GetFloat());
	//TODO:  Implement this -- armar_tracker_head_pitch.GetFloat(), armar_tracker_head_yaw.GetFloat(), armar_tracker_head_roll.GetFloat();
	Vector o_offset(0,0,0);
	//Create to the player's head
	matrix3x4_t xform;
	xform[0][0] =1;
	xform[0][1] =0;
	xform[0][2] =0;
	xform[0][3] =p_offset.x;

	xform[1][0] =0;
	xform[1][1] =1;
	xform[1][2] =0;
	xform[1][3] =p_offset.y;

	xform[2][0] =0;
	xform[2][1] =0;
	xform[2][2] =1;
	xform[2][3] =p_offset.z;

	xform[3][0] =0;
	xform[3][1] =0;
	xform[3][2] =0;
	xform[3][3] =1;

	
	//Execute the first matrix operation (translation)
	matrix3x4_t translationTemp;		
	ConcatTransforms( tracker->EntityToWorldTransform(), xform, translationTemp);

	//Set up the x axis rotation matrix
	Quaternion qx;
	Vector rotationAxisWs_x =Vector( 1,0,0 );
	AxisAngleQuaternion( rotationAxisWs_x, o_offset.x, qx );
	QuaternionMatrix( qx, vec3_origin, xform );
	
	//Execute the x axis rotation matrix
	matrix3x4_t x_temp;
	ConcatTransforms( translationTemp, xform, x_temp );

	//Set up the y axis rotation matrix
	Quaternion qy;
	Vector rotationAxisWs_y =Vector( 0,1,0 );
	AxisAngleQuaternion( rotationAxisWs_y, o_offset.y, qy );
	QuaternionMatrix( qy, vec3_origin, xform );
	
	//Execute the y axis rotation matrix
	matrix3x4_t y_temp;
	ConcatTransforms( x_temp, xform, y_temp );

	//Set up the z axis rotation matrix
	Quaternion qz;
	Vector rotationAxisWs_z =Vector( 0,0,1 );
	AxisAngleQuaternion( rotationAxisWs_z, o_offset.z, qz );
	QuaternionMatrix( qz, vec3_origin, xform );

	//Execute the z axis rotation matrix -- put result in our final answer
	matrix3x4_t localToWorldMatrix ;
	ConcatTransforms( y_temp, xform, localToWorldMatrix );

	//Now load the resultant transform back into our entity's transform
	tracker->SetLocalTransform(localToWorldMatrix);
	
	//Msg("post trans\n");
	//debugMatrix(localToWorldMatrix);
	//Msg("\n\n");
	return localToWorldMatrix;

}

It gets called by these methods...note how the intersense units and angles are tweaked before calling getHeadTransform.

This one sets the orientation:

/*
================
AdjustAngles

Moves the local angle positions
================
*/
void CInput::AdjustAngles ( float frametime )
{
	float	speed;
	QAngle viewangles;
	
	// Determine control scaling factor ( multiplies time )
	speed = DetermineKeySpeed( frametime );

	// Retrieve latest view direction from engine
	engine->GetViewAngles( viewangles );

//OHAN ADD BEGIN - Get view angle from the tracker
	if(arctl.IsTrackerInitialized() && (useIntersense == true)){
		//pitch, yaw, roll
		float pitch, yaw, roll;

		arctl.GetOrientation(pitch, yaw, roll, HEAD);
		
		viewangles.x = pitch;
		viewangles.y = -1*(yaw+90);
		viewangles.z = -1*(roll);

		float ox, oy, oz;				
		arctl.GetPosition(ox, oy, oz, HEAD);
		
		matrix3x4_t fTransform = getHeadTransfrom(ox, oy, oz, viewangles.x, viewangles.y, viewangles.z);
		
        //the angles of the feet -- they are same as eyes
		
		QAngle testangles;
		MatrixToAngles(fTransform, testangles);
		Msg("computed viewangles = %f, %f, %f\n", testangles.x, testangles.y, testangles.z);
		Msg("good viewangles = %f, %f, %f\n", viewangles.x, viewangles.y, viewangles.z);
		//viewangles.x = -viewangles.x;
		//viewangles.y = -viewangles.y;
	}
	else{
		// Adjust YAW
		AdjustYaw( speed, viewangles );

		// Adjust PITCH if keyboard looking
		AdjustPitch( speed, viewangles );

		// Make sure values are legitimate
		ClampAngles( viewangles );
	}
//OHAN ADD END

	// Store new view angles into engine view direction
	engine->SetViewAngles( viewangles );
}


This one sets position:

void CInput::CreateMove ( int sequence_number, float input_sample_frametime, bool active )
{	
	CUserCmd *cmd = &m_pCommands[ sequence_number % MULTIPLAYER_BACKUP];

	cmd->Reset();

	cmd->command_number = sequence_number;
	cmd->tick_count = gpGlobals->tickcount;

	QAngle viewangles;

	if ( active || sv_noclipduringpause.GetInt() )
	{
		// Determine view angles
		AdjustAngles ( input_sample_frametime );

// OHAN ADD: Use tracker for position if position tracking is available //STEVE and enabled
		if(arctl.HasPositionTracking() && !enable_calibration.GetBool() && (useIntersense == true)){
			// Send console command to the server from client side every "send_ticker" interval
			if(send_ticker >= TICK_INTERVAL){
				
				//First get the angles of the tracker
				float pitch, yaw, roll;				
				arctl.GetOrientation(pitch, yaw, roll, HEAD);
				
				viewangles.x = pitch;
				viewangles.y = -1*(yaw+90);
				viewangles.z = -1*(roll);
								
				char command[64];
				float ox, oy, oz;
				float x,y,z;
				// get the position of the head and send it to player position server
				arctl.GetPosition(ox, oy, oz, HEAD);
				
				//Rotate the coord system about the x axis
				z = oz *-1;
				x = oy;
				y = ox;
				
				//Convert meters to inches (Valve uses inches)
				//float factor = move_factor.GetFloat();
				float factor = 39.3700787;
				//Msg("multy x= %f, factor=%f\n", x, factor);
				x *= factor; y *= factor; z *= factor;

				//Msg("Raw position data = %f, %f, %f\n", x, y, z);
				//Add any coordinate frame translation
				x = x + armar_coord_frame_x.GetFloat();
				y = y + armar_coord_frame_y.GetFloat();
				z = z + armar_coord_frame_z.GetFloat();

				//Msg("Offset position data = %f, %f, %f\n", x, y, z);
				//Msg("Raw orientation data = %f, %f, %f\n", pitch, yaw, roll);
				matrix3x4_t fTransform = getHeadTransfrom(x, y, z, viewangles.x, viewangles.y, viewangles.z);
				
					

				x = fTransform[0][3];
                y = fTransform[1][3];
				z = fTransform[2][3]-64;  //Here we always subtract out the height of the player
				
				//Msg("set_user_position %f %f %f\n", x, y, z);
				sprintf(command, "set_user_position %f %f %f", x, y, z);
				engine->ClientCmd(command);			

				
				send_ticker = 0;
			}
			else {
				send_ticker++;
			}
		}
		
		if(!arctl.HasPositionTracking() || enable_calibration.GetBool()){
			// Determine sideways movement
			ComputeSideMove( cmd );

			// Determine vertical movement
			ComputeUpwardMove( cmd );

			// Determine forward movement
			ComputeForwardMove( cmd );

			// Scale based on holding speed key or having too fast of a velocity based on client maximum
			//  speed.
			ScaleMovements( cmd );
		}
// OHAN ADD END

		// Allow mice and other controllers to add their inputs
		ControllerMove( input_sample_frametime, cmd );
	}
	else
	{
		// need to run and reset mouse input so that there is no view pop when unpausing
		if ( !m_fCameraInterceptingMouse && m_fMouseActive )
		{
			float mx, my;
			GetAccumulatedMouseDeltasAndResetAccumulators( &mx, &my );
			ResetMouse();
		}
	}
	// Retreive view angles from engine ( could have been set in IN_AdjustAngles above )	
	engine->GetViewAngles( viewangles );

	// Latch and clear impulse
	cmd->impulse = in_impulse;
	in_impulse = 0;

	// Latch and clear weapon selection
	if ( m_hSelectedWeapon != NULL )
	{
		C_BaseCombatWeapon *weapon = m_hSelectedWeapon;

		cmd->weaponselect = weapon->entindex();
		cmd->weaponsubtype = weapon->GetSubType();

		// Always clear weapon selection
		m_hSelectedWeapon = NULL;
	}

	// Set button and flag bits
	cmd->buttons = GetButtonBits( 1 );

//MSW COMMENT OUT JOYSTICK
/*
	// Using joystick?
	if ( in_joystick.GetInt() )
	{
		if ( cmd->forwardmove > 0 )
		{
			cmd->buttons |= IN_FORWARD;
		}
		else if ( cmd->forwardmove < 0 )
		{
			cmd->buttons |= IN_BACK;
		}
	}
*/

	// Use new view angles if alive, otherwise user last angles we stored off.
	if ( g_iAlive )
	{
		VectorCopy( viewangles, cmd->viewangles );
		VectorCopy( viewangles, m_angPreviousViewAngles );
	}
	else
	{
		VectorCopy( m_angPreviousViewAngles, cmd->viewangles );
	}

	// Let the move manager override anything it wants to.
	g_pClientMode->CreateMove( input_sample_frametime, cmd );

	// Get current view angles after the client mode tweaks with it
	engine->SetViewAngles( cmd->viewangles );

	m_flLastForwardMove = cmd->forwardmove;

	cmd->random_seed = MD5_PseudoRandom( sequence_number ) & 0x7fffffff;

	HLTVCamera()->CreateMove( cmd );

	// Temporary Test: Ohan
	/*Vector v;
	prediction->GetViewOrigin(v);
	Msg("(%f, %f, %f)\n", v.x, v.y, v.z);*/

#if defined( HL2_CLIENT_DLL )
	// copy backchannel data
	int i;
	for (i = 0; i < m_EntityGroundContact.Count(); i++)
	{
		cmd->entitygroundcontact.AddToTail( m_EntityGroundContact[i] );
	}
	m_EntityGroundContact.RemoveAll();
#endif
}

--Steve 04:15, 12 March 2008 (EDT)

Personal tools