Split or duplicate material of lines

Hi @alex,
Regarding the geometry viewer.
We are sending custom lines styles (dots etc) as custom metadata.
Which means, in the default speckle viewer, these styles are not interpreted and the lines appear the same.
Which also mean, they share the same material.

Is it possible to split/duplicate this material to handle it for each case separately (dot, continuous etc)?

Here is the current code: geometrie-pour-architectes/src/extensions/linesStyles.ts at b8768339422eb68cd659d1460cc5aa2b88ad7c73 · ENAC-CNPA/geometrie-pour-architectes · GitHub

Thanks

Hi @RaphaelVouilloz

You can apply any material (respecting primitive type of course, meshes, lines, points) to any object regardless if they are in the same batch or not by using setMaterial

Cheers

1 Like

Hi @alex
I’m coming back to this issue. How can I create a new SpeckeLineMaterial?
Scenario: I have one sketch with two lines. On the standard Speckle viewer, they share the same material. But I have had some metadata in the connector, which specify that one is dotted, the other not (solid).
My goal is to create a new material, use your fastCopy method to kind of duplicate the material, so that when I update the material for the dotted line it doesn’t affect the solid line.
Thanks

Hi @RaphaelVouilloz

Lines are a bit different than meshes and points in the speckle viewer, in that you cannot set any material to one or more render views (objects) that belong to the same batch. So if you have two lines inside a batch, you can color them differently or set different opacities for each, but you cannot have one dotted and not solid, or one thicker than the other.

In order to achieve what you want, you first need to make sure dotted lines and solid lines will not get batched together. In order to do that, you can set different colors, opacities, or line weights for their display styles.

Once you have them in different batches you can create a new line material by using the batch material’s constructor like so:

const material = new batch.batchMaterial.constructor()

Typescript will loose it’s mind if you do it this way, along with all the world’s purists, but in the last public viewer-library version, SpeckleLineMaterial is not exposed. I’ll make sure we expose that, along with any other missing material types in the next update.

Technically, if dotted was something officially supported there would be no need for workarounds, but until it is, artificially splitting batches is going to be required. I also think that it might be possible to dynamically split your lines into separate batches at runtime, but that might be more involved than just having them split at load time.

Cheers

1 Like

Thank you @alex for the answer! Indeed I was not sure why I couldn’t import SpeckleLineMaterial.
Just to know if these workarounds are worthwhile: on what timescale do you plan :
-the next update with SpeckleLineMaterial exposed ?
-support for dotted ?

I’m also willing to try splitting the batch at runtime because I’m in charge of this development, whereas for the connector I’m dependent on other people who have little time to devote to it, and I already have a few evolution requests pending. Do you have any advice? :smiley_spockle:
Thanks!

It’s up on latest 2.26.9 version

This is not something we will be focusing on in the near future unfortunately.

Ok, let’s see what we can do about this. I’ll provide you some guidance as soon as I find a few free minutes

Cheers

1 Like

Thanks!! :smiley_spockle:

Hi @RaphaelVouilloz

Here is a live example with realtime line batch editing and creation.

We extract three existing lines from two batches (it can be as many batches, doesn’t have to be a single batch), we rebuild the batches without these lines, and finally create a new line batch with only the extracted lines.

You will see in the example that three lines have red dotted materials.

Cheers

1 Like

Thanks a lot @alex!!
I could adapt your script to my code and it works really nice in the case where I need to deduplicate the material just one time, as in your example.
But if I have to run it as a function on multiple items, it deduplicates the material for the first item as expected, but then keeps updating this same material instead of creating new ones and I am back to the same problem.
If I console.log the material, it confirms that it is the same material.
My code is here: github

In other words, in your example, you choose three objects and change them from blue to dashed red. How would you make one of them with another dashScale value?

Here’s an updated version where one of the separate lines has a different material applied. It doesn’t matter how you split the lines or what material you are applying to them

You where probably passing the same material hash (first argument) to batcher.materials.getMaterial. That function will returned an existing material for the hash value your provide. It will not make a new one each time. So the material hash that you pass in is important. If you want a new material, the hash value you pass needs to be unique

1 Like

Thanks a lot @alex. It was very useful, and I was able to successfully implement it in my code:
https://github.com/ENAC-CNPA/geometrie-pour-architectes/blob/cef996b7159803af4f066d7393c26362b39804a2/src/extensions/linesStyles-v2.ts
Unfortunately, while it works well for line graphics, it causes me problems with IDs in other extensions I’ve developed, such as sets and showing/hiding dimensions with a double-click.
I think I’ve identified the problem, which is that the parent of the modified lines changes to take on the same ID.
I don’t get it because here it seems to be remove and add to the same parent:

/** Go over each batch and rebuild the geometries after we've extracted the lines */
    for (let k = 0; k < batches.length; k++) {
      const batch = batches[k];
      /** Remove batch renderable from scene, as we'll make a new one */
      const sceneParent = batch.renderObject.parent;
      sceneParent?.remove(batch.renderObject);
      /** Rebuild the batch and set it's material */
      await batch.buildBatch();
      batch.setBatchMaterial(batch.batchMaterial);
      /** Add it's new renderable to the scene (rebuilding created a new renderable) */
      sceneParent?.add(batch.renderObject);
    }

It’s getting a bit complex, so I understand if you don’t have time to look into it. I can also abandon this issue for now and wait until you have official support for dashed lines! :smiley_spockle:

The parent of the batch’s render object does not change. Just the render object, which indeed is a new three object since buildBatch creates a new one. So if the issue lies with parents and their children, it would be a three.js related issue since the viewer still uses three’s built in scene graph at the end of the day.

1 Like

This topic was automatically closed after 180 days. New replies are no longer allowed.