MouseEvent callback lag with mesh selection

The issue I’m facing right now is that when there are thousands of selectable thininstances in the scene, every mouse down / up event triggers a callback that takes ~ 400-600 milliseconds to execute, so with a full click event, its takes around 1100 milliseconds to execute. I tried the following:

  1. Using a selection octree with the scene after everything is loaded like so:
    const capacity = 64 const maxDepth = 2 this.selectionOctree = this.scene.createOrUpdateSelectionOctree(capacity, maxDepth)

  2. Setting scene.skipPointerMovePicking = true
    (I can’t actually use this option in my project but I wanted to see if it would make a difference)

Just to give you an idea of the methods being invoked that take up the most time I took a chrome profiler snapshot while running my actual app:

I believe that Event: pointerdown callback present in the screenshot ^ is being invoke internally by the ArcRotateCamera class - is this right? My reasoning for thinking so is that I can produce a similar profiler snapshot within a playground scene with just a camera and the models that I built to to emulate what’s happening in my project:

Ideally in game I’ll be able to select a given rock without too much delay but also be able tp pan the camera smoothly while navigating the 3d terrain. My thought process was that since each thininstance is selectable, its own click event coordinates and mesh properties can be used with an octree. Presently an octree sounds like the best route to me though I’m open to suggestions.

Any help would be highly appreciated!

cc @PolygonalSun

One solution also is using a NullEngine in a worker to handle selecting. There is an ever so slight delay but performance issues go away.

2 Likes

Hey folks, just wanted to give a heads up that we do have tasks in the pipeline to improve input overhead and picking. The plan for this is to have perf improvements for input in place by the end of the month and picking changes by end of August. In the meantime, I can use this PG and the info to see if I can pinpoint what could be happening though it might take a bit for me to dig into this because I’m gonna be out of the office for several days starting this week.

3 Likes

So also I’m looking at some of the solutions here that claim to use GPU for picking -

In particular, these two:

Can someone explain exactly what the concepts & principals are behind these two examples?

1 Like

Okay nvm, I think I understand it now.

  1. Assign each thininstance a unique rgb color
  2. Read out the literal pixels on the screen where the mouse is
  3. match the unique rgb colors of the pixels to the thininstance

But I don’t see how I can use that for objects that are not one solid opaque color

Still looking for a good picking solution.

@arcman7

But I don’t see how I can use that for objects that are not one solid opaque color

In the PG you referred, the color used for picking is applied before rendering.

    renderTarget.onBeforeRender = () => {
        box.thinInstanceSetBuffer("color", rttColorData, 4);
    }

And before completing the rendering frame, the following line is called to set back the colors of cubes to the visual color on screen.

renderTarget.onAfterRender = function () {
.....
box.thinInstanceSetBuffer("color", colorData, 4);

}

I have tried it yet. But I guess it will require a custom material with a custom attribute e.g. ‘pickColor’. Then send pickColor in the onBeforeRender call for the thin instances, which instructs customized fragment shader to apply the single color. And unset the pickColor afterwards to render the actual texture for your model.

BTW, what pointer events you are talking about that cause the performance issue? When I open your PG, FPS is already very low without triggering any mouse/keyboard event.

Hi Slin,

Woah! Definitely did not realize that was what’s happening there in those before and after callbacks. I will definitely try that out!

BTW, what pointer events you are talking about that cause the performance issue? When I open your PG, FPS is already very low without triggering any mouse/keyboard event.

Yes. I assumed it was something internal to the arcrotate camera as well as the other cameras, it only happens when the thininstances are set to be pickable. You’ll notice that in the demo pg you referenced, it does not use thinInstanceEnablePicking = true. So whatever is about that setting it affects cameras by default.

Yes. I assumed it was something internal to the arcrotate camera as well as the other cameras, it only happens when the thininstances are set to be pickable.

I use FreeCamera and implemented my own customized arc rotation. That’s probably why I didn’t encounter this issue. GLHF :smile:

@slin Wait are you able to use large numbers of pickable thininstances without the camera slowing down?

No, I didn’t have problem with it. 800 samurai, ~1000 trees, ~100 building blocks, and some rocks. I had problem with picking on mouse hover since mouse move is triggered in high frequency. I was able to get it to an acceptable level by throttling mouse move events, but I will definitely try GPU picking when I have time. For mouse click based picking, I never had performance issue.

1 Like

Here’s my best attempt at getting this GPU selection method working for my usecase:

You’ll notice the blue-ish rocks, that’s an artifact of not being able to set the color back to what it was originally in the renderTarget.onAfterRender callback method. However because of that it’s visually easy to tell which rocks to test with by hovering the mouse over them and seeing what thininstance is identifed by the GPU selection process.

It’s pretty flakey, hovering some areas of the blue rocks with the mouse work - it logs the correct thininstance id - but more often it just doesn’t read the correct pixel values that correspond to the thininstance colorId.

You’ll also notice that I tried to generalize the method to work with different sets of thininstances (where each set corresponds to a different rootMesh). That code makes no difference on the net result right now since this is only being tested with one set.

Unless someone has solution that fixes both not setting the original color back, and always selecting the correct thininstance based on mouse position I’m going to look into other solutions that utilize the ammo js physics engine I’m working with.

Hi @arcman7

The latest PG is less laggy on my laptop. I was able to open inspector this time. Your GPU frame time is quite high already: 18ms per frame. From my experience, I feel the texture resolution is too high in your scene. You have several 2048*2048 textures and the terrain is even 4096 * 4096.

Are you the one who wants to build a large open world? You probably need to use smaller terrain tiles. Make the tiles as instances as well. By doing this you can split the heightmap to multiple images with lower resolution, and apply these images to each terrain tile instances. For rocks in the scene, you can also use models with lower resolution texture images.

You have several 2048*2048 textures and the terrain is even 4096 * 4096.

Can you explain a little more what you mean by these numbers? When I open the inspector and scroll through the textures and materials properties, it isn’t immediately obvious to me what you mean by 2048^2 and 4096^2.

Are you the one who wants to build a large open world?

Yes, that is my goal. I’ll be looking into splitting the world into smaller content regions, that is the only way I’ll be able to get the physics working for each rock and tree that comprises the open world environment.

Hi @arcman7

Pease see the image width/height at the bottom of screenshot for a selected texture. That’s what I referred to as your texture resolution.

@slin I’m trying to use the approach of splitting up a large world map into smaller pieces, as you suggested, here:

I don’t get why the texture images for each mesh do not fit the mesh. Each mesh has:
mesh.material.albedoTexture.uScale = 1
mesh.material.albedoTexture.vScale = 1

So shouldn’t that fit the entire image to each mesh exactly once?

There is an error in the PG when I open it. Could you check?

Woah, sorry, that is so odd how I did not see that earlier. My bad.

It takes a minute or so for the scene to load on my machine. So if you don’t see anything for a bit, don’t worry, its just the massive normal map png being loaded (I haven’t split that one yet and all the original files are loaded first anyways).

I didn’t look why is that. But it looks better if I set:

        texture.uScale = 10
        texture.vScale = 10
1 Like