CariusLars / ar_flutter_plugin

Flutter Plugin for AR (Augmented Reality) - Supports ARKit on iOS and ARCore on Android devices
MIT License
318 stars 229 forks source link

Adding Node to Anchor failed #113

Closed kamami closed 2 years ago

kamami commented 2 years ago

I am making use of the example of this repository, but always get the error "Adding Node to Anchor failed":
The object appears after a couple seconds, but didAddNodeToAnchor always returns false...

Future<void> onPlaneOrPointTapped(
      List<ARHitTestResult> hitTestResults) async {
    var singleHitTestResult = hitTestResults.firstWhere(
        (hitTestResult) => hitTestResult.type == ARHitTestResultType.plane);
    var newAnchor =
        ARPlaneAnchor(transformation: singleHitTestResult.worldTransform);
    bool? didAddAnchor = await arAnchorManager.addAnchor(newAnchor);
    if (didAddAnchor!) {
      anchors.add(newAnchor);
      // Add note to anchor
      var newNode = ARNode(
          type: NodeType.webGLB,
          name: 'Amphore',
          uri:
              "https://firebasestorage.googleapis.com/v0/b/aschaffenburgerkulturevents.appspot.com/o/ar%2FAmphore.glb?alt=media&token=cfc98635-65f0-4893-90d9-0cb2441185c6",
          scale: VectorMath.Vector3(0.2, 0.2, 0.2),
          position: VectorMath.Vector3(0.0, 0.0, 0.0),
          rotation: VectorMath.Vector4(1.0, 0.0, 0.0, 0.0));
      bool? didAddNodeToAnchor =
          await arObjectManager.addNode(newNode, planeAnchor: newAnchor);

      if (didAddNodeToAnchor!) {
        nodes.add(newNode);
      } else {
        arSessionManager.onError("Adding Node to Anchor failed");
      }
    } else {
      arSessionManager.onError("Adding Anchor failed");
    }
  }
Levizzel commented 2 years ago

@kamami have the same issue since version 0.6.3 when the return of the addNode function was changed.

This problem only occurs when you are trying to add a node to an anchor.

I think they simply forgot to add the return of true when the node is added to an anchor. I checked the plugin code (Android) in AndoridArView.kt (addNode function)

modelBuilder.makeNodeFromGltf(viewContext, transformationSystem, objectManagerChannel, enablePans, enableRotation, dict_node["name"] as String, key, dict_node["transformation"] as ArrayList<Double>)
                            .thenAccept{node ->
                                val anchorName: String? = dict_anchor?.get("name") as? String
                                val anchorType: Int? = dict_anchor?.get("type") as? Int
                                if (anchorName != null && anchorType != null) {

                                     // Node is added to an anchor //

                                    val anchorNode = arSceneView.scene.findByName(anchorName) as AnchorNode?
                                    if (anchorNode != null) {
                                        anchorNode.addChild(node)

                                        // here should also be  'completableFutureSuccess.complete(true)'

                                    } else {
                                        completableFutureSuccess.complete(false)
                                    }
                                } else {      

                                    //Node is added to the world without an anchor//

                                    arSceneView.scene.addChild(node)
                                    completableFutureSuccess.complete(true)  // change from 0.6.3
                                }
                                completableFutureSuccess.complete(false)
                            }
                            .exceptionally { throwable ->
                                // Pass error to session manager (this has to be done on the main thread if this activity)
                                val mainHandler = Handler(viewContext.mainLooper)
                                val runnable = Runnable {sessionManagerChannel.invokeMethod("onError", listOf("Unable to load renderable" +  dict_node["uri"] as String)) }
                                mainHandler.post(runnable)
                                completableFutureSuccess.completeExceptionally(throwable)
                                null // return null because java expects void return (in java, void has no instance, whereas in Kotlin, this closure returns a Unit which has one instance)
                            }

I tried it for andorid by locally adding completableFutureSuccess.complete(true) where I mentioned and it worked. Can't check it for iOS but by looking at the code there is the same 'issue' in IosARView.swift.

I opened a Pull-Request for merging these changes.

Levizzel commented 2 years ago

fix is merged. The issue can be closed.