cormullion / Thebes.jl

Thebes.jl is a simple little package that provides 3D services to Luxor.jl.
https://cormullion.github.io/Thebes.jl/
Other
32 stars 3 forks source link

Is there a way to implement mouse interaction in Thebes scenes ? #13

Open RenuSolanki opened 1 year ago

RenuSolanki commented 1 year ago

I am willing to use Thebes in one of my own projects. However, I need interactive scenes which can be rotated using mouse just like in MeshCat for example. Is there a way to achieve this in Thebes ?

cormullion commented 1 year ago

Hi there! Unfortunately there's no interactivity ๐Ÿ˜‚ - in my view Thebes is not really a good base to build on - I'd recommend Makie.jl for proper 3D and interaction.

RenuSolanki commented 1 year ago

Makie provides interactivity but for 3D animations I find Thebes comparatively more intuitive to use. Moreover, Makie has an annoyingly large first time compilation issue.

cormullion commented 1 year ago

Iโ€™m happy itโ€™s useful - Iโ€™ve always seen it as a learning exercise rather than anything else.

I did do this once:

https://plutocon2021-demos.netlify.app/cormullion%20โ€”%202%C2%BD%20d%20graphics

which was fun but not much more than that. ๐Ÿ˜„

RenuSolanki commented 1 year ago

With help from a friend I have implemented partial mouse interaction. The following code does only z rotation when mouse moves horizontally. I am not sure how to correctly transform the eyepoint for vertical mouse movement. Zoom effect is also to be implemented.

using WebIO, Thebes, Luxor, Interact, JSExpr

function drawcube(x,y,z,p)
    d=Drawing(800, 800, :svg)
    origin()
    Thebes.background("black")
    helloworld()
    eyepoint(x,y,z)
    perspective(p)
    object = make(Thebes.Cube, "cube")
    scaleby!(object, 80, 80, 80)
    pin(object)
    axes3D(300)
    finish()
    d
end

scope = Scope()
pagex = Observable(scope, "pagex", 0.0)
isdown = Observable(scope, "isdown", 0)
motionx = Observable(scope, "motionx", 0.0)
pagey = Observable(scope, "pagey", 0.0)
motiony = Observable(scope, "motiony", 0.0)
zoom = Observable(scope, "zoom", 0.0)
xe = Observable(300.0)
ye = Observable(0.001)
ze = Observable(0.001)
po = Observable(400.0)
valsx = [0.0]
valsy = [0.0]
on(motionx) do dx
    if isdown[]==1
        l,m,n=rotateby(Point3D(xe[],ye[],ze[]),0.0,0.0,-dx*0.02)
        xe[],ye[],ze[]=l,m,n
    end
end

img = Interact.@map drawcube(&xe, &ye, &ze, &po)

scnd = scope(Node(:div, img, events = Dict(
            "mousedown" => (@js (e) -> (e.preventDefault();$isdown[]=1;$pagex[]=e.clientX;$pagey[]=e.clientY)),
            "mousemove" => (@js (e) -> (e.preventDefault();$motionx[]= (e.clientX-$pagex[]);$motiony[]= ($pagey[]-e.clientY);$pagex[]=e.clientX;$pagey[]=e.clientY)),   
        "mouseup" => (@js (e)-> (e.preventDefault();$isdown[]=0;$motionx[]=e.clientX-$pagex[];$motiony[]=-e.clientY+$pagey[])),
            "wheel"=>(@js (e)-> (e.preventDefault();$zoom[] = e.deltaY))
        )    
    )
)
cormullion commented 1 year ago

Cool stuff!