How to move a car upon the ground of the ups and downs?

Started by kiffa, March 20, 2013, 01:33:42 PM

Previous topic - Next topic

kiffa

I'm making a car-racing game, the road is undulate, how to moving the car? Some sample codes will be very helpful, thanks!

EgonOlsen

...it depends. The desktop version contains the car example, which does something similar. Maybe that helps.

kiffa

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);
}



EgonOlsen

If the camera doesn't move smooth, you have to apply some damping. The car example does a basic way of damping in the moveCamera()-method of CarTest.java.

Your assumption about how calcMinDistance works is correct. It doesn't matter if org is inside the car of not as long as the car isn't a collider in which case you might end up calculating the distance between org and the car.

About the ground kissing...i'm not sure what your code does, but the car example (or almost any other collision code that i wrote) move the car up and drops it back onto the terrain. If you don't do that, you might end up in a situation where org is very close or even below the ground.

kiffa

           ^ +Y
            |
            |
+Z <---- (Out screen = +X)
           。。。。。           
           。。。。。
           。。。。。
。。。。。。。。。
。。。。。。。。。
F。。。。。。。R
       car

In my codes, the orgs are "F" and "R"(front and rear), they cast rays to ground. Maybe the org and the ground are too close, i will try to adjust them.