[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

habi2

This topic is old. But could you explain what this is? I see a red-line in game and it is in 3d! how VectorScreen(1,1) size is related to the line. You are using GUICanvas. About GUICanvas, there is no documentation.

habi2

Thank you vito. This was exactly i was looking for. I wanted a pixel and colour it. So that i can create a picture (of some dimension 640*420 pixel by pixel).

I will create another topic for it. thanks.