Предисловие

Универсальное описание сцены, или, для краткости, USD, - это популярный формат файлов для 3D-индустрии, в котором хранится иерархия геометрии, материалов, света, анимации, физики и звука. Формат файла USDZ без сжатия был специально разработан с учетом потребностей экосистемы iOS AR. Изначально форматы семейства Pixar USD были задуманы с учетом схем, а схемы отлично подходят для виртуальной реальности. Однако есть также результат сотрудничества Apple и Pixar, который привел к появлению для нас новой концепции - Схемы AR .

Схема AR USD - это настраиваемое расширение, позволяющее питонно или, другими словами, использовать высокоуровневый API, определить новую сцену, содержащую закрашенные модели с поведениями и соответствующими им типами якорей AR.

Конечно, вам придется писать скрипты Python в удобочитаемой версии ASCII формата USD - USDA. Перед работой со схемами AR USD убедитесь, что вы установили USDZ Tools и правильно настроили zsh resource file.

Чтобы узнать больше о концепции доллара, перейдите на pixar.com и sidefx.com.

Как создать файл USDA с нуля

Должен сказать, что на данный момент я использую macOS Monterey 12 с установленным USDPython 0.64. Чтобы создать файл .usda, запустите Терминал и выполнить следующий скрипт Python. Чтобы вызвать интерпретатор Python (REPL) в Терминале, просто напишите python и нажмите Return.

from pxr import Usd, UsdGeom
stage = Usd.Stage.CreateNew('/Users/swift/Desktop/arScene.usda')
xformPrim = UsdGeom.Xform.Define(stage, '/Transform')
spherePrim = UsdGeom.Sphere.Define(stage, '/Transform/Sphere')
stage.GetRootLayer().Save()

Мы только что создали модель многоугольной сферы. Давайте откроем новый файл USDA в приложении TextEdit. Все, что вы видите, это всего несколько строк:

#usda 1.0
def Xform "Transform" 
{
    def Sphere "Sphere" 
    { 
    }
}

Однако эти две линии способны выполнить задачу - создать примитив белой сферы. Вы можете посмотреть на эту сферу, если выберете файл arScene.usda на Desktop и нажмите пробел (ярлык, запускающий окно предварительного просмотра Quick Look).

Изменение файла USDA

Создадим куб, окрашенный в цвет серый металлик. Сначала мы должны составить металлический шейдер. Это не ракетостроение, для этого мы должны использовать diffuseColor, metallic и шероховатость параметров.

def Xform "Texturing" 
{
    def Scope "Shaders" 
    {
        def Material "Metal" 
        {
            token outputs:surface.connect </Texturing/Shaders/Metal/
SurfaceShading.outputs:surface>
            def Shader "SurfaceShading" 
            {
                uniform token info:id = "UsdPreviewSurface"
                color3f inputs:diffuseColor = (0.75, 0.75, 0.75)
                float inputs:metallic = 1.0
                float inputs:roughness = 0.2
                token outputs:surface
            }
        }
    }
}

С выпуском доллара США компания Pixar представила концепцию под названием prim. Примы похожи на сущности RealityKit в иерархическом дереве объектов, которые определяют стадию (результирующий граф сцены примитивов). Например, материал - это прим, сетка - это прим, свет - это прим и т. Д. Xform prim хранит матрицу преобразования, которую можно применить к его дочерним примерам. def - ключевое слово, определяющее новый примитив (over - ключевое слово для замены определенного примита).

Теперь мы готовы удалить сферу и построить вместо нее куб.

#usda 1.0
(
    defaultPrim = "Primitive"
    endTimeCode = 300
    startTimeCode = 1
    upAxis = "Y"
)
def Xform "Primitive" ( 
    prepend apiSchemas = ["Preliminary_AnchoringAPI"] 
)
{
    uniform token preliminary:anchoring:type = "plane"
    uniform token preliminary:planeAnchoring:alignment = "vertical"
    def Cube "SilverBox" 
    {
        # Transform and Material
        double size = 0.25
        rel material:binding = </Texturing/Shaders/Metal>
        color3f[] primvars:displayColor = [(0.5, 0.5, 0.5)]
        uniform token[] xformOpOrder = ["xformOp:translate"]
        float3 xformOp:translate = (0.0, 0.1, 0.0)
        # Basic Animation
        float xformOp:rotateY:spin.timeSamples = { 1: 0, 300: 1800 }
        uniform token[] xformOpOrder = ["xformOp:rotateY:spin"]
    }
}

Я должен дать некоторые пояснения. Например, «GoldenBox» - это имя примита, который появится в дереве сцены как / Primitive / GoldenBox. Команда Python prepend apiSchemas позволяет нам реализовать API привязки до любого 3D контент. Также мы применили анимацию вращения вокруг оси Y.

Когда мы открываем программу просмотра Quick Look, мы видим отражение на металлической поверхности анимированного куба. Эти отражения создаются встроенным HDR-изображением Pixar.

Класс Preterior_AnchoringAPI может иметь следующее содержимое.

class "Preliminary_AnchoringAPI" (
    inherits = </APISchemaBase>
    customData = {
        token apiSchemaType = "singleApply"
    }
)
{
    uniform token preliminary:anchoring:type (
        allowedTokens = ["plane", "image", "face", "none"]
    )
    uniform token preliminary:planeAnchoring:alignment (
        allowedTokens = ["horizontal", "vertical", "any"]
    )
}

Как мы видим здесь, на данный момент мы можем использовать none, plane, image или типы привязки face. Я выбрал здесь плоскость - для RealityKit этот тип привязки будет эквивалентен AnchorEntity (.plane (..)) .

Нажмите Сохранить ярлык.

Конвертация в Терминале

Заявляю - наш файл .usda готов. В течение минуты мы конвертируем его в файл .usdz. Для этого откройте приложение Терминал и выполните эту простую команду:

usdzconvert /Users/swift/Desktop/arScene.usda

Команда работает в bash и zsh.

Кодирование в Xcode

Откройте новое приложение AR раскадровку шаблон в Xcode 13.0, затем перетащите файл arScene.usdz в область навигатора (левая панель).

Затем замените код, найденный в файле ViewController.swift, на этот код:

import UIKit
import RealityKit
class ViewController: UIViewController {
    @IBOutlet var arView: ARView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let usdz = try! ModelEntity.loadAnchor(named: "arScene", 
                                                  in: nil).  
        arView.scene.addAnchor(usdz)

        // Animation
        print(usdz.availableAnimations.count)    // prints 1
       
        let animation = usdz.availableAnimations[0].repeat()
        usdz.playAnimation(animation)
    }
}

В RealityKit анимация не воспроизводится автоматически. Мы должны запустить его с помощью метода экземпляра playAnimation (_ :).

Скомпилировать!

В конце концов, было бы неплохо увидеть всю иерархию сцен нашего .usdz. Его можно распечатать в консоли Xcode.

print(usdz)

Теперь давайте убедимся, что целью является самолет.

print((usdz.children[0].anchor?.anchoring.target)!)

Это правда.

// plane(AnchoringComponent.Target.Alignment(rawValue: 2), 
         classification: AnchoringComponent.Target.Classification(
                                   rawValue: 18446744073709551615), 
          minimumBounds: SIMD2<Float>(0.0, 0.0))

Теперь приложение AR может автоматически обнаруживать и отслеживать вертикальную плоскость и прикреплять к ней наш серебряный анимированный куб.

Прохладный. У нас есть это.

Пожертвовать автору

addr1q9w70n62nu8p7f9ukfn66gzumm9d9uxwppkx7gk7vd7gy0ehfavj97gkncwm8t8l8l8x9e4adzmw2djh4y5gd9rmtewqr99zr3

На этом пока все.

Если эта публикация вам полезна, нажмите кнопку Хлопнуть и удерживайте ее. На Medium вы можете аплодировать до 50 за каждое сообщение.

Если у вас есть вопросы, вы можете связаться со мной через StackOverflow.

До встречи!