Geometry & Space Utilities

WorldToLocalUV

public Vector2 WorldToLocalUV(Vector3 worldPos)
{
    Vector3 local = transform.InverseTransformPoint(worldPos) - meshOffset;
    GetProjectionBasis(out Vector3 r, out Vector3 up, out _);
    float u = Vector3.Dot(local, r) / Mathf.Max(kEpsilon, raycastGridExtent.x) + 0.5f;
    float v = Vector3.Dot(local, up) / Mathf.Max(kEpsilon, raycastGridExtent.y) + 0.5f;
    return new Vector2(u, v);
}

Purpose: Convert a world-space point to decal UV (0..1). Parameters: worldPos Returns: Vector2 (UV) — (0.5, 0.5) is decal center. Notes: Uses current projection basis and grid extent.


IsPointInsideMask

public bool IsPointInsideMask(Vector3 worldPos)
{
    Vector3 local = transform.InverseTransformPoint(worldPos);
    Vector3 c = center;
    return
        Mathf.Abs(local.x - c.x) <= size.x * 0.5f &&
        Mathf.Abs(local.y - c.y) <= size.y * 0.5f &&
        Mathf.Abs(local.z - c.z) <= maxDistance * 0.5f;
}

Purpose: Test if a world point lies inside the projection box. Parameters: worldPos Returns: bool


GetProjectionBasis

public void GetProjectionBasis(out Vector3 right, out Vector3 up, out Vector3 fwd)
{
    fwd = GetProjectionVector(transform).normalized;
    if (fwd.sqrMagnitude < kEpsilon) fwd = -transform.up;
    up  = Mathf.Abs(Vector3.Dot(fwd, transform.up)) < 0.999f ? transform.up : transform.right;
    right = Vector3.Cross(up, fwd).normalized;
    up    = Vector3.Cross(fwd, right).normalized;
    right = transform.InverseTransformDirection(right);
    up    = transform.InverseTransformDirection(up);
    fwd   = transform.InverseTransformDirection(fwd);
}

Purpose: Compute local right/up/forward basis for the current projection. Parameters: out right, out up, out fwd Returns: void Notes: Ensures a stable orthonormal basis even for near-parallel cases.


ProjectPointOntoSurface

public Vector3 ProjectPointOntoSurface(Vector3 worldPos)
{
    Vector3 dir = GetProjectionVector(transform).normalized;
    if (Physics.Raycast(worldPos - dir * 0.01f, dir,
                        out var hit, maxDistance, wrapMask))
        return hit.point + hit.normal * surfaceOffset;
    return worldPos;
}

Purpose: Project a point along the projection vector onto the nearest valid surface. Parameters: worldPos Returns: Snapped world position. Notes: Offsets along the hit normal by surfaceOffset to avoid z-fighting.


Last updated