I'm mucking around in VR right now. In my world, I have a btRigidBody collision box representing my hand, and under kinematic control from the VR Device (setting position and rotation).
I also have a world globe (like those table top globes of the earth) that I want to be able to touch and spin.
The globe is constructed as a btRigidBody collision sphere, and is not kinematic. I also have the LinearFactor set to 0,0,0 to prevent it from moving. Angular factor is still 1,1,1.
I want to reach out and 'grab' the globe (using the controller, and check the button state to see if we're 'grabbing') - and *do something* to make the globe turn as I drag the controller across the surface.
I am unsure what that *do something* looks like. It's not an impulse or a force... it's almost as if I want to take the linear velocity of the controller and somehow apply that to the rotation of the globe -- but I don't know how to do that, or if that's the right approach. I did consider setting up a 6-dof constraint between the controller and the globe, but I don't think that will have the effect that I want (like if I try and flick/spin across the surface of the globe)
Any suggestions?
VR - spinning a globe
-
- Posts: 849
- Joined: Tue Sep 30, 2014 6:03 pm
- Location: San Francisco
Re: VR - spinning a globe
At the moment you make contact with the globe you do the following:
Then each frame where the hand moves the globe you do the following:
I dunno if that code compiles but it should be close. Beware of division by zero when you put the hand at the very center of the globe. Good luck.
Code: Select all
// caputure globe transform and normalized direction from globe to hand:
btTransform globeTransform = globeBody->getTransform();
btVector3 oldHandDirection = (handBody->getTransform().getOrigin() - globeTransform.getOrigin()).normalize();
Code: Select all
// measure new normalied hand direction
btVector3 newHandDirection = (handBody->getTransform().getOrigin() - globeTransform.getOrigin()).normalize();
// compute the dot-product between the two directions:
// a value of 1.0 means they are parallel and nothing needs to be done
// anything less than 1.0 means there is a non-zero angle between them
btScalar cosAngle = newHandDirection.dot(oldHandDirection);
if (cosAngle < 1.0f) {
// compute the shortest rotation from oldHandDirection to newHandDirection
btVector3 axis = oldHandDirection.cross(newHandDirection).normalize();
btScalar angle = acosf(cosAngle);
btQuaternion deltaRotation(axis, angle);
// the new rotation of the globe has an extra deltaRotation applied to it
btTransform newGlobeTransform = globeBody->getTransform();
btQuaternion globeRotation = deltaRotation * newGlobeTransform.getRotation(); // operate from the left by deltaRotation
newGlobeTransform.setRotation(globeRotation);
globeBody->setTransform(newGlobeTransform);
// update oldHandDirection for next frame:
oldHandDirection = newHandDirection;
}