示例#1
0
文件: Car.java 项目: embix/Tectonicus
  /**
   * Places the car. The car has to follow the ground. This is done by casting 4 rays (one from each
   * wheel) to the ground and calculating the resulting rotation angles to let the car follow the
   * ground as close as possible.
   *
   * @param ground the ground
   * @return if it was possible to place the car or not
   */
  public boolean place(Object3D ground) {
    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.
     */
    Matrix rotMat = getRotationMatrix();
    rotMat.setIdentity();
    setRotationMatrix(rotMat);

    rotateY(yRot);
    translate(0, -10, 0);

    /** Cast the rays... */
    float rightFrontHeight =
        ground.calcMinDistance(rightFront.getTransformedCenter(), dropDown, 4 * 30);
    float rightRearHeight =
        ground.calcMinDistance(rightRear.getTransformedCenter(), dropDown, 4 * 30);
    float leftFrontHeight =
        ground.calcMinDistance(leftFront.getTransformedCenter(), dropDown, 4 * 30);
    float leftRearHeight =
        ground.calcMinDistance(leftRear.getTransformedCenter(), dropDown, 4 * 30);

    /** Correct the movement we did above. */
    translate(0, 10, 0);

    /** Reset the rotation matrix again. */
    rotMat = getRotationMatrix();
    rotMat.setIdentity();
    setRotationMatrix(rotMat);

    /** The rays all hit the ground, the car can be placed */
    if (rightFrontHeight != Object3D.COLLISION_NONE
        && rightRearHeight != Object3D.COLLISION_NONE
        && leftFrontHeight != Object3D.COLLISION_NONE
        && leftRearHeight != Object3D.COLLISION_NONE) {

      /** Correct the values (see translation above) */
      rightFrontHeight -= 10;
      rightRearHeight -= 10;
      leftFrontHeight -= 10;
      leftRearHeight -= 10;

      /**
       * Calculate the angles between the wheels and the ground. This is done four times: for the
       * front and the rear as well as for left and right. Front/rear and left/right are averaged
       * afterwards.
       */
      double angleFront = rightFrontHeight - leftFrontHeight;
      double as = (angleFront / (16d));
      angleFront = Math.atan(as);

      double angleRear = rightRearHeight - leftRearHeight;
      as = (angleRear / (16d));
      angleRear = Math.atan(as);

      float rot = (float) ((angleFront + angleRear) / 2d);
      rotateZ(rot);

      double angleLeft = leftFrontHeight - leftRearHeight;
      as = (angleLeft / (16d));
      angleLeft = Math.atan(as);

      double angleRight = rightFrontHeight - rightRearHeight;
      as = (angleRight / (16d));
      angleRight = Math.atan(as);

      rot = (float) ((angleLeft + angleRight) / 2d);

      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 = rightFrontHeight;
      if (leftFrontHeight < down) {
        down = leftFrontHeight;
      }
      if (rightRearHeight < down) {
        down = rightRearHeight;
      }
      if (leftRearHeight < down) {
        down = leftRearHeight;
      }

      dropDown.scalarMul(down - 4);
      translate(dropDown);

    } else {
      return false;
    }

    /** And finally, rotate the car around Y (that's the car's direction) */
    rotateY(yRot);
    return true;
  }