简体   繁体   English

谷歌 ARCore Sceneform 如何检测射线击中 ar object

[英]Google ARCore Sceneform How to detect ray hit to ar object

I am new to Google AR core and Sceneform.我是 Google AR 核心和 Sceneform 的新手。 I want to develop a basic fps game on Android Studio, when user touches anywhere on the screen AR object will be created and if button is pushed, a ray will be shot from the center of the screen and if the ray hits to any created AR object, the score will increase.我想在 Android Studio 上开发一个基本的 fps 游戏,当用户触摸屏幕上的任何位置时,将创建 AR object,如果按下按钮,将从屏幕中心射出一条光线,如果光线击中任何创建的 AR object,分数会增加。 The code is below, but i cannot continue more.代码在下面,但我无法继续。 How can i do?我能怎么做?

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

    private ArFragment arFragment;
    private ModelRenderable mRenderable;
    private ImageButton imageButton;
    private TextView scoreText;
    private int score=0;
    private Set<Vector3> position = new HashSet<Vector3>();


   // Set<Vector3> obj_set = new HashSet<Vector3>();

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

        if (!checkIsSupportedDeviceOrFinish(this)) {
            return;
        }
        setContentView(R.layout.activity_main);

        arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
        imageButton = (ImageButton) findViewById(R.id.imageButton);
        scoreText = (TextView) findViewById(R.id.scoreText);


        setUpModel();
        setUpPlane();

        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Camera camera = arFragment.getArSceneView().getScene().getCamera();
                    Ray ray = new Ray(camera.getWorldPosition(),camera.getForward());

                    HitTestResult result = arFragment.getArSceneView().getScene().hitTest(ray);
                    if (result.getNode() != null && result.getDistance() < 0) {
                        // Hit something
                        //doSomething(result.getNode());
                        Log.e(TAG,"RAYCASTING ERROR");
                    }else{
                        Iterator value = position.iterator();
                        while(value.hasNext()){
                            if(position.equals(result.getPoint())){
                                Toast.makeText(getApplicationContext(),"HIT WAS DETECTED",Toast.LENGTH_SHORT).show();
                                score = score + 5;
                                scoreText.setText("SCORE: " + score + "");
                                Log.e(TAG,"HEY THERE");
                            }
                            else{
                                Log.e(TAG,"NOOOOOOO");
                            }
                        }
                    }

                } catch (Exception e) {
                    Log.e(TAG, "ERROR ON BUTTON");
                }
            }
        });

    }

    private void setUpModel() { //Load the model
        WeakReference<MainActivity> weakActivity = new WeakReference<>(this);

        ModelRenderable.builder()
                .setSource(this, R.raw.model)
                .setIsFilamentGltf(true)
                .build()
                .thenAccept(modelRenderable -> {
                    MainActivity activity = weakActivity.get();
                    if (activity != null) {
                        mRenderable = modelRenderable;
                    }
                })
                .exceptionally(throwable -> {
                    Toast.makeText(MainActivity.this, "Model can not be loaded!", Toast.LENGTH_SHORT).show();
                    return null;
                });
    }

    private void setUpPlane() {//Attach the scene to the node
        arFragment.setOnTapArPlaneListener(new BaseArFragment.OnTapArPlaneListener() {
            @Override
            public void onTapPlane(HitResult hitResult, Plane plane, MotionEvent motionEvent) {

                // Creates the anchor
                Anchor anchor = hitResult.createAnchor();
                AnchorNode anchorNode = new AnchorNode(anchor);
                anchorNode.setParent(arFragment.getArSceneView().getScene());
                createModel(anchorNode);
            }
        });
    }
    private void createModel(AnchorNode anchorNode) {// Create the transformable model and add it to the anchor
        TransformableNode node = new TransformableNode(arFragment.getTransformationSystem());
        node.setParent(anchorNode);
        node.setRenderable(mRenderable);
        node.select();

        position.add(anchorNode.getWorldPosition());

    }

    public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) {
        if (Build.VERSION.SDK_INT < Build.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;
    }
}

I'm not sure if I fully understood what you want to achieve but if you want to increase score when user points towards the object and presses button then you could check just that the result,= null and then do your action?我不确定我是否完全理解您想要实现的目标,但是如果您想在用户指向 object 并按下按钮时提高分数,那么您可以检查结果,= null 然后执行您的操作? why do you have the hit detection logic in the else part: So you could have:为什么你在 else 部分有命中检测逻辑:所以你可以有:

...
    HitTestResult result = arFragment.getArSceneView().getScene().hitTest(ray);
    if (result.getNode() != null) {
        // Hit something
         Toast.makeText(getApplicationContext(),"HIT WAS DETECTED",Toast.LENGTH_SHORT).show();
         score = score + 5;
         scoreText.setText("SCORE: " + score + "");                  
    }
...

This will of course keep the score increasing as long as the user points towards the object.只要用户指向 object,这当然会使分数不断增加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 ARCore 和 Sceneform 中翻译对象? - How to translate object in ARCore and Sceneform? 如何用Sceneform,ARCore绘制多边形? - How to draw a polygon with Sceneform, ARCore? 如何禁用 ARcore Sceneform Lighting? - How Disable ARcore Sceneform Lighting? 如何在 Android 上的 Sceneform/ARCore 中处理 model 缩放? - How to handle model scaling in Sceneform/ARCore on Android? 尝试在 null object 参考上调用虚拟方法 'void com.google.ar.sceneform.ux.ArFragment.setOnTapArPlaneListener - Attempt to invoke virtual method 'void com.google.ar.sceneform.ux.ArFragment.setOnTapArPlaneListener on a null object reference NullPointer:尝试在空对象引用上调用虚拟方法“com.google.ar.core.Session com.google.ar.sceneform.ArSceneView.getSession()” - NullPointer: Attempt to invoke virtual method 'com.google.ar.core.Session com.google.ar.sceneform.ArSceneView.getSession()' on a null object reference 膨胀 class com.google.ar.sceneform.ArSceneView 时出错 - Error inflating class com.google.ar.sceneform.ArSceneView 如何在 ARCore Sceneform 中为节点创建动画(更改缩放、旋转或位置)? - How to create Animation (changing Scaling, Rotation or Position) for a Node in ARCore Sceneform? 如何在 ARCore 中调整对象的大小? - How I resize an object in ARCore? 如何在ARCore中序列化会话对象? - How to serialize session object in ARCore?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM