как сгруппировать несколько трехмерных объектов как один, используя AR ядро - PullRequest
3 голосов
/ 16 января 2020

здесь я показываю несколько 3d-объектов в сцене (проверьте ниже pi c) enter image description here

и здесь у меня есть 3 объекта 3d-модели, и теперь возможно ли сгруппировать объекты 3d модели напр. если я переместлю один 3d-объект, то другие 2-е 3d-объекты также должны быть перемещены. Возможно ли это сделать без использования якорей «единство и облако»

ниже - мой код

package com.google.ar.sceneform.samples.hellosceneform;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.Toast;
import com.google.ar.core.Anchor;

import com.google.ar.core.HitResult;
import com.google.ar.core.Plane;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.ux.ArFragment;
import com.google.ar.sceneform.ux.TransformableNode;


public class HelloSceneformActivity extends AppCompatActivity {
  private static final String TAG = HelloSceneformActivity.class.getSimpleName();
  private static final double MIN_OPENGL_VERSION = 3.0;

  private ArFragment arFragment;
  private ModelRenderable andyRenderable;

  @Override
  @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"})

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!checkIsSupportedDeviceOrFinish(this)) {
      return;
    }

    setContentView(R.layout.activity_ux);
    arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);

    // When you build a Renderable, Sceneform loads its resources in the background while returning
    // a CompletableFuture. Call thenAccept(), handle(), or check isDone() before calling get().
    ModelRenderable.builder()
        .setSource(this, R.raw.andy)
        .build()
        .thenAccept(renderable -> andyRenderable = renderable)
        .exceptionally(
            throwable -> {
              Toast toast =
                  Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
              toast.setGravity(Gravity.CENTER, 0, 0);
              toast.show();
              return null;
            });

    arFragment.setOnTapArPlaneListener(
        (HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {
          if (andyRenderable == null) {
            return;
          }

          // Create the Anchor.
          Anchor anchor = hitResult.createAnchor();
          AnchorNode anchorNode = new AnchorNode(anchor);
          anchorNode.setParent(arFragment.getArSceneView().getScene());

          // Create the transformable andy and add it to the anchor.
          TransformableNode andy = new TransformableNode(arFragment.getTransformationSystem());
          andy.setParent(anchorNode);
          andy.setRenderable(andyRenderable);
          andy.select();
        });
  }


  public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) {
    if (Build.VERSION.SDK_INT < VERSION_CODES.N) {
      Log.e(TAG, "Sceneform requires Android N or later");
      Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show();
      activity.finish();
      return false;
    }
    String openGlVersionString =
        ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))
            .getDeviceConfigurationInfo()
            .getGlEsVersion();
    if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) {
      Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later");
      Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG)
          .show();
      activity.finish();
      return false;
    }
    return true;
  }
}

Ответы [ 3 ]

1 голос
/ 21 января 2020

Вы можете сгруппировать трехмерные объекты, используя метод .setParent(). Когда объект трансформируется (перемещается, поворачивается или масштабируется), дочерние объекты также трансформируются.

Образец Солнечной системы демонстрирует это в createSolarSystem(). Планеты сделаны детьми Солнца, а Луна - дочерними элементами узла Земли.

Затем вы можете расположить объект относительно родителя, используя setLocalPosition(). Например, позиционирование пл anet в солнечной активности :

Planet planet =
    new Planet(
        this, name, planetScale, orbitDegreesPerSecond, axisTilt, renderable, solarSettings);
planet.setParent(orbit);
planet.setLocalPosition(new Vector3(auFromParent * AU_TO_METERS, 0.0f, 0.0f));
1 голос
/ 24 января 2020

Вы можете сделать это, получив текущую позицию всех узлов TransformableNode.

, а затем назначить новое значение вектора для всех ваших узлов, например node1.setLocalPosition (localPosition);

    private void modleMovement(TransformableNode node, String moveMent) {
            Vector3 currentPosition1 = new Vector3();
            Vector3 currentPosition2 = new Vector3();
            Vector3 currentPosition3 = new Vector3();
            Vector3 move = new Vector3();

            currentPosition1 =Objects.requireNonNull( node1.getLocalPosition());
            currentPosition2 =Objects.requireNonNull( node2.getLocalPosition());
            currentPosition3 =Objects.requireNonNull( node3.getLocalPosition());

            if (moveMent.equals("down")) {
                move.set(currentPosition.x, (float) (currentPosition.y - 0.1), currentPosition.z);
                localPosition = move;
            }

            if (moveMent.equals("up")) {
                move.set(currentPosition.x, (float) (currentPosition.y + 0.1), currentPosition.z);
                localPosition = move;
            }

     node1.setLocalPosition(localPosition);
    }
1 голос
/ 21 января 2020

Вы можете группировать узлы самостоятельно и просто перемещать каждый узел в группе, когда вы перемещаете один, применяя одно и то же преобразование к каждому.

В терминах высокого уровня - создайте группу, или массив, или несколько своего рода коллекция для ваших узлов, все, что работает для вашего приложения.

Затем, когда вы хотите переместить группу, вы можете l oop через каждый узел и для каждого применить одно и то же преобразование - например, в приведенном ниже примере все будут иметь перевод (-0.05f, 0 , 0) apply:

        //Looping over each node in your group
        {
             //For each node, get the current Pose and transform it then set a new anchor at the new pose
             Session session = arFragment.getArSceneView().getSession();
             Anchor nextAnchor = [Get the next anchor node in your array or group]
             Pose oldPose = nextAnchor.getPose();
             Pose newPose = oldPose.compose(Pose.makeTranslation(-0.05f,0,0));
             movedAnchor = moveRenderable(currentSelectedAnchorNode, newPose);
             [Update your array or collection or group with this 'new' movedAnchor]
        }

Чтобы фактически переместить отдельные узлы, можно использовать код ниже. Это фактически удаляет узел в текущей позиции и воссоздает новый узел в целевой позиции:

private AnchorNode moveRenderable(AnchorNode anchorNodeToMove, Pose newPoseToMoveTo) {
        //Move a renderable to a new pose
        if (anchorNodeToMove != null) {
            arFragment.getArSceneView().getScene().removeChild(anchorNodeToMove);
        } else {
            Log.d(TAG,"moveRenderable - anchorNodeToMove was null");
            return null;
        }
        Frame frame = arFragment.getArSceneView().getArFrame();
        Session session = arFragment.getArSceneView().getSession();
        Anchor markAnchor = session.createAnchor(newPoseToMoveTo.extractTranslation());
        AnchorNode newAnchorNode = new AnchorNode(markAnchor);
        newAnchorNode.setRenderable(andyRenderable);
        newAnchorNode.setParent(arFragment.getArSceneView().getScene());

        return newAnchorNode;
    }
...