Thanks for the car-example, it helps much. But i also have some problems:
1, When the car moving down or up, the camera will shake —— not smooth.
2,Sometimes, the car will run into the ground.
My question:
1, Object3D.calcMinDistance(org, dir): Does the method mean this: From "org", castting a ray along the "dir", if the ray hits the "Object3D", return the length of the ray(segment).
。。。。。|<--return--->|
。。。。。<-------------- 。
。。。。。
Object3D dir org
2, If the org is located into the object3D, then what happen? Return what?
There are my codes, could you point out the problems(camera-shaking and running into ground), thanks:
1, Update the camera per frame, the camera will be located behind and above the car, look at the car-direction(z-axis) :
<----- 。camera
。。。。
。。。。。。。
。。。。。。。
car
// I use a GL-like coordinate system: up(+y),right(+x), out(+z)
private void updateCamera() {
if (mCombinedObj == null) // mCominedObj means the car
return;
SimpleVector camPos = mCombinedObj.getTransformedCenter();
camPos.y += mUpOffset; // mUpOffset == 20, move up the camera
SimpleVector up = mCombinedObj.getYAxis();
SimpleVector direction = mCombinedObj.getZAxis();
mCamera.setOrientation(direction, up);
direction.scalarMul(mDirOffset); // mDirOffset == -20
camPos.add(direction);
mCamera.setPosition(camPos);
}
2, Moving the car:
My car is just one .obj model which has no wheels, i assume the front-bottom-middle as the front wheel, the rear-bottom-middle as the rear wheel, using the two "wheels" to calculate the angle between ground and car-direction(rotate around x-axis), and simply ignore the rotating around z-axis.
private boolean placeOnGround(Object3D road) {
SimpleVector step = mCar.getZAxis();
step.scalarMul(mCurrentSpeed);
mCar.translate(step);
SimpleVector dropDown = new SimpleVector(0, -1, 0);
/**
* To cast the rays, the car will be rotated in horizontal position first,
* rotated around the y-axis according to the cars direction and moved 10
* units up.
*/
mCar.clearRotation();
mCar.rotateY(mTurnY);
mCar.translate(0, 10, 0);
/**
* Cast the rays...
*/
SimpleVector front = mCar.getCenter().calcAdd(
SimpleVector.create(0, -mHeight / 2 + 1, mLenth / 2)); // mHeight meas the height of the car(AABB, y-axis), mLenth means the lenth of the car(AABB, z-axis).
SimpleVector rear = mCar.getCenter().calcAdd(
SimpleVector.create(0, -mHeight / 2 + 1, -mLenth / 2));
Matrix m = mCar.getWorldTransformation();
front.matMul(m);
rear.matMul(m);
float frontHeight = road.calcMinDistance(front, dropDown, 4 * 30);
float rearHeight = road.calcMinDistance(rear, dropDown, 4 * 30);
/**
* Correct the movement we did above.
*/
mCar.translate(0, -10, 0);
mCar.clearRotation();
/**
* The rays all hit the ground, the car can be placed
*/
if(frontHeight != Object3D.COLLISION_NONE && rearHeight != Object3D.COLLISION_NONE){
/**
* Correct the values (see translation above)
*/
frontHeight -= 10;
rearHeight -= 10;
/**
* Calculate the angles between the wheels and the ground.
*/
double angle= frontHeight - rearHeight;
double as = (angle/ (mLenth));
float rot = (float) Math.atan(as);
WLog.d("rotateX: " + rot);
mCar.rotateX(-rot);
/**
* The car is correctly rotated now. But we still have to adjust the
* height. We are simply taking the minimum distance from all wheels to
* the ground as the new height.
*/
float down = frontHeight;
if(frontHeight > rearHeight)
down = rearHeight;
dropDown.scalarMul(down);
WLog.d("car down: " + down);
WLog.d("car updown: " + dropDown);
mCar.translate(dropDown);
step.add(dropDown);
}
/**
* And finally, rotate the car around Y (that's the car's direction)
*/
mCar.rotateY(mTurnY);
}