⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 colli3dx.pas

📁 传奇源代码的delphi版本
💻 PAS
📖 第 1 页 / 共 5 页
字号:

  //collision is only possible when something moves
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
  then
  begin
    result := false;
    exit;
  end;


  //factors
  d0 := sqr(dstep.x) + sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
  d1 := 2 * (step.x * dstep.x + step.y * dstep.y + step.z * dstep.z);
  d2 := sqr(step.x) + sqr(step.y) + sqr(step.z);

  //solving an equation of the second degree
  rod := sqr(d1) - 4 * d2 * d0;

  //d2 is never zero
  if rod > 0
  then
  begin
    rod2 := sqrt(rod);
    t1 := (-d1 - rod2)/2/d2;
    t2 := (-d1 + rod2)/2/d2;

    // if longshot then look into all future
    if longshot
    then
      result := (t1 >= 0) or (t2 >= 0)
    else
    begin
      //collision in between the starting and the ending point if
      result := ((t1 >= 0) and (t1 <= 1))
             or ((t2 >= 0) and (t2 <= 1));
    end;
  end;

end; //end of coll_test_sphere




function TcollisionTester3DX.coll_test_ellipsoid(coll_nr : byte;
                              old_attacker_position, attacker_position : TD3DVector;
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
var
  new_eye, old_eye : TD3DVector;
  dstep, step, center : TD3DVector;
  d0, d1, d2, rod, rod2, t1, t2, a, b, c : TD3DValue;
begin
  result := false;

  //Get the coordinates of the old eye_position in the actual coll frame
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
                 (old_eye, old_attacker_position);

  //Get the coordinates of the eye_position in the actual coll frame
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
                 (new_eye, attacker_position);

  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;

  //x, y and z radius of ellipsoid enlarged with the radius of the bullet
  //to cover the space where a collision may occure
  a := (Fcoll_box_max[FSeriesNr, coll_nr].x
             - Fcoll_box_min[FSeriesNr, coll_nr].x)/2 + bullet_radius;
  b := (Fcoll_box_max[FSeriesNr, coll_nr].y
             - Fcoll_box_min[FSeriesNr, coll_nr].y)/2 + bullet_radius;
  c := (Fcoll_box_max[FSeriesNr, coll_nr].z
             - Fcoll_box_min[FSeriesNr, coll_nr].z)/2 + bullet_radius;

  //eye to center distance
  dstep.x := old_eye.x - center.x;
  dstep.y := old_eye.y - center.y;
  dstep.z := old_eye.z - center.z;

  //step in eye position
  step.x := new_eye.x - old_eye.x;
  step.y := new_eye.y - old_eye.y;
  step.z := new_eye.z - old_eye.z;

  //collision is only possible when something moves
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
  then
  begin
    result := false;
    exit;
  end;


  //factors
  d0 := sqr(b * c * dstep.x) + sqr(a * c * dstep.y) + sqr(a * b * dstep.z)
        - sqr(a * b * c);
  d1 := 2 * (sqr(b * c) * step.x * dstep.x + sqr(a * c) * step.y * dstep.y
        + sqr(a * b) * step.z * dstep.z);
  d2 := sqr(b * c * step.x) + sqr(a * c * step.y) + sqr(a * b * step.z);

  //solving an equation of the second degree
  rod := sqr(d1) - 4 * d2 * d0;

  //d2 is never zero
  if rod > 0
  then
  begin
    rod2 := sqrt(rod);
    t1 := (-d1 - rod2)/2/d2;
    t2 := (-d1 + rod2)/2/d2;

    // if longshot then look into all future
    if longshot
    then
      result := (t1 >= 0) or (t2 >= 0)
    else
    begin
      //collision in between the starting and the ending point if
      result := ((t1 >= 0) and (t1 <= 1))
             or ((t2 >= 0) and (t2 <= 1));
    end;
  end;

end; //end of coll_test_ellipsoid





function TcollisionTester3DX.coll_test_cylinder(coll_nr : byte;
                              old_attacker_position, attacker_position : TD3DVector;
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
var
  distance : TD3DValue;
  new_eye, old_eye : TD3DVector;
  dstep, step, center : TD3DVector;
  radius, d0, d1, d2, rod, rod2, t1, t2, xc1, yc1, zc1, xc2, yc2, zc2 : TD3DValue;
begin
  result := false;


  //Get the coordinates of the old eye_position in the actual coll frame
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
                 (old_eye, old_attacker_position);

  //Get the coordinates of the eye_position in the actual coll frame
  FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
                 (new_eye, attacker_position);

  center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
             + Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
  center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
             + Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
  center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
             + Fcoll_box_min[FSeriesNr, coll_nr].z)/2;

  //radius of sphere enlarged with the radius of the bullet
  //to cover the space where a collision may occure
  radius := Fcoll_radius[FSeriesNr, coll_nr] + bullet_radius;

  //eye to center distance
  dstep.x := old_eye.x - center.x;
  dstep.y := old_eye.y - center.y;
  dstep.z := old_eye.z - center.z;

  //step in eye position
  step.x := new_eye.x - old_eye.x;
  step.y := new_eye.y - old_eye.y;
  step.z := new_eye.z - old_eye.z;

  //collision is only possible when something moves
  if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
  then
  begin
    result := false;
    exit;
  end;

  d0 := 1; //just to avoid warnings
  d1 := 1;
  d2 := 1;


  //The cylinder is alined parallel to the x, y or z axis
  case FOrientation3D of
  symmetric_x :
  begin
    //factors
    d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
    d1 := 2 * (step.y * dstep.y + step.z * dstep.z);
    d2 := sqr(step.y) + sqr(step.z);
  end;
  symmetric_y :
  begin
    //factors
    d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(radius);
    d1 := 2 * (step.x * dstep.x + step.z * dstep.z);
    d2 := sqr(step.x) + sqr(step.z);
  end;
  symmetric_z :
  begin
    //factors
    d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(radius);
    d1 := 2 * (step.x * dstep.x + step.y * dstep.y);
    d2 := sqr(step.x) + sqr(step.y);
  end;
  end; //end of case FOrientation3D of


  //solving an equation of the second degree
  rod := sqr(d1) - 4 * d2 * d0;

  //d2 is never zero
  if rod >= 0
  then
  begin
    //only then is the collision possible
    rod2 := sqrt(rod);
    t1 := (-d1 - rod2)/2/d2;
    t2 := (-d1 + rod2)/2/d2;

    // if longshot then look into all future
    if longshot
    then
      result := (t1 >= 0) or (t2 >= 0)
    else
    begin
      //collision in between the starting and the ending point if
      result := ((t1 >= 0) and (t1 <= 1))
             or ((t2 >= 0) and (t2 <= 1));
    end;

    // however the collision also affords that we are within the length of the cylinder
    if result then
    begin
      case FOrientation3D of
      symmetric_x :
      begin
        xc1 := old_eye.x + t1 * step.x;
        xc2 := old_eye.x + t2 * step.x;


        if longshot
        then
          result :=
           (result and (t1 >= 0) and
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
          or
           (result and (t2 >= 0) and
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
        else
          result :=
           (result and (t1 >= 0) and (t1 <= 1) and
           (xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
           (xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
         or
           (result and (t2 >= 0) and (t2 <= 1) and
           (xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
           (xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) );

         //if collision detected then exit now
         if result then exit;

      end;
      symmetric_y :
      begin
        yc1 := old_eye.y + t1 * step.y;
        yc2 := old_eye.y + t2 * step.y;


        if longshot
        then
          result :=
           (result and (t1 >= 0) and
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
          or
           (result and (t2 >= 0) and
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
        else
          result :=
           (result and (t1 >= 0) and (t1 <= 1) and
           (yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
           (yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
         or
           (result and (t2 >= 0) and (t2 <= 1) and
           (yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
           (yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) );

         //if collision detected then exit now
         if result then exit;


      end;
      symmetric_z :
      begin
        zc1 := old_eye.z + t1 * step.z;
        zc2 := old_eye.z + t2 * step.z;


        if longshot
        then
          result :=
           (result and (t1 >= 0) and
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
          or
           (result and (t2 >= 0) and
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
        else
          result :=
           (result and (t1 >= 0) and (t1 <= 1) and
           (zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
           (zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
         or
           (result and (t2 >= 0) and (t2 <= 1) and
           (zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
           (zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) );

         //if collision detected then exit now
         if result then exit;
      end;

      end; //end of case
    end;

    //exit if a collision occured
    if result then exit;
  end;


  //the collision may also occur with the end surfaces of the cylinder
  case FOrientation3D of
  symmetric_x :
  begin
    if step.x > 1e-6
    then
    begin
      //1st end surface
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
      yc1 := old_eye.y + t1 * step.y;
      zc1 := old_eye.z + t1 * step.z;

      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );

      result := (distance < radius) and (t1 >= 0);
      if not longshot then result := result and (t1 <= 1);
      if result then exit;

      //2nd end surface
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
      yc1 := old_eye.y + t1 * step.y;
      zc1 := old_eye.z + t1 * step.z;

      distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );

      result := (distance < radius) and (t1 >= 0);
      if not longshot then result := result and (t1 <= 1);
      if result then exit;
    end;
  end;
  symmetric_y :
  begin
    if step.y > 1e-6
    then
    begin
      //1st end surface
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
      xc1 := old_eye.x + t1 * step.x;
      zc1 := old_eye.z + t1 * step.z;

      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );

      result := (distance < radius) and (t1 >= 0);
      if not longshot then result := result and (t1 <= 1);
      if result then exit;

      //2nd end surface
      t1 := (Fcoll_box_max[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
      xc1 := old_eye.x + t1 * step.x;
      zc1 := old_eye.z + t1 * step.z;

      distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -