Makie show image on surface

I’m trying to display images as posters around a 3D environment using GLMakie. For that purpose, I wrote the following code

using Makie
using GeometryBasics
using FileIO

struct Sprite{T<:RGB,T2<:Integer,T3<:Point3, T4<:Point2,T5<:Vec3}
    points::Vector{T3}
    faces::Vector{TriangleFace{T2}}
    normals::Vector{T5}
    uv::Vector{T4}
    img::Matrix{T}
end

"""
Map `img` onto a flat 3D surface
"""
function sprite(img,rect=Rect2(-0.5, -0.5, 1.0, 1.0))
    points = decompose(Point3f, rect)
    normals = decompose(GeometryBasics.Normal(Vec3f), rect)
    faces = decompose(GLTriangleFace, rect)
    uv = decompose(UV(Point2f), rect)

    Sprite(points, faces, normals, uv, img)
end

function Makie.convert_arguments(::Type{<:AbstractPlot}, sp::Sprite)
    gb_mesh = GeometryBasics.Mesh(sp.points, sp.faces; uv = sp.uv, normal =sp.normals) # this does not error, but I can't see the image
    # gb_mesh = GeometryBasics.Mesh(GeometryBasics.meta(sp.points; uv=sp.uv, sp.normals), sp.faces) # this used to work, but now errors.
    PlotSpec(Makie.Mesh, gb_mesh,color=sp.img)
end

When I call the plot function on a Sprite object, I used to see the image projected onto a 3D surface, that I could then rotate and place around my environment. However, in the latest version of Makie, I no longer see the image. In fact, the commented line in the plot function produces an error, and when I replace it with the previous line, I do not see the image, but just a beige looking rectangle.

img = FileIO.load("camel.png")
sp = Sprite(mg, Rect2(-1.25, -2.5/1.2/2, 2.5, 2.5/1.2))
plot(sp)

What is the proper way of creating such orientable sprites in GLMakie? The test image “camel.png” can be downloaded from here: Hippocampus.jl/artefacts/camel 1.png at 0ebdc6d5a12eaa01efe4052b99ef54dceaa0b41f · grero/Hippocampus.jl · GitHub

@ffreyer did something change about uvs?

I’m not sure why this has changed, but it seems if you use Point2f for uv, it just silently skips them.

So this fixes it for me: uv=Vec2f.(sp.uv).
Worth opening an issue!

Hm, I still don’t see the image. Could it be a version issue? I’m using GLMakie version v0.22.2?

This is the update plot function, for reference

function Makie.convert_arguments(::Type{<:AbstractPlot}, sp::Sprite)
    gb_mesh = GeometryBasics.Mesh(sp.points, sp.faces; uv = Vec2f.(sp.uv), normal =sp.normals)
    PlotSpec(Makie.Mesh, gb_mesh,color=sp.img)
end

I’m on 0.22.2 and this works:

using Makie
using GeometryBasics
using Colors 

struct Sprite{T<:RGB,T2<:Integer,T3<:Point3,T5<:Vec3}
    points::Vector{T3}
    faces::Vector{TriangleFace{T2}}
    normals::Vector{T5}
    uv::Vector{Vec2f}
    img::Matrix{T}
end

"""
Map `img` onto a flat 3D surface
"""
function sprite(img, rect=Rect2(-0.5, -0.5, 1.0, 1.0))
    points = decompose(Point3f, rect)
    normals = decompose(GeometryBasics.Normal(Vec3f), rect)
    faces = decompose(GLTriangleFace, rect)
    uv = decompose(UV(Vec2f), rect)
    Sprite(points, faces, normals, uv, img)
end

function Makie.convert_arguments(::Type{<:AbstractPlot}, sp::Sprite)
    gb_mesh = GeometryBasics.Mesh(sp.points, sp.faces; uv=sp.uv, normal=sp.normals) # this does not error, but I can't see the image
    # gb_mesh = GeometryBasics.Mesh(GeometryBasics.meta(sp.points; uv=sp.uv, sp.normals), sp.faces) # this used to work, but now errors.
    PlotSpec(Makie.Mesh, gb_mesh, color=sp.img)
end

plot(sprite(rand(RGBf, 100, 100)))

Thanks Simon, indeed it does work! I probably didn’t clear my workspace properly or something just now.