I am trying to build upon a speckle idea from the last hackatron. the Mass On Speed.
and am i trying to build a webapp that loads a speckle model and then overlays an obj over the model.
i am using typescript for overlaying the obj with the ObjLoader from speckle.
I am using the following code for this:
async function overlayObj(objData: string, id: string) {
if (!viewer) {
console.error("Viewer is not initialized");
return;
}
if (lastLoaded) {
viewer.unloadObject(id);
console.log("Disposed last loaded object");
}
/** Create a loader for the .obj data */
const loader = new ObjLoader(viewer.getWorldTree(), id, objData);
/** Load the obj data */
await viewer.loadObject(loader, false);
// this seems to be sepckle stuff
const tree = viewer.getWorldTree();
// get node from loader.tree.nodeMap with id and set the colour of the object to red
const nodes = viewer.getWorldTree().findId(id);
// Set the color of the object to red
if (nodes && Array.isArray(nodes) && nodes.length > 0) {
for (const node of nodes) {
for (const child of node.children) {
const obj = child.model.raw;
if (obj.isMesh ) {
obj.material.color.set(0xff0000);
console.log(`Node ${node.id} color set to red`);
} else {
console.error(`Node.model is not a THREE.Mesh: ${child.model}`);
}
}
}
} else {
console.error("Node array is empty");
}
// Refresh the viewer
viewer.requestRender();
lastLoaded = loader;
console.log("OBJ file loaded successfully");
}
but this code loads the obj propperly but does not colour it red.
any help on how i can colour the loaded OBJ in red would be appreciated.
i am not getting any errors in the console and it seems that the script changes the material colour, but nothing happens.
i really am a beginner in undestranding programming and how speckle and three work together.
You are trying to apply a material to a BlockInstance which in the context of the OBJ content would be the equivalent of a group that is not displayable in any way.
You are getting the render views, but only applying the material to the first one, renderViews[0] which is a BlockInstance and does not have nor take materials. What you probably want is to apply the material to all the renderViews returned by the call to getRenderViewsForNodeId. Also note thatsetMaterial takes an array of renderviews as it’s first argument.
If you have a look at the live example I’ve prepared for you, you will see that it’s functioning properly
thank you for the live example. i see that is working with load obj from a file.
unfortunately i am creating my obj using js from contours detected in an image.
so i use the objloader with an id and objData.
i have setup a live example (simplified) of the workflow i use for speckle.
the stating point is a very simple objData for an icosahedron.
There is a particularity of the OBJLoader which makes the group objects atomic, which in turn makes the render tree not return it’s children when executing calls of the getRenderViews.... So nothing was getting colored, because the child object, the mesh, was not present in the array passed to setMaterial.
To circumvent this, you can get the child render views manually, like I’ve shown in your live example.