• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

如何在Android应用程序中使用来自Google Poly的免费3D模型

如今,对提供沉浸式虚拟现实或增强现实体验的 android 应用程序有着巨大的需求。作为开发人员,您可以使用许多不同的框架来创建此类应用程序 

但是,除非您也是熟练的 3D 艺术家,否则您将如何创建将在这些应用程序中显示的 3D 对象?您准备好花几个月的时间学习如何使用blender或 Maya 等 3D 建模程序吗?如果不是,您应该考虑使用Google Poly,这是一个包含数千个 3D 资产的在线存储库,并附带知识共享许可。

您今天可以在 Poly 上找到的大多数资产都是使用简单材料的低多边形。这是因为普通的移动 GPU 还没有变得足够强大,可以实时显示具有高多边形数的 3D 对象。

在本教程中,我将向您介绍 Poly api我还将向您展示如何使用 Processing for Android 来渲染您下载的 3D 资产。

先决条件

要充分利用本教程,您需要:

  • 最新版本的Android Studio

  • 运行 Android API 级别 21 或更高级别的设备

  • 和一个Google Cloud帐户 

1.获取API Key

您向 Poly API 发出的所有 HTTP 请求都必须附有属于您的 API 密钥。要获取密钥,首先登录 Google Cloud控制台并导航到 API 仪表板。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第1张

接下来,按下Enable APIs and services 按钮,展开Other 类别,然后选择Poly API

如何在Android应用程序中使用来自Google Poly的免费3D模型  第2张

您现在可以按启用 按钮来启用 Poly API。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第3张启用 API 后,会自动为其生成一组 API 密钥。您可以打开“凭据” 选项卡来查看它们。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第4张对于本教程,您将只需要Android 密钥记下它,以便以后使用。

2.项目设置

由于 Poly 目前没有适用于 Android 平台的官方工具包,因此您必须直接使用 Poly API 的rest接口来使用它。通过使用针对 kotlin 语言优化的Fuel网络库,您可以节省大量时间和精力。 因此,在模块的build.gradle 文件中添加以下implementation 依赖项:app

implementation 'com.github.kittinunf.fuel:fuel-android:1.13.0'

为了能够显示您从 Poly 存储库下载的 3D 资产,您还需要一个渲染引擎。Processing for Android自带一个,所以将它添加为另一个依赖项。

implementation 'org.p5android:processing-core:4.0.1'

最后,不要忘记INTERNET 在项目的清单文件中请求权限。

<uses-permission android:name="android.permission.INTERNET"/>

3.上市资产

为了能够下载 Poly 资产,您必须知道其唯一 ID。通过使用支持 WebGL 的浏览器,您可以轻松确定任何资产的 ID。它就在地址栏中。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第5张但是,如果您想让您的用户在运行时动态地决定他们想要使用哪些资产,您可以使用assets.list REST 方法来确定这些资产的 ID。该方法允许您使用各种参数(例如关键字、类别和 3D 文件格式)来查找资产。

为了一个现实的例子,现在让我们尝试查找属于该animals 类别的一些资产的 ID。当然,您可以自由选择任何其他有效类别,例如 architecturefoodpeople

在编写 HTTP 请求之前,最好将 API 密钥和 Poly API 的基本 URL 声明为Activity中的常量。

companion object {
    const val key = "Abcdefghabcdefgh1234567810"
    const val baseURL = "https://poly.googleapis.com/v1"
}

使用基本 URL,您可以构建assets.list REST 方法的 URL,如下所示:

val listURL = "$baseURL/assets"

此时,您可以通过调用该httpGet() 方法并将您的 API 密钥和所需类别作为查询参数传递给它来创建有效的 HTTP GET 请求。或者,您可以使用format 查询参数来指定所需的资产格式。Poly 支持 OBJ、FBX、TILT 和其他几种流行的 3D 格式。

由于该方法异步运行并且其结果是 JSON 文档,因此您必须使用该 方法将事件处理程序附加到它。responseJSON()以下代码向您展示了如何:

listURL.httpGet(listOf(
        "category" to "animals",
        "key" to key,
        "format" to "OBJ"
)).responseJson { _, _, result ->

    // More code here
   
}

在事件处理程序中,如果您的请求成功,您将有权访问 Asset 对象列表。每个此类对象的name 字段指定其 ID。

此外,每个对象都将具有诸如 、 和 之类的字段displayNamelicense您 authorName可能会发现这些字段很有用。现在,让我们简单地打印所有对象的 name 和 displayName 。以下代码向您展示了如何:

result.fold({
    // Get assets array
    val assets = it.obj().getJSONArray("assets")

    // Loop through array
    for(i in 0 until assets.length()) {
        // Get id and displayName
        val id = assets.getJSONObject(i).getString("name")
        val displayName = 
                assets.getJSONObject(i).getString("displayName")

        // Print id and displayName
        Log.d("POLY", "(ID: $id) -- (NAME: $displayName)")
    }
}, {
    // In case of an error
    Log.e("POLY", "An error occurred")
})

如果您现在运行您的应用程序,您应该能够在 Android Studio的Logcat窗口中看到以下输出。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第6张

4.下载资产

获得资产的唯一 ID 后,您可以直接将其附加到 Poly API 的基本 URL 以创建资产 URL。

// some asset id
val assetID = "assets/3yiiERrKNQr"

// its url
val assetURL = "$baseURL/$assetID"

当您再次使用该方法向资产 URL 发出 HTTP GET 请求httpGet() 时,您将获得一个仅包含一个Asset 对象的 JSON 文档。

assetURL.httpGet(listOf("key" to key))
        .responseJson { _, _, result ->
            result.fold({
                val asset = it.obj()
        
                // More code here
        
            }, {
                Log.e("POLY", "An error occurred")
            })
        }

正如您在上面的代码中可能已经注意到的那样,此请求也必须有一个查询参数提及您的 API 密钥。

您已经Asset 在上一步中学习了如何使用对象中存在的一些字段。现在,您需要做的就是使用formats 对象中存在的数组来确定与资产关联的文件的 URL 和名称。数组中的每个项目将具有三个重要字段: 

  • formatType,它可以让您确定资产的类型

  • root,其中包含与资产关联的主文件的名称和 URL

  • resources,其中包含有关与资产关联的所有辅助文件的详细信息,例如材质和纹理

如果您使用的是 OBJ 格式,则主文件将是一个包含顶点和面数据的.obj文件,而辅助文件通常是包含有关所用材料的数据的.mtl文件。以下代码向您展示了如何确定主文件和辅助文件的 URL:

var objFileURL:String? = null
var mtlFileURL:String? = null
var mtlFileName:String? = null

val formats = asset.getJSONArray("formats")

// Loop through all formats
for(i in 0 until formats.length()) {
    val currentFormat = formats.getJSONObject(i)

    // Check if current format is OBJ
    if(currentFormat.getString("formatType") == "OBJ") {
        // Get .obj file details
        objFileURL = currentFormat.getJSONObject("root")
                                .getString("url")

        // Get the first .mtl file details
        mtlFileURL = currentFormat.getJSONArray("resources")
                        .getJSONObject(0)
                        .getString("url")

        mtlFileName = currentFormat.getJSONArray("resources")
                        .getJSONObject(0)
                        .getString("relativePath")
        break
    }
}

在上面的代码中,除了.mtl文件的 URL,我们还使用该relativePath 字段来确定其名称。这样做很重要,因为名称被硬编码到.objmtllib文件的 元素中,不应更改。

一旦你有了这两个文件的 URL,你就可以使用httpDownload() Fuel 库的方法来下载它们。以下是如何将它们下载到应用程序的私有存储目录的方法,可以使用 filesDir 属性确定其绝对路径:

// download and store obj file as asset.obj
objFileURL!!.httpDownload().destination { _, _ ->
    File(filesDir, "asset.obj")
}.response { _, _, result ->
    result.fold({}, {
        Log.e("POLY", "An error occurred")
    })
}

// download and store mtl file without
// changing its name
mtlFileURL!!.httpDownload().destination { _, _ ->
    File(filesDir, mtlFileName)
}.response { _, _, result ->
    result.fold({}, {
        Log.e("POLY", "An error occurred")
    })
}

5.展示资产

您需要一个 3D画布来绘制您下载的 Poly 资源。要创建一个,您必须扩展PApplet Processing for Android 库提供的类。但是,默认情况下,以这种方式创建的画布仅支持 2D 形状。要将其配置为也绘制 3D 形状,请覆盖该settings() 方法并将P3D 其作为参数传递给该fullScreen() 方法,这也使画布与用户的屏幕一样大。

val canvas = object : PApplet() {
    override fun settings() {
        fullScreen(PConstants.P3D)
    }

    // More code here
}

接下来,在类中创建一个新属性以将 Poly 资产表示为一个 PShape 对象。

var myPolyAsset: PShape? = null

要初始化属性,请覆盖该setup() 方法并调用该 方法,将您下载的.objloadShape()文件 的绝对路径作为参数传递给它。

override fun setup() {
    myPolyAsset = loadShape(File(filesDir, "asset.obj").absolutePath)
}

您现在可以通过覆盖该draw() 方法开始在画布上绘图。在方法内部,您需要做的第一件事是调用该background() 方法以确保您始终在空白画布上绘图。

override fun draw() {
    background(0)
        
    // More code here
}

直接绘制时,大多数 Poly 资源看起来非常小且倒置。您可以通过使用自定义相机或使用画布变换来解决此问题。为了使本教程简单直观,让我们使用画布转换。

要增加资产的大小,请使用该scale() 方法并将较大的负值传递给它。该值必须为负,以确保资产垂直翻转。或者,您可以使用该方法沿 X 和 Y 轴translate() 调整其位置。以下代码向您展示了如何:

scale(-50f)
translate(-4f,-14f)

您现在可以通过调用该shape() 方法继续绘制资产。

shape(myPolyAsset)

画布当前不是活动视图层次结构的一部分。因此,如果您现在尝试运行您的应用程序,您将无法看到该资产。要解决这个问题,首先将一个新的 FrameLayout 小部件添加到活动的布局 XML 文件中。

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/canvas_holder">
</FrameLayout>

然后,PFragment 使用画布创建一个新实例并将其指向 FrameLayout 小部件。

val fragment = PFragment(canvas)
fragment.setView(canvas_holder, this)

此时,您可以再次运行应用程序以查看资产。

如何在Android应用程序中使用来自Google Poly的免费3D模型  第7张

结论

您现在知道如何使用 Poly API 搜索和下载 3D 资产。在本教程中,您还学习了如何使用 Processing for Android 渲染和操作这些资产。

值得注意的是,Poly 上可用的许多资产都是使用 Google Blocks 创建的,这是一款可供 HTC Vive 和 Oculus Rift 用户使用的应用程序。如果您拥有这些 VR 耳机,请考虑创建并提交您自己的模型。


文章目录
  • 先决条件
  • 1.获取API Key
  • 2.项目设置
  • 3.上市资产
  • 4.下载资产
  • 5.展示资产
  • 结论