Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster creation of monochrome point clouds #3545

Merged
merged 7 commits into from
Oct 4, 2024

Conversation

voigta
Copy link
Contributor

@voigta voigta commented Aug 20, 2024

This PR reduces the amount of data transferred to the clients in case of monochrome point clouds. Instead of sending the color for each point, one can now set a single color for all points.

Copy link
Contributor

@falkoschindler falkoschindler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this pull request, @voigta!

The JavaScript implementation looks good to me. But I guess we should update the Python API to reflect the different possibilities.

  • So far you had to provide a List[List[float]] containing RGB colors per point.
  • Now you can also pass a single string containing an RGB hex code or a color name.
  • We should probably also allow passing a List[float] containing a single RGB color.
  • And, last but not least, we could support a List[str] if it is easy to implement. That's probably a less common use case.

What do you think? Could you, please, update the API accordingly? Thanks!

@falkoschindler falkoschindler added the enhancement New feature or request label Aug 29, 2024
Monochrome point-clouds can be styled using the .materials method just as any other mesh
@voigta
Copy link
Contributor Author

voigta commented Aug 29, 2024

Hi @falkoschindler,
thanks for the reply. While going though your comments, I found a much simpler way to implement this enhancement: make the per-point colors optional and then simply use the regular .material method to do all the styling.
Does this work for you?

Copy link
Contributor

@falkoschindler falkoschindler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea, @voigta!

However, combining both color sources doesn't seem to be correct in all cases: When setting the color via material ("Mono color") and then via set_points ("Data color"), there's still a material color stored somewhere. When reloading the browser tab, we see a uniform color again.

def generate_data():
    x, y = np.meshgrid(np.linspace(-3, 3), np.linspace(-3, 3))
    z = np.sin(x) * np.cos(y) + 1
    points = np.dstack([x, y, z]).reshape(-1, 3)
    colors = points / [6, 6, 2] + [0.5, 0.5, 0]
    return points, colors

with ui.scene() as scene:
    points, colors = generate_data()
    point_cloud = scene.point_cloud(points, colors, point_size=0.1)

ui.button('Mono color', on_click=lambda: point_cloud.material(color='red'))
ui.button('Data color', on_click=lambda: point_cloud.set_points(*generate_data()))

Besides that, there are different shadings of red when initially clicking the "Mono color" button.

Can you check again if there's a way to fix these conflicts? Thanks!

@voigta
Copy link
Contributor Author

voigta commented Sep 6, 2024

Good catch @falkoschindler! I haven't tried changing between the different "color-types".
Your snipped should now work as expected.

@falkoschindler
Copy link
Contributor

Ok, we're getting there... But I don't quite like the magic string "per point". And if we support the material() method for point clouds, the user might expect to be able to change the opacity as well. Therefore I tried making color an Optional[str] so that you can call point_cloud.material(color=None, opacity=0.2). This required another change in JavaScript to process opacity and side even though color is None.

Here is my new test code:

def generate_data():
    x, y = np.meshgrid(np.linspace(-3, 3), np.linspace(-3, 3))
    z = np.sin(x) * np.cos(y) + 1
    points = np.dstack([x, y, z]).reshape(-1, 3)
    colors = points / [6, 6, 2] + [0.5, 0.5, 0]
    return points, colors

with ui.scene() as scene:
    points, colors = generate_data()
    point_cloud = scene.point_cloud(points, colors, point_size=0.1)

ui.button('Mono color', on_click=lambda: point_cloud.material(color='red'))
ui.button('Data color', on_click=lambda: point_cloud.set_points(*generate_data()))
ui.button('Transparent', on_click=lambda: point_cloud.material(color=None, opacity=0.2))
ui.button('Opaque', on_click=lambda: point_cloud.material(color=None, opacity=1))

Unfortunately this introduced another tiny bug: When clicking "Mono color", "Transparent" and then reloading the browser tab, the points have data color again. 😕

@voigta
Copy link
Contributor Author

voigta commented Sep 14, 2024

Using an Optional[str] is much cleaner that the magic string, that's right!
I cleaned up the code a bit and made sure that color=None will result in vertex colors. The bug you mentioned above is gone with the cleanup and you can freely switch between the colors and transparencies:

def generate_data():
    x, y = np.meshgrid(np.linspace(-3, 3), np.linspace(-3, 3))
    z = np.sin(x) * np.cos(y) + 1
    points = np.dstack([x, y, z]).reshape(-1, 3)
    colors = points / [6, 6, 2] + [0.5, 0.5, 0]
    return points, colors


with ui.scene() as scene:
    points, colors = generate_data()
    point_cloud = scene.point_cloud(points, colors, point_size=0.1)

ui.button('Mono color', on_click=lambda: point_cloud.material(color='red', opacity=point_cloud.opacity))
ui.button('Data color', on_click=lambda: point_cloud.material(color=None, opacity=point_cloud.opacity))
ui.button('Transparent', on_click=lambda: point_cloud.material(color=point_cloud.color, opacity=0.2))
ui.button('Opaque', on_click=lambda: point_cloud.material(color=point_cloud.color, opacity=1))

Copy link
Contributor

@falkoschindler falkoschindler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, @voigta!
Now it seems to work really nicely.
Let's merge! 👍🏻

@falkoschindler falkoschindler added this to the 2.3 milestone Oct 4, 2024
@falkoschindler falkoschindler merged commit 68b56d1 into zauberzeug:main Oct 4, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants