3D Create a point to a distance taking in consideration the Player Y rotation

依然范特西╮ 提交于 2019-12-11 15:02:56

问题


I need to define a 2D plane area in front of a Point(which is our player position) and check which Points(enemies) are within it. In the game it is used to determine what enemies are within the "box" in front of us with X width, Y height and Z length.

I need help calculating the bottom left and top right points of the plane.

Input : We know the player position and we know the player rotation. Only the player Y rotation matters, as the plane should always be in front of the player.

We know the plane width and length. Height is irrelevant in this case, I know how to calculate it. If the width is 8 meters and the length 20, if player position is 0,0,0 the bottom left point would be X= -4 / Y = 0 / Z = 0 and the top right point would be X=4 / Y = 0 / Z = 20

My code only works when the player Y rotation is 0, because I simply add the width/length to current X and Z values. I need the correct math formula to determine where the bottom left and top right points would be, taking in parameter the Player's Y rotation, so that the plane area will always be in the same direction that the player is facing

Here is a visual representation of what I need exactly :

https://gyazo.com/fd5ad0e393f6db8236ee7fd766e7286b

`

float AreaWidth = 8;
float AreaLength = 20;
float AreaHeight = 10;

Point AreaBTMLeftPoint = new Point(PlayerPosition.getX()-(AreaWidth/2), 
PlayerPosition.getLoc().getY(), PlayerPosition.getLoc().getZ());

Point AreaTOPRightPoint = new Point(PlayerPosition.getLoc().getX()+ 
(AreaWidth/2), PlayerPosition.getLoc().getY(), 
PlayerPosition.getLoc().getZ()+(AreaLength));

float AreaBTMX = AreaBTMLeftPoint.getX();
float AreaBTMZ = AreaBTMLeftPoint.getZ();
float AreaTOPX = AreaTOPRightPoint.getX();
float AreaTOPZ = AreaTOPRightPoint.getZ();
float AreaMaxY = PlayerPosition.getLoc().getY()+(AreaHeight/2);
float AreaMinY = PlayerPosition.getLoc().getY()-(AreaHeight/2);

if (TargetPosition.getLoc().getX() > AreaBTMX && 
TargetPosition.getLoc().getX() < AreaTOPX &&
TargetPosition.getLoc().getY() > AreaMinY &&
TargetPosition.getLoc().getY() < AreaMaxY &&
TargetPosition.getLoc().getZ() > AreaBTMZ && 
TargetPosition.getLoc().getZ() < AreaTOPZ) {

This target is inside the area, do stuff.

}`


回答1:


Let player position is P, direction angle is Fi, target position is T.
Unit direction vector D:

d.x = cos(Fi) //don't forget about radians
d.y = sin(Fi)

Difference vector

PT = T - P = (T.x - P.x, T.y - P.y)

Perpendicular distance from T to direction line of player is length of orthogonal projection

perplen = Abs(Pt x D) =                  //cross product
          Abs(PT.x * d.y - Pt.y * d.x)
compare it with (AreaWidth/2)

Distance along direction line:

alonglen = (Pt .dot. D) =                  //dot product
           PT.x * d.x + PT.y * d.y
it should be >=0 and <= than AreaLength

If both conditions are true, target lies in inclined rectangle

Proof-of-concept Delphi code:

var
  i, px, py, tx, ty, XX, YY, ptx, pty: Integer;
  perplen, alonglen: Double;
  wdt, lng: Integer;
  Fi, cs, sn: Double;
begin
  px := 300;    py := 300;
  wdt := 150;   lng := 250;
  Fi := Pi / 6;   cs := Cos(Fi);   sn := Sin(Fi);
  Canvas.Brush.Color := clBlack;
  Canvas.Ellipse(px - 5, py - 5, px + 6, py + 6);  //player

  Canvas.Brush.Style := bsClear;
  Canvas.MoveTo(px, py);
  XX := px - Round(Wdt / 2 * sn);  YY := py + Round(Wdt / 2 * cs);
  Canvas.LineTo(XX, YY);
  XX := XX + Round(lng * cs);   YY := YY + Round(lng * sn);
  Canvas.LineTo(XX, YY);
  XX := XX + Round(Wdt * sn);   YY := YY - Round(Wdt * cs);
  Canvas.LineTo(XX, YY);
  XX := XX - Round(lng * cs);   YY := YY - Round(lng * sn);
  Canvas.LineTo(XX, YY);
  Canvas.LineTo(px, py);  //rectangle finished

  for i := 0 to 99 do begin
    tx := 100 + Random(600);  //random target
    ty := 100 + Random(600);
    ptx := tx - px;
    pty := ty - py;
    perplen := Abs(ptx * sn - pty * cs);
    alonglen := ptx * cs + pty * sn;
    if (perplen <= Wdt / 2) and (alonglen >= 0) and (alonglen <= lng) then
      Canvas.Brush.Color := clBlue  // in region
    else
      Canvas.Brush.Color := clRed;
    Canvas.Ellipse(tx - 3, ty - 3, tx + 4, ty + 4);
  end;



来源:https://stackoverflow.com/questions/57599014/3d-create-a-point-to-a-distance-taking-in-consideration-the-player-y-rotation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!