The RROrbitViewerLayout is a great way of adding an interactive visualization to your application. The user can twist & turn the object to see it from all angles and zoom in to inspect details. The layout works with any type of RRRenderable and automatically adjusts the camera so that the objects is fully visible. A common use case for this is to add it to an existing shopping application by providing the 3D model in addtion to images an a product detail page. The following snippet shows how its done.

self.orbitLayout = RROrbitViewerLayout.init()
self.renderView.layout = self.orbitLayout

let garmentPath = Bundle.main.path(forResource: "accessory_bag_black", ofType: "gm3d")!
let garment = RRGarment3D.init()
try! garment.load(fromFile: garmentPath, largeObjectDataProvider: nil)

// Loading the preview in the current async queue
let renderable = RRGarment3DRenderable.init(garment3D: garment)
self.orbitLayout.renderable = renderable
SWIFT

Asynchronous Content Loading

Loading assets like garments or avatars takes some time and therefore should not be done on the main thread. It’s also a good practice to have different versions of the asset like a low-resolution and a high-resolution one. This allows to show something to the user quickly while the detailed, high-resolution asset is still loading.

fileprivate func loadRenderableAsync() {

    DispatchQueue.global(qos: .userInitiated).async {
      
      let previewPath = Bundle.main.path(forResource: "accessory_bag_black_preview", ofType: "gm3d")!
      let previewModel = RRGarment3D.init()
      try! previewModel.load(fromFile: previewPath, largeObjectDataProvider: nil)
      
      // Loading the preview in the current async queue
      let previewRenderable = RRGarment3DRenderable.init(garment3D: previewModel)
      
      DispatchQueue.main.sync {
        // Updating the preview renderable in the main queue
        self.orbitLayout.renderable = previewRenderable
      }

      // Loading the full size model in the current async queue
      let garmentPath = Bundle.main.path(forResource: "accessory_bag_black", ofType: "gm3d")!
      let garment = RRGarment3D.init()
      try! garment.load(fromFile: garmentPath, largeObjectDataProvider: nil)

      // Loading the preview in the current async queue
      let fullResRenderable = RRGarment3DRenderable.init(garment3D: garment)

      DispatchQueue.main.sync {
        // Updating the full size renderable in the main queue and hiding the activity indicator
        self.orbitLayout.renderable = fullResRenderable
      }
    }
  }
SWIFT