This sample shows how to upload 3D models into a 3D object layer, and edit them using the SceneLayer class. Importing a model consists of a few steps:
- Uploading a model file (for example a glb or fbx file) and converting it to a Mesh
- Placing the mesh in the view
- Persisting the model into the 3D object layer through a SceneLayer instance
The sample also directs you to the necessary resources to learn how to set up 3D object layers that support this workflow.
Placing the model
You can create a mesh from a file using the sceneLayer.convertMesh method. To make the model visible, we must also place the mesh geometry into a graphic on the view. In this sample we manage this graphic with a SketchViewModel. This makes the model immediately editable and allows you to control the placement of the model. We get the mesh into the SketchViewModel using the sketchVM.place method.
const { mesh } = await sceneLayer.convertMesh([file]);
sketchVM.place(mesh, { graphicProperties: { layer: sketchLayer, },});Placing the model with georeference information
If the uploaded model is georeferenced (i.e., it contains location metadata), sceneLayer.convertMesh returns additional information in georeferenceInfo alongside the mesh. When georeferenceInfo is present, the sample auto-places the model at its real-world position, adds it to the sketchLayer, and makes it editable. The view also navigates to the model.
If georeferenceInfo is absent, the workflow falls back to interactive placement using SketchViewModel.place.
const { mesh, georeferenceInfo } = await sceneLayer.convertMesh([file]);
if (georeferenceInfo) { // Georeferenced model: auto-place at correct location if (georeferenceInfo.origin.spatialReference.equals(mesh.spatialReference) === false) { showGeoreferencedModelWarning(); } else { showGeoreferencedModel(); }
const meshGraphic = new Graphic({ geometry: mesh, attributes: { deviceId: deviceId }, symbol: { type: "mesh-3d", // autocasts as new MeshSymbol3D() symbolLayers: [ { type: "fill", // autocasts as new FillSymbol3DLayer() }, ], }, });
sketchLayer.add(meshGraphic); sketchVM.update(meshGraphic); // make it editable viewElement.goTo({ target: mesh }).catch(() => {});} else { // Not georeferenced → manual placement sketchVM.place(mesh, { graphicProperties: { layer: sketchLayer, attributes: { deviceId: deviceId }, }, });}Persisting the changes
After the model is placed you can persist the changes using the sceneLayer.applyEdits method.
When updating or deleting features, each item must have a valid objectId or globalId corresponding to the feature being changed.
await sceneLayer.applyEdits({ addFeatures: graphics,});
await sceneLayer.applyEdits({ updateFeatures: graphics,});
await sceneLayer.applyEdits({ deleteFeatures: ids,});Note that updateFeatures does not add features that are not already present in the layer, for those features you must use addFeatures.
Sample workflow
The workflow the sample demonstrates can be broken up into a few steps:
- File loading: The sample implements loading of user files either through a file picker or by dragging and dropping them into a designated area.
- Model uploading: The
uploadModelfunction takes a SceneLayer and a File instance, converts the file into a mesh, positions it at the mouse cursor’s location using theplacemethod of the SketchViewModel (SVM), and adds it as a Graphic to the GraphicsLayer. - Mesh selection and hiding: When the SVM is updated and a Graphic is selected (the event state is
start), the sample attempts to hide the model with the sameobjectIdfrom the 3D object layer. Two scenarios are possible here:- If a new model has been added, it will not yet have an
objectId(it will receive it upon being saved to the layer). As a result, no hiding will occur. - If an existing model has been retrieved from the 3D object layer (see “Retrieving stored models” below), it will have an
objectIdand will be hidden from the layer.
- If a new model has been added, it will not yet have an
- Adding, updating, and deleting features: Deselecting a Graphic (which can happen after manipulating it) triggers another SVM update with the event state
complete. At this point, the sample again checks for the presence of theobjectId:- If it is absent (newly added model)
applyEditsis used to add the model to the layer. This method assigns anobjectIdto the feature and as an attribute to the Graphic. The model is then hidden from the 3D object layer. - If it is present,
applyEditsis used to update the model’s attributes in the database. The updated model is then again displayed from the 3D object layer but the sample hides it as an identical Graphic still exists in the GraphicsLayer, and it is better suited for further manipulation. Pressing the delete key with the Graphic selected, deletes it from the GraphicsLayer, and triggers the SVM (the event state isdelete) to delete the selected model from the 3d object layer usingapplyEdits.
- If it is absent (newly added model)
Retrieving stored models: When a scene is loaded, and a user clicks on a feature already stored in the 3D object layer, the view’s hitTest method is used to find the feature’s objectId. It then queries the 3D object layer, retrieves the corresponding Graphic, adds it to the GraphicsLayer, and updates it through the SketchViewModel, which brings us back to step 3.2.
Learn more about 3D object layers
A 3D object layer is a unit consisting of a 3D object scene layer with a 3D object feature layer. The scene layer facilitates efficient display and loading, while the associated feature layer stores the data for editing and querying. This 3D functionality is integrated within the SceneLayer class, allowing you to use SceneLayer.queryFeatures() to retrieve results directly from the associated feature layer.
For a detailed overview of 3D object capabilities and workflows, please refer to:
- 3D Object Layer: A Comprehensive Overview blog post.
- 3D Object Layer in ArcGIS Maps SDK for JavaScript
- 3D object workflows in the SDK guide page.