Skip to content
View on GitHub

Add a layer to a local scene to visualize and interact with 3D building models developed using Building Information Modeling (BIM) tools.

Image of add building scene layer

Use case

Building Scene Layers allow you to display and analyze detailed building models created from 3D BIM data. Unlike 3D object scene layers, which represent all features within a single layer, Building Scene Layers are organized into a hierarchy of sublayers representing individual building components such as walls, light fixtures, and mechanical systems. These sublayers are often grouped by disciplines like Architectural, Mechanical, or Structural. This structure enables deeper interaction and analysis of both interior and exterior features, providing insight into how a building is designed, used, and situated in its spatial context.

How to use the sample

When loaded, the sample displays a scene with a Building Scene Layer. By default, the Overview sublayer is visible, showing the building's exterior shell. Use the "Full Model" toggle to switch to the Full Model sublayer, which reveals the building's components. Pan around and zoom in to observe the detailed features such as walls, light fixtures, mechanical systems, and more, both outside and inside the building.

How it works

  1. Create a local scene object with the ArcGISScene.withBasemapStyle(BasemapStyle, SceneViewingMode) constructor.
  2. Create an ArcGISTiledElevationSource object and add it to the local scene's base surface.
  3. Create a BuildingSceneLayer and add it to the local scene's operational layers.
  4. Create an ArcGISLocalSceneView object and add the scene.

Relevant API

  • ArcGISLocalSceneView
  • ArcGISScene
  • ArcGISTiledElevationSource
  • BuildingSceneLayer
  • BuildingSublayer

Tags

3D, buildings, elevation, layers, scene, surface

Sample Code

add_building_scene_layer.dart
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2025 Esri
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import 'package:arcgis_maps/arcgis_maps.dart';
import 'package:arcgis_maps_sdk_flutter_samples/common/common.dart';
import 'package:flutter/material.dart';

class AddBuildingSceneLayer extends StatefulWidget {
  const AddBuildingSceneLayer({super.key});

  @override
  State<AddBuildingSceneLayer> createState() => _AddBuildingSceneLayerState();
}

class _AddBuildingSceneLayerState extends State<AddBuildingSceneLayer>
    with SampleStateSupport {
  // Create a controller for the local scene view.
  final _localSceneViewController = ArcGISLocalSceneView.createController();

  // A flag for when the local scene view is ready and controls can be used.
  var _ready = false;

  // The overview sublayer. This contains a simplified, exterior-only model of
  // the building.
  late final BuildingSublayer _overviewSublayer;

  // The full model sublayer. This contains the fully detailed model of the
  // building including all exterior and interior features.
  late final BuildingSublayer _fullModelSublayer;

  // Flag indicating if the app is displaying the full model or overview sublayer.
  var _showFullModel = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        top: false,
        left: false,
        right: false,
        child: Stack(
          children: [
            Column(
              children: [
                Expanded(
                  // Add a local scene view to the widget tree and set the controller.
                  child: ArcGISLocalSceneView(
                    controllerProvider: () => _localSceneViewController,
                    onLocalSceneViewReady: onLocalSceneViewReady,
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    // Button to toggle overview or full model sublayers.
                    ElevatedButton(
                      onPressed: toggleModelView,
                      child: Text(_showFullModel ? 'Overview' : 'Full Model'),
                    ),
                  ],
                ),
              ],
            ),
            // Display a progress indicator and prevent interaction until state is ready.
            LoadingIndicator(visible: !_ready),
          ],
        ),
      ),
    );
  }

  Future<void> onLocalSceneViewReady() async {
    // Initialize the Scene.
    final scene = _initializeScene();

    // Initialize the BuildingSceneLayer.
    final buildingSceneLayer = await _initializeBuildingSceneLayer();

    // Add the BuildingSceneLayer to the Scene.
    scene.operationalLayers.add(buildingSceneLayer);

    // Add the Scene to the LocalSceneViewController.
    _localSceneViewController.arcGISScene = scene;

    // Set an initial viewpoint camera.
    final viewpointCamera = Camera.withLocation(
      location: ArcGISPoint(
        x: -13045109,
        y: 4036614,
        z: 511,
        spatialReference: SpatialReference.webMercator,
      ),
      heading: 343,
      pitch: 64,
      roll: 0,
    );
    _localSceneViewController.setViewpointCamera(viewpointCamera);

    // Set the ready state variable to true to enable the sample UI.
    setState(() => _ready = true);
  }

  ArcGISScene _initializeScene() {
    // Create a Scene with a topographic basemap style.
    final scene = ArcGISScene.withViewingModeAndBasemapStyle(
      viewingMode: SceneViewingMode.local,
      basemapStyle: BasemapStyle.arcGISTopographic,
    );

    // Add an ElevationSource to the Scene.
    final elevationSource = ArcGISTiledElevationSource.withUri(
      Uri.parse(
        'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
      ),
    );
    scene.baseSurface.elevationSources.add(elevationSource);

    return scene;
  }

  Future<BuildingSceneLayer> _initializeBuildingSceneLayer() async {
    // Load the BuildingSceneLayer.
    final buildingSceneLayer = BuildingSceneLayer.withUri(
      Uri.parse(
        'https://www.arcgis.com/home/item.html?id=669f6279c579486eb4a0acc7eb59d7ca',
      ),
    );
    await buildingSceneLayer.load();

    // Extract the overview and full model sublayers.
    _overviewSublayer = buildingSceneLayer.sublayers.firstWhere(
      (sublayer) => sublayer.modelName == 'Overview',
    );
    _fullModelSublayer = buildingSceneLayer.sublayers.firstWhere(
      (sublayer) => sublayer.modelName == 'FullModel',
    );

    return buildingSceneLayer;
  }

  void toggleModelView() {
    // Toggle the visibilities for the sublayers.
    _overviewSublayer.isVisible = _showFullModel;
    _fullModelSublayer.isVisible = !_showFullModel;

    // Set the state for the new full model visibility.
    setState(() => _showFullModel = !_showFullModel);
  }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.