@Override
  protected void loadContents() {
    try {
      // Getting a file path for tracking configuration XML file
      final String trackingConfigFile =
          AssetsManager.getAssetPath(
              getApplicationContext(),
              "TutorialStereoRendering/Assets/TrackingData_MarkerlessFast.xml");

      // Assigning tracking configuration
      boolean result = metaioSDK.setTrackingConfiguration(trackingConfigFile);
      MetaioDebug.log("Tracking data loaded: " + result);

      // Getting a file path for a 3D geometry
      final String filepath =
          AssetsManager.getAssetPath(
              getApplicationContext(), "TutorialStereoRendering/Assets/metaioman.md2");
      if (filepath != null) {
        // Loading 3D geometry
        IGeometry geometry = metaioSDK.createGeometry(filepath);
        if (geometry != null) {
          // Set geometry properties
          geometry.setScale(2f);
        } else MetaioDebug.log(Log.ERROR, "Error loading the geometry: " + filepath);
      }

      // Adjust hand-eye calibration (i.e. difference in view of camera vs. left/right eye).
      // These are contrived example values. Real values should be gathered by an exact
      // calibration. Note that for typical scenarios, e.g. AR/VR glasses where the camera has
      // a translation to left/right eye, the camera image is still rendered as for the mono
      // case (it is not transformed by the hand-eye calibration to look correct). Therefore
      // on glasses, see-through mode should be enabled (see above).
      // Note that setStereoRendering automatically sets an initial hand-eye calibration for
      // known devices, so if you want to override it, you should instead call
      // setHandEyeCalibration *after* setStereoRendering(true)!
      metaioSDK.setHandEyeCalibration(
          new Vector3d(70f, 0f, 0f),
          new Rotation(0f, -18f * (float) Math.PI / 180f, 0f),
          ECAMERA_TYPE.ECT_RENDERING_LEFT);
      metaioSDK.setHandEyeCalibration(
          new Vector3d(10f, 0f, 0f),
          new Rotation(0f, 7f * (float) Math.PI / 180f, 0f),
          ECAMERA_TYPE.ECT_RENDERING_RIGHT);

      // Enable stereo rendering
      metaioSDK.setStereoRendering(true);

      // Enable see through mode (e.g. on glasses)
      metaioSDK.setSeeThrough(true);
      metaioSDK.setSeeThroughColor(0, 0, 0, 255);
    } catch (Exception e) {
      MetaioDebug.printStackTrace(Log.ERROR, e);
    }
  }
  @Override
  protected void loadContents() {
    try {
      // Getting a file path for tracking configuration XML file
      String trackingConfigFile = AssetsManager.getAssetPath("TrackingData_MarkerlessFast.xml");

      // Assigning tracking configuration
      boolean result = metaioSDK.setTrackingConfiguration(trackingConfigFile);
      MetaioDebug.log("Tracking data loaded: " + result);

      // Getting a file path for a 3D geometry
      String robotModel = AssetsManager.getAssetPath("RB-BumbleBee.obj");
      if (robotModel != null) {
        // Loading 3D geometry
        model = metaioSDK.createGeometry(robotModel);
        if (model != null) {
          // Set geometry properties
          Vector3d scale = new Vector3d(0.3f, 0.3f, 0.3f);
          Vector3d translation = new Vector3d(-300f, -200f, 0f);
          Rotation rotation = new Rotation(0f, 0f, -(float) Math.PI / 2f);

          model.setRotation(rotation);
          model.setScale(scale);
          model.setTranslation(translation);

          model.setName("RB-BumbleBee");

          mGestureHandler.addObject(model, 1);
        } else {
          MetaioDebug.log(Log.ERROR, "Error loading geometry: " + robotModel);
        }
      }

      String extra = AssetsManager.getAssetPath("metaioman_target.png");
      if (extra != null) {
        imageModel = metaioSDK.createGeometryFromImage(extra, false, true);
        if (imageModel != null) {
          Vector3d v = new Vector3d(0f, 0f, 0f);
          imageModel.setTranslation(v);
          mGestureHandler.addObject(imageModel, 2);
        } else {
          MetaioDebug.log(Log.ERROR, "Error loading geometry: " + imageModel);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  @Override
  protected void loadContents() {
    try {
      final File trackingConfigFile =
          AssetsManager.getAssetPathAsFile(
              getApplicationContext(),
              "TutorialCustomShading/Assets/TrackingData_MarkerlessFast.xml");

      final boolean result = metaioSDK.setTrackingConfiguration(trackingConfigFile);
      MetaioDebug.log("Tracking configuration loaded: " + result);

      final File modelPath =
          AssetsManager.getAssetPathAsFile(
              getApplicationContext(), "TutorialCustomShading/Assets/metaioman.md2");
      if (modelPath != null) {
        mModel = metaioSDK.createGeometry(modelPath);
        if (mModel != null) {
          MetaioDebug.log("Loaded geometry " + modelPath);

          mModel.startAnimation("idle", true);

          // Make him look away from the pattern
          mModel.setScale(2);
          mModel.setRotation(new Rotation((float) (-Math.PI / 2.0), 0, 0));
          mModel.setTranslation(new Vector3d(0, -100, 50));
        } else MetaioDebug.log(Log.ERROR, "Error loading geometry: " + modelPath);
      } else MetaioDebug.log(Log.ERROR, "Model not found");

      final File shaderMaterialsFile =
          AssetsManager.getAssetPathAsFile(
              getApplicationContext(), "TutorialCustomShading/Assets/shader_materials.xml");
      if (shaderMaterialsFile == null || !metaioSDK.loadShaderMaterials(shaderMaterialsFile)) {
        MetaioDebug.log(Log.ERROR, "Failed to load shader material");

        if (mModel != null) mModel.setVisible(false);
      } else {
        if (mModel != null) mModel.setShaderMaterial("tutorial_customshading");
      }

      if (mModel != null)
        mModel.setShaderMaterialOnSetConstantsCallback(
            new IShaderMaterialOnSetConstantsCallback() {
              @Override
              public void onSetShaderMaterialConstants(
                  String shaderMaterialName,
                  SWIGTYPE_p_void extra,
                  IShaderMaterialSetConstantsService constantsService) {
                // We just pass the positive sinus (range [0;1]) of absolute time in seconds so that
                // we can
                // use it to fade our effect in and out.

                final float time[] =
                    new float[] {
                      0.5f * (1.0f + (float) Math.sin(System.currentTimeMillis() / 1000.0))
                    };
                constantsService.setShaderUniformF("myValue", time, 1);
              }
            });
    } catch (Exception e) {
      e.printStackTrace();
      MetaioDebug.log(Log.ERROR, "loadContents failed, see stack trace");
    }
  }