Skip to content

World to Screen#

Convert 3D world positions to 2D screen coordinates for drawing.

Basic Usage#

The most common pattern uses the bool overload:

Vector3 worldPos = enemy.GetBonePos(Bone::Head);
Vector2 screenPos;

if (WorldToScreen(worldPos, screenPos))
{
    // screenPos is valid — draw something
    Draw::CircleFilled(screenPos, 5.f, Color::Red());
}

WorldToScreen returns false when the position is behind the camera (off-screen). Always check the return value before drawing.

Two Overloads#

bool WorldToScreen(const Vector3& worldPos, Vector2& screenPos);

Returns true if the position is on screen. The result is written to screenPos.

Direct return#

Vector2 WorldToScreen(const Vector3& worldPos);

Returns the screen position directly. Returns {0, 0} if behind the camera.

Tip

Prefer the bool overload. The direct return can't distinguish "behind camera" from "top-left corner at (0,0)".

Screen Coordinates#

Screen space starts at (0, 0) in the top-left corner:

  • ScreenSize() returns the total resolution (e.g., {1920, 1080})
  • ScreenCenter() returns the center (e.g., {960, 540})

Practical Patterns#

Snaplines#

Draw a line from the screen center to each enemy:

Vector2 center = ScreenCenter();

for (Entity player : Players())
{
    if (!player.IsAlive() || !player.IsEnemy()) continue;

    Vector2 screen;
    if (WorldToScreen(player.GetBonePos(Bone::Head), screen))
        Draw::Line(center, screen, Color::White());
}

Text at World Position#

Display text at a 3D location:

Vector2 screen;
if (WorldToScreen(enemy.GetPosition(), screen))
{
    TextBuilder<32> dist;
    dist.putInt(static_cast<int>(enemy.GetDistance())).put("m");
    Draw::Text(screen.x, screen.y + 15, Color::White(), dist.c_str());
}

Bone Skeleton#

Use GetSkeletonConnections to get the correct bone pairs for any hero, then project each pair:

BonePair bones[21];
int count = GetSkeletonConnections(enemy.GetHeroId(), bones);

for (int i = 0; i < count; ++i)
{
    Vector2 a, b;
    if (WorldToScreen(enemy.GetBonePos(bones[i].a), a) &&
        WorldToScreen(enemy.GetBonePos(bones[i].b), b))
    {
        Draw::Line(a, b, Color::White());
    }
}

The host handles hero-specific bone remapping automatically. See Entity API — Skeleton for details.

See Also#