class MainActivity : AppCompatActivity() {
private lateinit var mContentViewBinding: ActivityArBinding
private var arFragment: ArFragment? = null
private var objectRenderable: ModelRenderable? = null
private var arModel: String? = null
private var mModelStateSnackBar: Snackbar? = null
private lateinit var mModelCompletableFuture: CompletableFuture<Void>
var anchorNode: AnchorNode? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arModel = "AR_MODEL_URL"
if (checkIsSupportedDeviceOrFinish(this)) {
mContentViewBinding = DataBindingUtil.setContentView(this, R.layout.activity_ar)
startInitialization()
} else {
ToastHelper.showToast(this, getString(R.string.the_ar_feature_is_not_supported_by_your_device))
this.finish()
}
}
private fun startInitialization() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
try {
arFragment = supportFragmentManager.findFragmentById(R.id.ux_fragment) as ArFragment
Toast.makeText(this@ArActivity, getString(R.string.downloading_model), Toast.LENGTH_SHORT).show()
// Init renderable
loadModel()
// Set tap listener
arFragment!!.setOnTapArPlaneListener { hitResult: HitResult, plane: Plane?, motionEvent: MotionEvent? ->
val anchor = hitResult.createAnchor()
if (anchorNode == null) {
anchorNode = AnchorNode(anchor)
anchorNode?.setParent(arFragment!!.arSceneView.scene)
createModel()
}
}
} catch (e: Exception) {
e.printStackTrace()
}
} else {
val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
requestPermissions(permissions, RC_AR)
}
}
} catch (e: java.lang.Exception) {
Log.d("TAG", e.printStackTrace().toString() + e.message.toString())
}
}
private fun createModel() {
try {
if (anchorNode != null) {
val node = TransformableNode(arFragment!!.transformationSystem)
node.scaleController.maxScale = 0.02f
node.scaleController.minScale = 0.01f
node.setParent(anchorNode)
node.renderable = objectRenderable
node.select()
mModelStateSnackBar = Snackbar.make(mContentViewBinding.arLayout, getString(R.string.model_ready), Snackbar.LENGTH_INDEFINITE).setAction(getString(R.string.dismiss)) {
mModelStateSnackBar?.dismiss()
}
}
} catch (e: Exception) {
Toast.makeText(this@ArActivity, getString(R.string.something_went_wrong), Toast.LENGTH_SHORT).show()
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
private fun loadModel() {
try {
ModelRenderable.builder()
.setSource(this,
RenderableSource.builder().setSource(
this,
Uri.parse(arModel),
RenderableSource.SourceType.GLB)/*RenderableSource.SourceType.GLTF2)*/
.setScale(0.75f)
.setRecenterMode(RenderableSource.RecenterMode.ROOT)
.build())
.setRegistryId(arModel)
.build()
.thenAccept { renderable: ModelRenderable ->
objectRenderable = renderable
Toast.makeText(this@ArActivity, getString(R.string.model_ready), Toast.LENGTH_SHORT).show()
}
.exceptionally { throwable: Throwable? ->
Log.i("Model", "cant load")
mModelStateSnackBar = Snackbar.make(mContentViewBinding.arLayout, getString(R.string.model_error), Snackbar.LENGTH_INDEFINITE).setAction(getString(R.string.try_again)) {
mModelStateSnackBar?.dismiss()
}
null
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun checkIsSupportedDeviceOrFinish(activity: Activity): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
Log.e("error", "Sceneform requires Android N or later")
return false
}
val openGlVersionString = (activity.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
.deviceConfigurationInfo
.glEsVersion
if (java.lang.Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) {
Log.e("error", "Sceneform requires OpenGL ES 3.1 later")
return false
}
return true
}
}
4 comments
Hey,
Firstly, it depends on how you have imported the 3d model.
If you are seeing only the 3D model, then most probably the animations were not added in the glb/gltf file.
To make sure that your gltf file is proper and has animations while importing, open the gltf file in text editor and then check for the tag named “animations”.
If this tag is present, then you need to check the android end code further.
Supposedly, your glb/gltf file is correct and upto the mark, then in the android code you will need to get access to animation that you want to run by calling getAnimationData Function on your ModelRenderable object.
Now you will need to create an instance of ModelAnimator and pass both animationObject and Renderable object as arguments to the constructor of ModelAnimator.
Now you need to call the start function over ModelAnimator object and it should work.
Still if you face any issue, then please feel free to reply back over here.