[clientside] 3d text

Started by vitovc, Mar 08, 2025, 07:06 PM

Previous topic - Next topic

vitovc


This script adds 3D text to the game world.

/* functions for 3d calc */
rel_pos2d <- function(z_angle, pos_x, pos_y, pos_z, rel_x, rel_y, rel_z){
  local rX = pos_x + rel_x * ::cos(z_angle) - rel_y * ::sin(z_angle);
  local rY = pos_y + rel_x * ::sin(z_angle) + rel_y * ::cos(z_angle);
  local rZ = pos_z + rel_z;
  return ::Vector(rX, rY, rZ);
}
get_angle <- function(x, y, x2, y2){
  return ::atan2(y2 - y, x2 - x);
}
dist_2d <- function (x, y, x2, y2){
  return ::sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2));
}
get_vangle <- function(x1, y1, z1, x2, y2, z2){
  return ::atan2(z2 - z1, ::dist_2d(x2,y2,x1,y1));
}
normalize_angle <- function (a){
  return ::atan2(::sin(a), ::cos(a));
}
/* 3d text function */
text3d <- {
  "i" : 0,
  "items" : {},
  "proc" : function(){
    local ss = ::GUI.GetScreenSize();
    local cam_from = ::GUI.ScreenPosToWorld(::Vector(ss.X * 0.5, ss.Y * 0.5, -1));
    local cam_to = ::GUI.ScreenPosToWorld(::Vector(ss.X * 0.5, ss.Y * 0.5, 1));
    local a = ::get_angle(cam_from.X, cam_from.Y, cam_to.X, cam_to.Y);
    local v = ::get_vangle(cam_from.X, cam_from.Y, cam_from.Z, cam_to.X, cam_to.Y, cam_to.Z);
    local x = ::normalize_angle(v + 1.57079);
    local y =  3.14159;
    local z = ::normalize_angle(a + 1.57079);
    foreach(k in ::text3d.items){
      k.label.Rotation3D.X = x;
      k.label.Rotation3D.Y = y;
      k.label.Rotation3D.Z = z;
      local rel_pos = ::rel_pos2d(z, k.pos.X, k.pos.Y, k.pos.Z, k.label.Size3D.X * 0.5, 1 + (1 * ::sin(v)), 1 + (-1 * ::sin(v)));
      k.label.Position3D.X = rel_pos.X;
      k.label.Position3D.Y = rel_pos.Y;
      k.label.Position3D.Z = rel_pos.Z ;
    }
  },
  "create" : function(text, position, color = ::Colour(255,255,255,255)){
    local label = ::GUILabel(::VectorScreen(0, 0), color, text);
    label.Position = ::VectorScreen(0, 0);
    label.FontSize = 100;
    local len = text.len();
    label.Size = ::VectorScreen(100 * len, 200);
    label.TextAlignment = GUI_ALIGN_CENTER;
    label.Colour = ::Colour(color.R, color.G, color.B, 255);
    label.Alpha = color.A;
    label.AddFlags(GUI_FLAG_3D_ENTITY);
    label.Position3D = ::Vector(0,0,0);
    label.Rotation3D = ::Vector(0,0,0);
    label.Size3D = ::Vector(0.5 * len * 0.5, 0.5, 0);
    local id = ::text3d.i++;
    ::text3d.items.rawset(id, {"pos" : ::Vector(position.X, position.Y, position.Z), "label" : label});
    return id;
  },
  "remove" : function(id){
    if(::text3d.items.rawin(id)){
      ::text3d.items.rawdelete(id);
    }
  }
}
/* example */
::text3d.create("3D Text", ::Vector(-0.597393, -599.043, 14.5663), ::Colour(255,255,0,128));
function Script::ScriptProcess(){
  ::text3d.proc();
}
...::: vice city :::...
Useful things for vcmp: Relative position and finding an angle (in 3d), 3d line (like laser)