pythreejs icon indicating copy to clipboard operation
pythreejs copied to clipboard

geometry.attributes.color.needsUpdate for BufferGeometry

Open PBrockmann opened this issue 5 years ago • 12 comments

Is there a way to update the color BuffetAttribute from a BufferGeometry ?

geometry = BufferGeometry(attributes=dict( position=BufferAttribute(pList), color=BufferAttribute(cList), ))

Changing the color attribute on geometry does not change the display. geometry.attributes['color'] =BufferAttribute(new_cList)

A notebook to test this is available from https://gist.github.com/PBrockmann/f155a779382e2b8dec7543f3466e0798

PBrockmann avatar Apr 02 '19 21:04 PBrockmann

The main issue here is that in-place modifications of a dict does not generate any trait notifications.

There are two ways to work around this:

  • Re-assign the entire attributes dict. With a newer Python version you can do geometry.attributes = dict(**geometry.attributes, color=BufferAttribute(new_cList)), or something along those lines.
  • Re-assing the array on the BufferAttribute: You can assign a new ndarray to the array field of the attribute. If you feel like the overhead of creating a new array is too heavy, I have some optimization you could possibly use.

vidartf avatar Apr 04 '19 20:04 vidartf

Example for the latter case above: geometry.attributes['color'].array = new_cList

vidartf avatar Apr 04 '19 20:04 vidartf

Ahhh... Thanks. In fact, I had forgotten to reassign the array. geometry.attributes['color'] = new_cList should be geometry.attributes['color'].array = new_cList

I have tested quickly and basic cube example works. I will correct the gist accordingly.

Next step for me is to test how fast can be the update in my real case. The purpose is to make an animation from a netcdf variable using the play ipywidget. Event will trigger:

  • read next slice of data
  • recreate the colors array (float to rgb values)
  • update the bufferGeometry and its attribut color array with the new color array

PBrockmann avatar Apr 04 '19 22:04 PBrockmann

I have prepared a notebook to test hown to update a BufferGeometry but the efficiency is not good enougth to imagine an animation.

https://gist.github.com/PBrockmann/ee69c705ab5fca8854323e807cbd8863

Is there optimization to do ?

PBrockmann avatar Apr 05 '19 19:04 PBrockmann

Is there optimization to do ?

Always 😉 The questions is where your current bottlenecks are (kernel, network, JS, GPU?), and how your final thing will differ from the test notebook.

vidartf avatar Apr 07 '19 07:04 vidartf

Hi @vidartf, I have just released a current work that uses three.js. The application reads netcdf variables and offer to the user to display variables as synchronous maps. Animations are quite efficient in this design (pure js).

Please, have a look to: https://github.com/PBrockmann/threejsMap

Now, I would like to rebuild this application for python notebooks. Using pythree.js should be the right code for this I believe. Variables should be read and post-processed by the user in a previous steps (cells) and then only when ready the user would request for a display of the different XYT variables that are present in memory. Animations should be proposed as well.

So to answer you, yes, I am really looking for optimization in the simple example I have coded using pythree.js that is less efficient than what I have done with three.js (animations in last case are fluid).

PBrockmann avatar Apr 08 '19 15:04 PBrockmann

Hi @vidartf, Any clue to optimize the Gist code above ? Your lights would be more than welcome.

PBrockmann avatar Apr 16 '19 13:04 PBrockmann

Sorry for the slow response here. Its hard to put the time in to go over it in detail, when I don't really know how your example translates for actual files. Some general points though:

  • Ideally, you would probably want to transfer as little data over the network as possible, and transform the data on the client. The package ipyscales might help you with that.
  • Are you streaming data as soon as it becomes available to you, or do you have all the data in one go, and simply want to loop over a slice of it?

vidartf avatar Apr 29 '19 11:04 vidartf

Hi, Back on this issue. Yes I am in the case where all the data are already in memory (transfert is indeed another problem). But in this specific case (all in memory), I would like to update colors produced from new values as fast as possible to make animation possible. So starting from the notebook that I have prepared, how to optimize the code ? Actually the update takes more than 1 second.

PBrockmann avatar Jun 03 '19 14:06 PBrockmann

I've had on my roadmap for ipydatawidgets for a while to upload an array, and then output a slice of that depending on an index input (and an input for which axis/axes to slice). That would help you only upload your data once (but would put a larger amount of data in client). Then you can use that as input for your colors, which you could do in one of two ways:

  • Compute the vertex colors from the input in JS, e.g. using something like ipyscales.
  • Use a custom shader and another vertex attribute to compute the vertex color in the shader directly.

vidartf avatar Jun 04 '19 11:06 vidartf

I have investigated use of ipyscales but cannot figure out how to use a ScaledArray with a BufferGeometry. Documentation from ipyscales https://ipyscales.readthedocs.io/en/latest/examples/scaled-data.html#Color-mapped-data didn't help enough.

PBrockmann avatar Jun 06 '19 17:06 PBrockmann

I'll put this on my TODO list to try to do make as realistic an example as possible. It might be a week till I get around to it though, but ping me if I forget, or you have some dependency free data / use case that you think would be illustrative!

vidartf avatar Jun 11 '19 21:06 vidartf