jupyter-widgets / pythreejs

A Jupyter - Three.js bridge
https://pythreejs.readthedocs.io
Other
936 stars 187 forks source link

Access World Position of Object #218

Closed JunkyByte closed 5 years ago

JunkyByte commented 5 years ago

Hello! Sorry but I'm completely inexperienced with both ThreeJS and JS in general.

I'm trying to draw lines between objects but I can't find a way to access an object world position when it is a child of another, I found a lot of documentation on how to do this in Threejs but I can't find corresponding functions in Pythreejs.

Example:

parent = Mesh(..., position=[0,10,0])
child = Mesh(..., position=[0,5,0])
parent.add(child)
print(child.position) 
# Returns [0,5,0] as the position is local, but it's world pos. is [0, 15, 0] 

Thank you in advance, great work on this library, impressing!

JunkyByte commented 5 years ago

Update, I managed to access the world position with

child.exec_three_obj_method('updateMatrixWorld')
child.worldMatrix[12:15] # 12x, 13y, 14z

But as the call is Async. I need to find a way to get notified when the actual call has been made and the matrix has changed, I tried with observe but it doesn't work (It works for names like 'position' or 'rotation)

child.observe(handler=f, names=['worldMatrix'])
parent.position = [x, y, z]
child.exec_three_obj_method('updateMatrixWorld')

could anyone point me out in the right direction? Thanks!

JunkyByte commented 5 years ago

As I didn't manage to get the observe I just did the opposite and used a thread to verify when the value changes. I also found a way to simply use local positions -.-" I just had to set the line as a child of the parent so that it now has its global position by default.

def update_matrix(inp, out, color):
    inp.exec_three_obj_method('updateMatrixWorld');
    out.exec_three_obj_method('updateMatrixWorld');
    worker = Thread(target=wait_for_update, args=[inp, out])
    worker.setDaemon(True)
    worker.start()
vidartf commented 5 years ago

Thanks for posting back how you resolved the issue!

For reference: The newest ipython kernel is supposed to support async directly, but we're still trying to figure out the best way to combine this with widgets!