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

📄 colli3dx.pas

📁 传奇源代码的delphi版本
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      result := (distance < radius) and (t1 >= 0);
      if not longshot then result := result and (t1 <= 1);
      if result then exit;
    end;

  end;
  symmetric_z :
  begin
    if step.z > 1e-6
    then
    begin
      //1st end surface
      t1 := (Fcoll_box_min[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
      xc1 := old_eye.x + t1 * step.x;
      yc1 := old_eye.y + t1 * step.y;

      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );

      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].z - old_eye.z)/step.z;
      xc1 := old_eye.x + t1 * step.x;
      yc1 := old_eye.y + t1 * step.y;

      distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );

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

  end;


  end; //end of case

end; //end of coll_test_cylinder





function TcollisionTester3DX.coll_test_conus(coll_nr : byte;
                              old_attacker_position, attacker_position : TD3DVector;
                              bullet_radius : TD3DValue; longshot : boolean): boolean;
var
  height3D, width3D : TD3DValue;
  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;
  xc, yc, zc, conusfact : 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;


  //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;

  //if FPercentLeftatTop is positiv then the conus is largest at the bottom
  xc := center.x;
  yc := center.y;
  zc := center.z;

  width3D := 10;  //just to avoid warnings
  height3D := 10;

  case FOrientation3D of
  symmetric_x :
  begin
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].x
              - Fcoll_box_min[FSeriesNr, coll_nr].x;
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].y
              - Fcoll_box_min[FSeriesNr, coll_nr].y
              + Fcoll_box_max[FSeriesNr, coll_nr].z
              - Fcoll_box_min[FSeriesNr, coll_nr].z)/2;

    //the top of the conus is maller than the bottom of it
    if FPercentLeftatTop >= 0
    then
      xc := center.x - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
    else
      xc := center.x + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
  end; //end of symmetric_x
  symmetric_y :
  begin
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].y
              - Fcoll_box_min[FSeriesNr, coll_nr].y;
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
              - Fcoll_box_min[FSeriesNr, coll_nr].x
              + Fcoll_box_max[FSeriesNr, coll_nr].z
              - Fcoll_box_min[FSeriesNr, coll_nr].z)/2;

    //the top of the conus is maller than the bottom of it
    if FPercentLeftatTop >= 0
    then
      yc := center.y - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
    else
      yc := center.y + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
  end; //end of symmetric_y
  symmetric_z :
  begin
    height3D := Fcoll_box_max[FSeriesNr, coll_nr].z
              - Fcoll_box_min[FSeriesNr, coll_nr].z;
    width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
              - Fcoll_box_min[FSeriesNr, coll_nr].x
              + Fcoll_box_max[FSeriesNr, coll_nr].y
              - Fcoll_box_min[FSeriesNr, coll_nr].y)/2;

    //the top of the conus is maller than the bottom of it
    if FPercentLeftatTop >= 0
    then
      zc := center.z - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
    else
      zc := center.z + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
  end; //end of symmetric_z
  end; //end of case

  //mathematically we need the conusfact describing the ratio between the radius of
  //the large end of the conus and the height of the conus
  if width3D > 0
  then
    conusfact := height3D/2/width3D
  else
    conusfact := 1e9;

  //eye to the fictive tip of the conus distance
  dstep.x := old_eye.x - xc;
  dstep.y := old_eye.y - yc;
  dstep.z := old_eye.z - zc;

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

  //The conus is aligned parallel to the x, y or z axis
  case FOrientation3D of
  symmetric_x :
  begin
    //factors
    d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(dstep.x * conusfact);
    d1 := 2 * (step.y * dstep.y + step.z * dstep.z
          - sqr(conusfact) * step.x * dstep.x);
    d2 := sqr(step.y) + sqr(step.z) - sqr(conusfact * step.x);
  end;
  symmetric_y :
  begin
    //factors
    d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(dstep.y * conusfact);
    d1 := 2 * (step.x * dstep.x + step.z * dstep.z
          - sqr(conusfact) * step.y * dstep.y);
    d2 := sqr(step.x) + sqr(step.z) - sqr(conusfact * step.y);
  end;
  symmetric_z :
  begin
    //factors
    d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(dstep.z * conusfact);
    d1 := 2 * (step.x * dstep.x + step.y * dstep.y
          - sqr(conusfact) * step.z * dstep.z);
    d2 := sqr(step.x) + sqr(step.y) - sqr(conusfact * step.z);
  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 conus
    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) );

      if FPercentLeftatTop >= 0
      then
        radius := width3D/2 //the large end of the conus is down
      else
        radius := -width3D/2 * FPercentLeftatTop;

      radius := radius + bullet_radius;

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

      if FPercentLeftatTop >= 0
      then
        radius := width3D/2 * FPercentLeftatTop //the small end of the conus is upwards
      else
        radius := width3D/2;

      radius := radius + bullet_radius;

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

      if FPercentLeftatTop >= 0
      then
        radius := width3D/2 //the large end of the conus is down
      else
        radius := -width3D/2 * FPercentLeftatTop;

      radius := radius + bullet_radius;

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

⌨️ 快捷键说明

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