PDA

View Full Version : Trying to hook up FPSControlComponent to the accelerometer



BigBMan
12-20-2010, 10:02 AM
I'm trying to get the RT3DApp to use the accelerometer for camera rotation. I've gotten this far:

In MyAppDelegate.mm (didAccelerate) I changed:


[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.25f];

in FPSControlComponent::OnAdd I added:

GetBaseApp()->m_sig_accel.connect(1, boost::bind(&FPSControlComponent::OnAccel, this, _1));

void FPSControlComponent::OnAccel(VariantList *pVList)
{
CL_Vec3f v = pVList->Get(1).GetVector3();

#ifdef _DEBUG
LogMsg("Acc: %f, %f, %f", v.x, v.y, v.z);
#endif

// at some point, I should be able to set the rotation matrix, but I'm not sure how to do this
irr::scene::CCameraSceneNode *camera = (irr::scene::CCameraSceneNode*)GetIrrlichtManager( )->GetScene()->getActiveCamera();
// camera->setRotation(...);
}

I know this is somewhat elementary matrix math, but it's been a while. How can I turn the accelerometer vector into a 3D camera rotation?

Seth
12-20-2010, 11:44 PM
Hmm, very good question. I haven't done this yet... but if you can take the three values and plug them into three rotation matrixes as euler angles (x,y,z) I would guess it will sort of work, but will be jittery and you'll have to do some filtering on the input first (Kalman filter?) to make it smoother. (approximate changes over the last five frames or something like that?)

BTW, to warn ya: I am ABOUT to get seriously into the Irrlicht part of p+ soon, in fact I did update Irrlicht to 1.7.X a few days ago and will commit it soon. Need to re-add support for loading .rttex textures from Irrlicht first.

PS, instead of hardcoding the accel update speed in MyAppDelegate.mm, you can do this from the C++ side:


GetBaseApp()->SetAccelerometerUpdateHz(30); //update 30 times a second

BigBMan
12-21-2010, 01:01 AM
1.7... Woot! You Rock!!!

I've got some code that does this along with filtering. Thanks for the tips.

BigBMan
12-31-2010, 08:16 AM
Well, I've gotten a little further with this. You can use the accelerometer to rotate up/down and tilt to turn left/right. Next I'll be trying to move this into a separate component so displaying the controls can be optional.

end of OnAdd():


//
// adding acceleromter support
//
m_nAccelSmoothing = 0.1;
//m_v3fAccel = CL_Vec3f(.1, .1, .1);

#ifdef _DEBUG
m_pAccelDisplayEnt = CreateTextLabelEntity(GetParent(), "AccelDebug", GetScreenSizeXf()/2, GetScreenSizeYf()-150, "Accel:");
AddFocusIfNeeded(m_pAccelDisplayEnt);
#endif

GetBaseApp()->m_sig_accel.connect(1, boost::bind(&FPSControlComponent::OnAccel, this, _1));
GetBaseApp()->SetAccelerometerUpdateHz(30); //update 30 times a second


and our message handler:


void FPSControlComponent::OnAccel(VariantList *pVList)
{
// get raw acceleration values
CL_Vec3f v = pVList->Get(1).GetVector3();

// smooth this out
m_v3fAccel.x = v.x * m_nAccelSmoothing + m_v3fAccel.x * (1.0 - m_nAccelSmoothing);
m_v3fAccel.y = v.y * m_nAccelSmoothing + m_v3fAccel.y * (1.0 - m_nAccelSmoothing);
m_v3fAccel.z = v.z * m_nAccelSmoothing + m_v3fAccel.z * (1.0 - m_nAccelSmoothing);

irr::scene::CCameraSceneNode *camera = (irr::scene::CCameraSceneNode*) GetIrrlichtManager()->GetScene()->getActiveCamera();

if( !camera )
return;

if( !m_bCalibrated )
{
// record the original camera position
m_v3dfCameraStart = camera->getRotation();
m_bCalibrated = true;
}

core::vector3df v3dfNewRot;

// Set X Rotation
// TODO: this assumes landscape mode

if( m_v3fAccel.z >=0 )
{
v3dfNewRot.X = 360 - (m_v3fAccel.z * 90);
}
else
{
v3dfNewRot.X = (m_v3fAccel.z * -90);
}

// Set Y Rotation
if( m_v3fAccel.y >=0 )
{
v3dfNewRot.Y = m_v3dfCameraStart.Y + (m_v3fAccel.y * 90);
//v3dfNewRot.Z = 90 - (m_v3fAccel.y * 90);
}
else
{
v3dfNewRot.Y = m_v3dfCameraStart.Y + (m_v3fAccel.y * 90);
//v3dfNewRot.Z = 90 - (m_v3fAccel.y * 90);
}

//v3dfNewRot.Y = m_v3dfCameraStart.Y;
v3dfNewRot.Z = m_v3dfCameraStart.Z; // TODO: tilt the camera

// set our rotation
camera->setRotation(v3dfNewRot);

#ifdef _DEBUG
char strMsg[256];

sprintf(strMsg, "Acc: %f, %f, %f\nCam: %f, %f, %f",
m_v3fAccel.x, m_v3fAccel.y, m_v3fAccel.z,
v3dfNewRot.X, v3dfNewRot.Y, atan2(v3dfNewRot.X , v3dfNewRot.Y));//v3dfNewRot.Z ) ;

//LogMsg("Acc: %f, %f, %f", x, y, z);

EntityComponent* comp = m_pAccelDisplayEnt->GetComponentByName("TextRender");
comp->GetVar("text")->Set(strMsg);
#endif

}