As I’m not using a public constructor, I don’t get how to achieve these lines :
public onRender() {
this.labelRenderer.render(
this.viewer.getRenderer().scene,
this.viewer.getRenderer().renderingCamera
);
}
Cool project! I’ve read your post from showcase and I’m very happy to hear you’re finding Speckle useful!
The example you are mentioning is using a custom viewer extension to display the labels. Generally, extensions are the goto approach on adding/customizing viewer functionality. Extensions offer out-of-the-box frame callbacks like onRender which is being used in the example
I’m not entirely sure what you mean by this, but my assumption is that you are not developing viewer extensions, but rather customizing the viewer library entirely. Maybe you want to give extensions a chance, see if they can make your life easier
The animate function in that three.js example is just a callback for the browser’s requestAnimationFrame. There are multiple ways you can get yourself an animation frame callback. One way would be to extend the SpeckleRenderer and override it’s render or update functions that get automatically called by the viewer. But probably an easier approach would be to just stack your own animation frame callback like they do in the three.js example:
function animate() {
requestAnimationFrame( animate );
// You code here
}
Just remember that you need to manually call animateonce in order to get the loop going
Hi @alex
Thank you very much !
Indeed, to launch the prototype I was playing with a single js file. You are definitely right about extensions, so I have started a new ts project similar to your example.
But I still have a problem : I guess this line doesn’t work from my Labelling.ts to my main.ts file:
The main-.ts file is a test, adding a CSS2DObject to a basic three scene, which works. I am missing something either with ts Extensions or with speckle.viewer.
I’ve checkout out your repo and there is something you are missing. In Labelling.ts extension
public addLabel() {
const earthDiv = document.createElement("div");
earthDiv.className = "label";
earthDiv.textContent = "Earth";
const earthLabel = new CSS2DObject(earthDiv);
earthLabel.position.set(0, 0, 0);
earthLabel.layers.set(ObjectLayers.OVERLAY); <-- This is required
this.viewer.getRenderer().scene.add(earthLabel); // This line doesn't work, earthDiv isnt' added to html
}
The viewer works with object layers as a means of separating stuff that needs to get rendered into ‘categories’ as it were. You don’t necessary need to use ObjectLayers.OVERLAY, as the label’s layer, other layers will work as well, however ObjectLayers.OVERLAY is recommended in this case, because that layer gets rendered at the end and it works nicely with 2D elements.
This would be the only change required in order to get things running, however another thing I recommend is to use the viewer’s ViewerEvent.LoadComplete event to start executing stuff that is stream related. Loading streams is asynchronous in the viewer, so until that event gets fired, you won’t have all the data from the stream available to work with. Also, you don’t need to manually call the onRender function of extensions. That gets called automatically each frame.
Fantastic, it works! Thanks @alex
May I add one question : I’ve added a getNomination() function to the repo : from this, I can get each vertex.Name and vertex.namePosVector of the TopSolid sketches points to which we’ve added nominations. The last value is the position of the letter to the point relative to the 2d screen (so to be handled as css padding or margin)
My question is : these points are of speckle_type: “Objects.Geometry.Point”. How can I obtain there position in space? Three getWorldPosition() method doesn’t seem to work
For ease of use, I’ve made this live sandbox which shows how you can get point positions and also adds labels to those locations (not sure if that was your intention, but I did it anyway )
Currently there is extra complexity in retrieving point and line geometry data, but we are planning on adding some abstractions on top, like we did with meshes via BatchObject, sometime in the future