Thebes.jl icon indicating copy to clipboard operation
Thebes.jl copied to clipboard

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

Open RenuSolanki opened this issue 1 year ago • 5 comments

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 ?

RenuSolanki avatar Dec 23 '22 19:12 RenuSolanki

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.

cormullion avatar Dec 23 '22 19:12 cormullion

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.

RenuSolanki avatar Dec 23 '22 20:12 RenuSolanki

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. 😄

cormullion avatar Dec 24 '22 15:12 cormullion

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))
        )    
    )
)

RenuSolanki avatar Jan 01 '23 16:01 RenuSolanki

Cool stuff!

cormullion avatar Jan 02 '23 11:01 cormullion