Looking up mesh vertices from viewer api

I’ve been using the new viewer package and I’ve been really liking the new functionality built in :slight_smile: I was wondering if there is a way to access the vertices, or at least the vertex count, from a mesh after it’s been loaded by the viewer? I figure I can grab the mesh buffer positions to get the vertex count but I thought it would be smarter to use the viewer tree nodes. I’ve been trying a few ways, but whenever I drill down to the vertices property its empty.

// grab the props of a model after load complete
const props = await viewer.getObjectProperties(somePath).filter(...)

// or by the render nodes
const nodes = viewer
.getWorldTree()
.getRenderTree()
.getRenderViewNodesForNode(viewer.getWorldTree().root);

I’m guessing that I’m looking in all the wrong places…

Hi @haitheredavid

We’re glad to hear you’ve been experimenting with the viewer API! :slight_smile:

Getting the geometry data for objects is very much possible, however it does involve a few extra steps. The viewer batches together geometry for rendering, so there is no per-object access to geometry available. The vertices properties in the speckle objects are indeed empty because we first copy them over to the larger batch buffers, and then we delete them! We do that do minimize redundancy and reduce memory footprint

Here is a complete live example that creates copies of selected objects to exemplify how individual object geometry can be read from it’s batch.

In short, each NodeRenderView will have the batchStart and batchEnd which specify the location of it’s indices inside the batch’s index buffer and also vertStart and vertEnd which specify the location of it’s vertex positions inside the batch’s position buffer. With these properties you can easily reconstruct each individual object’s geometry data. Also note, that batchStart and batchEnd do not remain constant during the viewer lifecycle. They will change in time while the batch reshuffle’s it’s index buffer for optimal draw call count.

Let us know if you need more help with this

Cheers

1 Like

hihi @alex :wave:

This is great, thank you for the speedy reply and info! I didn’t realize there was an actual api page for the viewer :exploding_head: I’m going to have to play around with a custom loader at some point.

The example you provided helped clarify everything I needed. This is what I ended up hacking together to grab the vertex count for each mesh in the scene. Seems to do the trick :white_check_mark:

const nodes = viewer
	.getWorldTree()
	.findAll(
		(node: TreeNode) =>
			node.model.renderView &&
			node.model.renderView.geometryType === GeometryType.MESH
	);

const renderTree = viewer.getWorldTree().getRenderTree();
for (const node of nodes) {
	const rvs = renderTree.getRenderViewsForNode(node);
	const rv = rvs[0];
	/* multiply by 8 for number byte size */
	const size = (rv.vertEnd - rv.vertStart) * 8;
}
1 Like

Happy you got it working @haitheredavid ! :slight_smile:

I have no context as to what you are trying to do, so I apologize if my comment is out of place, but the byte size wise the vertex positions for an object would be (rv.vertEnd - rv.vertStart) * 3 * 4 since each position has 3 floats (x,y,z) of 4 bytes each.

Looking forward to seeing what you have planned for the custom loader! :starstruck_spockle:

Cheers

1 Like

ah that is a good point @alex ! I was being a bit of a simpleton with just getting the array size, but it should be done by vertex size like you noted :pray:

I’m revisiting an old speckle project that was calculating the density of a mesh and creating a lil dashboard with it. The density formula is simple, just byteSize / bbox.volume. If you have any more suggestions, please share away :slight_smile:

pew pew :arrow_down_small:

1 Like

Different medium, but it started life from dirstat so use anything you find useful.

The specific calculation was plan area so vertical objects were denser than horizontal but the code has box volume calls there too.

2 Likes

I was snooping through this over the weekend :slight_smile: I noticed some meshes that are completely flat have no volume which messes up the density calc. I think I’ll need to implement a similar 2d like the automation does. Copy :spaghetti:

We also don’t always create a bound box on every element which was kiboshing the automate version, but i think threejs gives that as a freebie - so depends what you are building in ad which data you’re using.

1 Like