Java 如何使用AR core将多个3d对象分组为一个
在这里,我在场景中显示多个3d对象(检查下图) 这里我有3个3d模型对象,现在可以对3d模型对象进行分组了吗?例如,如果我移动一个3d对象,那么其他2个3d对象也需要移动。是否可以在不使用unity&cloud锚的情况下实现这一点 下面是我的代码Java 如何使用AR core将多个3d对象分组为一个,java,android,arcore,Java,Android,Arcore,在这里,我在场景中显示多个3d对象(检查下图) 这里我有3个3d模型对象,现在可以对3d模型对象进行分组了吗?例如,如果我移动一个3d对象,那么其他2个3d对象也需要移动。是否可以在不使用unity&cloud锚的情况下实现这一点 下面是我的代码 package com.google.ar.sceneform.samples.hellosceneform; import android.app.Activity; import android.app.ActivityManager; imp
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;
}
}
package com.google.ar.sceneform.samples.hellosceneform;
导入android.app.Activity;
导入android.app.ActivityManager;
导入android.content.Context;
导入android.os.Build;
导入android.os.Build.VERSION\u代码;
导入android.os.Bundle;
导入android.support.v7.app.AppActivity;
导入android.util.Log;
导入android.view.Gravity;
导入android.view.MotionEvent;
导入android.widget.Toast;
导入com.google.ar.core.Anchor;
导入com.google.ar.core.HitResult;
导入com.google.ar.core.Plane;
导入com.google.ar.sceneform.AnchorNode;
导入com.google.ar.sceneform.rendering.ModelRenderable;
导入com.google.ar.sceneform.ux.ArFragment;
导入com.google.ar.sceneform.ux.TransformableNode;
公共类HelloSceneformActivity扩展了AppCompatActivity{
private static final String TAG=HelloSceneformity.class.getSimpleName();
私有静态最终double MIN_OPENGL_版本=3.0;
私有ArFragment-ArFragment;
私有模型可渲染和可渲染;
@凌驾
@SuppressWarnings({“Androidapchecker”、“FutureReturnValueIgnored”})
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
如果(!checkissupportedeviceorfinish(此)){
返回;
}
setContentView(R.layout.activity_x);
arFragment=(arFragment)getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
//构建可渲染视图时,Sceneform在返回时在后台加载其资源
//一个可完成的未来。在调用get()之前,先调用accept()、handle()或check isDone()。
ModelRenderable.builder()
.setSource(这个,R.raw.andy)
.build()
.thenAccept(可渲染->可渲染=可渲染)
.例外(
可丢弃->{
吐司=
Toast.makeText(这是“无法加载andy renderable”,Toast.LENGTH\u LONG);
toast.setGravity(Gravity.CENTER,0,0);
toast.show();
返回null;
});
arFragment.setOnTapArPlaneListener(
(HitResult HitResult、平面、运动事件)->{
if(andyRenderable==null){
返回;
}
//创建锚定。
Anchor Anchor=hitResult.createAnchor();
锚点节点锚点节点=新锚点节点(锚点);
setParent(arFragment.getArSceneView().getsceneview());
//创建可转换的andy并将其添加到锚点。
TransformableNode andy=新的TransformableNode(arFragment.getTransformationSystem());
andy.setParent(anchorNode);
andy.setRenderable(andyRenderable);
andy.select();
});
}
公共静态布尔检查IsSupportedDeviceorFinish(最终活动){
if(Build.VERSION.SDK\u INT
通过对每个节点应用相同的变换,您可以自己对节点进行分组,并在移动节点时移动组中的每个节点
从高层角度讲,为节点创建一个组、数组或某种类型的集合,只要对应用程序有效
然后,当您想要移动组时,可以在每个节点之间循环,并对每个节点应用相同的转换-例如,在下面的示例中,所有节点都将应用转换(-0.05f,0,0):
//在组中的每个节点上循环
{
//对于每个节点,获取当前姿势并对其进行变换,然后在新姿势处设置新的锚定
Session Session=arFragment.getArSceneView().getSession();
Anchor nextAnchor=[获取数组或组中的下一个锚节点]
Pose-oldPose=nextAnchor.getPose();
Pose newPose=oldPose.compose(Pose.makeTranslation(-0.05f,0,0));
movedAnchor=moveRenderable(当前选定的Anchornode,新姿势);
[使用此“新”movedAnchor更新您的阵列、集合或组]
}
要实际移动各个节点,可以使用下面的代码。这实际上会删除当前位置的节点,并在目标位置重新创建新节点:
private AnchorNode moveRenderable(AnchorNode anchorNodeToMove,Pose newPoseToMoveTo){
//将可渲染对象移动到新姿势
if(anchorNodeToMove!=null){
arFragment.getArSceneView().getScene().removeChild(AnchorNodeMove);
}否则{
d(标记“moveRenderable-anchorNodeToMove为null”);
返回null;
}
Frame Frame=arFragment.getArSceneView().getArFrame();
Session Session=arFragment.getArSceneView().getSession();
Anchor-markAnchor=session.createAnchor(newPoseToMoveTo.extractTranslation());
AnchorNode newAnchorNode=新的AnchorNode(markAnchor);
newAnchorNode.setRenderable(andyRenderable);
纽瓦克
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));
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);
}