[clientside] 3d line (like laser)

Started by vitovc, Jan 26, 2024, 01:35 PM

Previous topic - Next topic

vitovc


This script can be helpful in development to draw npc paths, visualize raytrace or just for laser rifle feature.

line3d <- {
  "list" : {},
  "del" : function(id){
    if(::line3d.list.rawin(id)){
      return ::line3d.list.rawdelete(id);
    }
  },
  "set" : function(id, color, from, to){
    if(::line3d.list.rawin(id)){
      return ::line3d.update(id, from, to);
    }
    local item = {
      "id" : id,
      "pos" : {
        "from" : ::Vector(0, 0, 0),
        "to" : ::Vector(0, 0, 0)
      },
      "dist" : 0
      "raw" : []
    }
    for(local j = 0; j < 4; j++){
      local ca = ::GUICanvas();
      ca.Colour = color;
      ca.Position = ::VectorScreen(0, 0);
      ca.Size = ::VectorScreen(1, 1);
      ca.AddFlags(GUI_FLAG_BACKGROUND | GUI_FLAG_3D_ENTITY);
      ca.Position3D = ::Vector(0.0,0.0,0.0);
      ca.Rotation3D = ::Vector(0.0,0.0,0.0);
      if(j < 2){
        ca.Size3D = ::Vector(0.01, 0.01, 0.0);
      } else {
        ca.Size3D = ::Vector(0.01, 0.01, 0.0);
      }
      item.raw.push(ca);
    }
    ::line3d.list.rawset(id, item);
    return ::line3d.update(id, from, to);
  },
  "update" : function(id, from, to){
    if(::line3d.list.rawin(id)){
      local item = ::line3d.list.rawget(id);
      item.pos.from = ::Vector(from.X, from.Y, from.Z);
      item.pos.to = ::Vector(to.X, to.Y, to.Z);
      item.dist = ::line3d.dist_3d(from.X, from.Y, from.Z, to.X, to.Y, to.Z);

      local lp2 = item.pos.from;
      local lp = item.pos.to;
      local fp = ::Vector(lp2);
      local fp0 = ::Vector(lp);

      for(local j = 0; j < 4; j++){
        if(0 == j){
          local rot = ::line3d.rotate1(lp.X, lp.Y, lp.Z, lp2.X, lp2.Y, lp2.Z);
          rot.X += -1.570796;
          item.raw[j].Rotation3D = ::Vector(rot);
          local pitch = rot.X;
          local yaw = rot.Z;
          local rel_y = 1;
          local reloffset = sin(pitch) + 1;
          local X = fp.X + -0.005 * cos(yaw) - ((rel_y * -2) + rel_y + reloffset) * sin(yaw);
          local Y = fp.Y + -0.005 * sin(yaw) + ((rel_y * -2) + rel_y + reloffset) * cos(yaw);
          local Z = fp.Z + 1 + cos(pitch) * -1;
          item.raw[j].Size3D.Y = item.dist;
          item.raw[j].Position3D = ::Vector(X, Y, Z);
        } else if(1 == j){
          local rot = ::line3d.rotate1(lp.X, lp.Y, lp.Z, lp2.X, lp2.Y, lp2.Z);
          rot.X += 1.570796;
          item.raw[j].Rotation3D = ::Vector(rot);
          local pitch = rot.X;
          local yaw = rot.Z;
          local rel_y = 1;
          local reloffset = sin(pitch) + 1;
          local X = fp0.X + -0.005 * cos(yaw) - ((rel_y * -2) + rel_y + reloffset) * sin(yaw);
          local Y = fp0.Y + -0.005 * sin(yaw) + ((rel_y * -2) + rel_y + reloffset) * cos(yaw);
          local Z = fp0.Z + 1 + cos(pitch) * -1;
          item.raw[j].Size3D.Y = item.dist;
          item.raw[j].Position3D = ::Vector(X, Y, Z);
        } else if(2 == j){
          local rot = ::line3d.rotate2(lp.X, lp.Y, lp.Z, lp2.X, lp2.Y, lp2.Z);
          rot.X += -1.570796;
          item.raw[j].Rotation3D = ::Vector(rot);
          local pitch = rot.X;
          local yaw = rot.Z;
          local rel_y = 1;
          local reloffset = sin(pitch) + 1;
          local X = fp.X + -0.005 * cos(yaw) - ((rel_y * -2) + rel_y + reloffset) * sin(yaw);
          local Y = fp.Y + -0.005 * sin(yaw) + ((rel_y * -2) + rel_y + reloffset) * cos(yaw);
          local Z = fp.Z + 1 + cos(pitch) * -1;
          item.raw[j].Size3D.X = item.dist;
          item.raw[j].Position3D = ::Vector(X, Y, Z);
        } else if(3 == j){
          local rot = ::line3d.rotate2(lp.X, lp.Y, lp.Z, lp2.X, lp2.Y, lp2.Z);
          rot.X += 1.570796;
          item.raw[j].Rotation3D = ::Vector(rot);
          local pitch = rot.X;
          local yaw = rot.Z;
          local rel_y = 1;
          local reloffset = sin(pitch) + 1;
          local X = fp.X + -0.005 * cos(yaw) - ((rel_y * -2) + rel_y + reloffset) * sin(yaw);
          local Y = fp.Y + -0.005 * sin(yaw) + ((rel_y * -2) + rel_y + reloffset) * cos(yaw);
          local Z = fp.Z + 1 + cos(pitch) * -1;
          item.raw[j].Size3D.X = item.dist;
          item.raw[j].Position3D = ::Vector(X, Y, Z);
        }
      }
    }
  },
  "dist_2d" : function (x, y, x2, y2){
    return ::sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2));
  },
  "dist_3d" : function (x, y, z, x2, y2, z2){
    return ::sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2) + (z - z2)*(z - z2));
  },
  "rotate1" : function(x1, y1, z1, x2, y2, z2){
    local rotx = ::atan2(z2 - z1, ::line3d.dist_2d(x1, y1, x2, y2));
    rotx = rotx - 1.570796;
    local rotz = -1 * ::atan2( x2 - x1, y2 - y1 );
    if(rotz < -3.141592){
      rotz = rotz + 6.283184;
    }
    return ::Vector(rotx, 0,rotz);
  },
  "rotate2" : function(x1, y1, z1, x2, y2, z2){
    local rotx = ::atan2(z2 - z1, ::line3d.dist_2d(x1, y1, x2, y2));
    local rotz = -1 * ::atan2( x2 - x1, y2 - y1 );
    rotz = rotz + -1.570796;
    if(rotz < -3.141592){
      rotz = rotz + 6.283184;
    }
    local roty = ::atan2(z2 - z1, ::line3d.dist_2d(x1, y1, x2, y2));
    rotx = rotx - roty;
    return ::Vector(rotx, roty,rotz);
  }
}

::line3d.set("test", ::Colour(255,0,0,200), Vector(-29.2778, -1342.03, 12.3133), Vector(-36.4452, -1342.45, 10.3133));
...::: vice city :::...
Useful things for vcmp: Relative position and finding an angle (in 3d), 3d line (like laser)

PSL

This script is great, thanks for sharing

Sebastian

Cool! this is something I need.
Thank you!

H.a.S.a.N

Best script I've seen on this forum