ARCore 使用 SceneForm 框架 —— 三维空间中,通过三个点绘制平面(Plane)

两个点确定一条直线,三个点确定一个平面,相信大家看了 SceneForm 的 API 会发现,绘制直线的比较好处理,凭空添加平面就很少见了,这篇文章就是基于这个需求做的

代码逻辑其实很简单,使用 RenderableDefinition.builder 自定义模型形状,arFragment 是 CleanArFragment 类型的,CleanArFragment 源码在《ARCore 使用 SceneForm 框架 —— 三维空间中不基于 Plane 加载 3D 模型》已经贴出,看看代码

    /**
     * 绘制三角形平面
     * context: 上下文,用于获取纹理资源
     * allSetPoint: 顶点集合
     * arFragment: 用于渲染的 ArFragment
     */
    fun buildPolygon(context : Context, allSetPoint : MutableList<Vector3>, arFragment : CleanArFragment) {
        var anchorsList = ArrayList<AnchorNode>()
        // 设置三角形各个顶点的位置
        for (j in 0 .. (allSetPoint.size - 1)) {
            val anchorNode = AnchorNode()
            anchorNode.worldPosition = allSetPoint.get(j)
            anchorNode.setParent(arFragment!!.arSceneView.scene)
            anchorsList.add(anchorNode)
        }

        // 绘制三角形模型,强制限制三个顶点
        if (anchorsList.size == 3) {
            Texture.builder()
                .setSource(context, R.drawable.final_point) //  纹理资源
                .build()
                .thenAccept { texture ->
                    MaterialFactory.makeOpaqueWithTexture(context, texture)
                        .thenAccept { material ->
                            // 将生成的三角形模型添加到场景中
                            val node = Node()
                            val triangle = makeTriangleWithAnchors(anchorsList, material)
                            if (triangle != null) {
                                node.setParent(arFragment!!.arSceneView.scene)
                                node.renderable = triangle
                            }
                        }
                }
        }
    }

    // 构建三角形平面
    private fun makeTriangleWithAnchors(anchorNodes : List<AnchorNode>, material : Material) : ModelRenderable {

        var p0 = anchorNodes.get(0).getLocalPosition()
        var p1 = anchorNodes.get(1).getLocalPosition()
        var p2 = anchorNodes.get(2).getLocalPosition()
        var up = Vector3.up()
        var uvTop = Vertex.UvCoordinate(0.5f, 1.0f)
        var uvBotLeft = Vertex.UvCoordinate(0.0f, 0.0f)
        var uvBotRight = Vertex.UvCoordinate(1.0f, 0.0f)
        var vertices = ArrayList (
            Arrays.asList(
                Vertex.builder().setPosition(p0).setNormal(up).setUvCoordinate(uvTop).build(),
                Vertex.builder().setPosition(p1).setNormal(up).setUvCoordinate(uvBotRight).build(),
                Vertex.builder().setPosition(p2).setNormal(up).setUvCoordinate(uvBotLeft).build()
            ))

        var triangleIndices : MutableList<Int> = ArrayList(6);
        triangleIndices.add(0)
        triangleIndices.add(2)
        triangleIndices.add(1)
        triangleIndices.add(0)
        triangleIndices.add(1)
        triangleIndices.add(2)

        // 通过 RenderableDefinition.builder 自定义模型形状
        var submesh = RenderableDefinition.Submesh.builder()
            .setTriangleIndices(triangleIndices)
            .setMaterial(material)
            .build()
        var renderableDefinition = RenderableDefinition.builder()
            .setVertices(vertices)
            .setSubmeshes(Arrays.asList(submesh))
            .build()
        var future = ModelRenderable.builder()
            .setSource(renderableDefinition)
            .build()

        var result : ModelRenderable
        try {
            result = future.get() as ModelRenderable
        } catch ( e : Exception ) {
            throw Exception("creating model error. ", e);
        }
        return result
    }

效果图如下,为了证明是 3D 效果,取了多个角度的效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了23 篇原创文章 · 获赞 22 · 访问量 3885

猜你喜欢

转载自blog.csdn.net/qq_19154605/article/details/103474566