So I've this project where I'm trying to approximate the movement made by a smartwatch by feeding the accelerometer and the gyroscope data into Bullet (accelerations are set using btRigidBody.applyCentreForce and angular velocities by using btRigidBody.setAngularVelocity at its proper time). Yes I know there's a lot of error in the readings from those sensors, but I'm not exactly there yet. Also, I should note I'm using the version of Bullet included with libGDX.
One of the first tests I made, was to use the 2nd derivative of the circle's parametric equation to feed the acceleration vectors into Bullet. I've a class that stores those vectors and then fetch them according to the current time. I called it a "DataLoader". To feed the DataLoader with the acceleration vectors needed to do a circle, I extended it with the following class:
Code: Select all
public class CircleDataLoader extends DataLoader {
private boolean gravity;
public CircleDataLoader(float interval, boolean gravity) {
this.gravity = gravity;
final double crads = 2 * Math.PI;
double rads = 0;
double time = 0;
while(rads < crads) {
Vector3 acc = new Vector3((float) -Math.cos(rads), (float) -Math.sin(rads), 0f); //parametric circle 2nd derivative goes here
super.data.add(new DataSet(acc, Vector3.Zero, time)); //This stores all relevant data. Rotation isn't being used at the moment, so Vector3.Zero it is
rads += Math.PI * interval;
time += interval;
}
}
/**
* This exists because we're setting Bullets gravity as (0,0,0) and apply it as another force in our rigidbody
*/
@Override
public Vector3 getGravity(double time) throws NoMoreElementsException {
if(!gravity)
return new Vector3(); //currently not testing with gravity, so this is the gravity vector in all attempts.
else return new Vector3(0,1,0);
}
//there's also a find(time) method in the parent class which finds the appropriate acceleration
}
Then in the scene, we use the following to apply the forces (this is inside the game loop):
Code: Select all
double miliTime = TimeUtils.millis();
double time = (miliTime-startTime)/1000; //time is stored in seconds btw
float dt = Gdx.graphics.getDeltaTime();
if(loader != null && playing) try {
DataSet curr = loader.find(time); //this is our DataLoader, fed from someplace else
Quaternion orientation = sphereInstance.body.getOrientation(); //just a note: sphereInstance.body is a btRigidBody type
Vector3 gravity = loader.getGravity(time).mul(orientation).scl(9.8f); //we fetch the gravity vector, rotate it to orientation and then scale it from gs to m/s^2
sphereInstance.body.applyCentralForce(gravity); //we apply the gravity here
sphereInstance.body.applyCentralForce( //and here we apply the velocity vector and do the same treatment as we did with gravity
curr.acceleration.cpy()
.mul(orientation).scl(9.8f));
sphereInstance.body.setAngularVelocity(curr.rotation); //and we set the angular velocity, which isn't important to our example
} catch (NoMoreElementsException ex) {
(Not important for our example)
}
dynamicsWorld.stepSimulation(dt); //and we update our simulation
Thanks in advance guys!