当前位置: 首页 > 知识库问答 >
问题:

在场景窗体中拍照时隐藏平面渲染器

刘向阳
2023-03-14

我添加了一个基于谷歌(https://codelabs.developers.google.com/codelabs/sceneform-intro/index.html?index=../..index#15)Codelabs教程的功能,允许用户拍摄添加到场景中的增强现实对象的照片。代码工作正常,但是,我希望在用户拍摄的照片中隐藏PlaneRenader(当ARCore检测到表面时出现的白点)。

在“捕获照片”按钮的onClickListener中,我尝试在调用takePhoto()之前将PlaneRenderer设置为不可见。这会隐藏屏幕上的PlaneRenderer,但不会隐藏在捕获的照片中。

这是我的听众:

capturePhotoBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                arFragment.getArSceneView().getPlaneRenderer().setVisible(false);
                for (TransformableNode vNode : videoNodeList){
                    if (vNode.isSelected()){
                        vNode.getTransformationSystem().selectNode(null);
                    }
                }
                takePhoto();
            }
        });

videoNodeList包含可转换节点的列表,用于跟踪用户添加的对象(因为用户可以向场景中添加多个对象)。由于对象是可变换节点,用户可以点击它们来调整大小/旋转,从而在选定对象下方显示一个小圆圈。因此,添加的for循环是在拍照时取消选择所有transformableNodes,以确保照片中不会出现小圆圈。

takePhoto()方法来自CodeLabs教程,如下所示:

private void takePhoto() {

        final String filename = generateFilename();
        ArSceneView view = arFragment.getArSceneView();

        // Create a bitmap the size of the scene view.
        final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
                Bitmap.Config.ARGB_8888);

        // Create a handler thread to offload the processing of the image.
        final HandlerThread handlerThread = new HandlerThread("PixelCopier");
        handlerThread.start();
        // Make the request to copy.
        PixelCopy.request(view, bitmap, (copyResult) -> {
            if (copyResult == PixelCopy.SUCCESS) {
                try {
                    File file = saveBitmapToDisk(bitmap, filename);
                    MediaScannerConnection.scanFile(this,
                            new String[] { file.toString() }, null,
                            new MediaScannerConnection.OnScanCompletedListener() {
                                public void onScanCompleted(String path, Uri uri) {
                                    Log.i("ExternalStorage", "Scanned " + path + ":");
                                    Log.i("ExternalStorage", "-> uri=" + uri);
                                }
                            });
                } catch (IOException e) {
                    Toast toast = Toast.makeText(ChromaKeyVideoActivity.this, e.toString(),
                            Toast.LENGTH_LONG);
                    toast.show();
                    return;
                }
                Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content),
                        "Photo saved", Snackbar.LENGTH_LONG);
                snackbar.setAction("Open in Photos", v -> {
                    File photoFile = new File(filename);

                    Uri photoURI = FileProvider.getUriForFile(ChromaKeyVideoActivity.this,
                            ChromaKeyVideoActivity.this.getPackageName() + ".provider",
                            photoFile);
                    Intent intent = new Intent(Intent.ACTION_VIEW, photoURI);
                    intent.setDataAndType(photoURI, "image/*");
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    startActivity(intent);

                });
                snackbar.show();
            } else {
                Toast toast = Toast.makeText(ChromaKeyVideoActivity.this,
                        "Failed to copyPixels: " + copyResult, Toast.LENGTH_LONG);
                toast.show();
            }
            handlerThread.quitSafely();
        }, new Handler(handlerThread.getLooper()));

    }

这不是我想要的,因为我想在照片中隐藏平面渲染器(即,拍摄的照片不应该有白点)

此应用程序的用户通过从菜单中选择对象并点击PlaneRenderer来添加对象,因此完全禁用PlaneRenderer是不可行的。此外,我在应用程序中还有另一个视频录制功能,通过简单地将PlaneRenderer设置为“不可见”,成功地将PlaneRenderer隐藏在录制中,因此我不确定为什么在拍摄照片时它不起作用。

任何帮助都将不胜感激!:)

共有1个答案

戚鸿福
2023-03-14

经过无数个小时终于明白了这一点。分享我的解决方案(可能不是最好的解决方案),以防将来有人面临同样的问题。

我发现,由于使用了handlerThread,每当点击按钮时,takePhoto()方法总是在PlaneRenderer设置为不可见之前发生。因此,我添加了一个短延迟,以确保发生相反的情况,即延迟takePhoto()方法一段时间,以便该方法始终在planeRenderer不可见之后发生。

以下是代码片段:

capturePhotoBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                arFragment.getArSceneView().getPlaneRenderer().setVisible(false);
                for (TransformableNode vNode : videoNodeList){
                    if (vNode.isSelected()){
                        vNode.getTransformationSystem().selectNode(null);
                    }
                }

                v.postDelayed(new Runnable() {
                    public void run() {
                        takePhoto();
                    }
                }, 80);
            }
        });

这种方法对我有效,但我相信有更好的解决方案来解决这个问题。希望这能帮助有同样问题的人,如果你知道更好的解决方案,请随时做出贡献。

 类似资料:
  • 我是新来的阿科雷和斯内福。我在arSceneView中有一个arObject,我想在场景中隐藏它(几秒钟)。我不想从场景中分离()锚点,只需将其隐藏,然后在几秒钟后再次显示。 我已尝试更改的参数。sfa文件,但它不起作用 或者我还缺少什么别的方法

  • 本节课对WebGL光照的介绍主要目的是让你对WebGL光照,以及如何在代码层面实现WebGL光照算法有个大致的轮廓认知,计算机图形学中关于光照相关算法的介绍更为详细和系统,如果有兴趣可以阅读计算机图形学的书籍。 光线照在物体上,物体反射光线就会构成一个光场,眼睛看到生活中的物体有立体感就是因为有光的存在。因此在学习物理光学在WebGL编程中如何应用, 你就要先了解基本的光学知识。 生活中你看到一个

  • 我不是Vulkan方面的专家。我想知道如何在常规场景渲染的顶部显示Vulkan帧(提交每帧记录的especif commandBuffer以绘制UI更改)。所以在本例中,我有两个renderPasses,一个用于场景,另一个用于ImGui,还有两个commandBuffers。在尝试发送这两个commandBuffers时,只显示最后一个,因为它们使用的是swapchain映像。我错过了什么?im

  • 加载页面时 <div id="root"></div> 这样的占位空节点在 js bundle 未生效前表现为白屏。网速差 js bundle 加载慢时,白屏时间增长会造成不好的体验。 节点快照可将 HTML 容器填充为用户上一次访问时对应的内容,极速展示页面内容,提升首屏加载速度。 第一步:在工程配置 build.json 中的 build-plugin-rax-pwa 添加 snapshot

  • 我得到这个错误而导入场景形式资产。我添加了 在项目级渐变文件中,此

  • 我试图让条目在聚焦时选择所有文本。我有一个自定义的渲染器,可以在Android上执行此操作,但我希望它也能在Windows 8上运行。如何在Xamarin窗体中为Windows创建自定义渲染?以下是我所拥有的: