Slide 1

Slide 1 text

SwiftͰVRMϑΝΠϧΛදࣔͯ͠Έͨ࿩ ాதୡ໵ (@tattn) #potatotips 59

Slide 2

Slide 2 text

ాத ୡ໵ / ͨͳͨͭ (@tattn) • Yahoo!৐׵Ҋ಺ • iOSΞϓϦΤϯδχΞ • Unity΋΍ͬͯ·͢ @tattn @tanakasan2525 @tattn

Slide 3

Slide 3 text

VRMͱ͸

Slide 4

Slide 4 text

VRMͱ͸ IUUQTEXBOHPHJUIVCJPWSN VR޲͚ͷਓܕ3DΞόλʔϑΥʔϚοτ
 ϙʔλϏϦςΟ͕ߴͯ͘ѻ͍΍͍͢
 ެࣜͰఏڙ͞Ε͍ͯΔͷ͸Unity࣮૷ͷΈ ɾχίχཱମ
 ɾόʔνϟϧΩϟετ
 ɾcluster
 ɾVDraw
 ɾVRoid ͳͲͰར༻͞Ε͍ͯΔ

Slide 5

Slide 5 text

SwiftͰVRMΛදࣔͰ͖Δ
 ϥΠϒϥϦΛ࡞Γ·ͨ͠

Slide 6

Slide 6 text

DEMO

Slide 7

Slide 7 text

PDF / DEMOࣦഊ༻εΫγϣ IUUQTUXJUUFSDPNUBOBLBTBOTUBUVT ಈըˠ © Kizuna AI © SSS LLC. © DWANGO Co., Ltd.

Slide 8

Slide 8 text

VTuberKit / VRMKit / VRMSceneKit VTuberKit IUUQTHJUIVCDPNUBUUO75VCFS,JU IUUQTHJUIVCDPNUBUUO73.,JU VTuberͬΆ͍͜ͱ͕Ͱ͖Δ (؆୯ʹΩϟϥΛදࣔͰ͖Δ) VRMKit VRMSceneKit VRMͷಡΈࠐΈ͕Ͱ͖Δ ಡΈࠐΜͩVRMΛSceneKitͰදࣔͰ͖Δ ґଘάϥϑ

Slide 9

Slide 9 text

࣮૷ (ϥΠϒϥϦͷ࢖͍ํ͸GitHubΛݟͯͶ)

Slide 10

Slide 10 text

VRMͷಡΈࠐΈ

Slide 11

Slide 11 text

VRM (GLTF/GLB) ͷσʔλߏ଄ IUUQTHJUIVCDPN,ISPOPT(SPVQHM5'CMPCNBTUFSTQFDJpDBUJPO3&"%.&NE magic = ϑΝΠϧܗࣜͷνΣοΫ༻
 version = GLBͷόʔδϣϯ (VRMͷ৔߹ɺ2)
 length = σʔλͷαΠζ
 Chunk = Ϟσϧσʔλ (0͸JSONɺ1͸όΠφϦ)

Slide 12

Slide 12 text

SwiftͰόΠφϦσʔλΛಡΈࠐΉ let data = try Data(contentsOf: url) let version: UInt32 = data.subdata(in: 0..<4) .withUnsafeBytes { $0.pointee } subdataͰόΠφϦσʔλΛ੾Γग़ͯ͠
 withUnsafeBytesͰద੾ͳσʔλܕͱͯ͠औΓग़͢

Slide 13

Slide 13 text

Chunk 0͸JSON

Slide 14

Slide 14 text

Chunk 0ͷJSONΛಡΈࠐΉ let endOffset = offset + Int(length) let jsonData = data.subdata(in: offset..

Slide 15

Slide 15 text

GLTFܕ public struct GLTF: Codable { let extensionsUsed: [String]? let extensionsRequired: [String]? let accessors: [Accessor]? let animations: [Animation]? let asset: Asset let buffers: [Buffer]? let bufferViews: [BufferView]? let cameras: [Camera]? let images: [Image]? let materials: [Material]? let meshes: [Mesh]? let nodes: [Node]? let samplers: [Sampler]? let _scene: Int? var scene: Int { return _scene ?? 0 } let scenes: [Scene]? let skins: [Skin]? let textures: [Texture]? let extensions: Extension? let extras: Extras? private enum CodingKeys: String, CodingKey { case extensionsUsed case extensionsRequired case accessors case animations case asset case buffers case bufferViews case cameras case images case materials case meshes case nodes case samplers case _scene = "scene" case scenes case skins case textures case extensions case extras } } εϥΠυͰ͸঺հ͕೉͍͠ͷͰ
 GitHubͰݟͯͶ IUUQTHJUIVCDPNUBUUO73.,JUCMPCNBTUFS4PVSDFT73.,JU73.(-5'TXJGU

Slide 16

Slide 16 text

࢓༷ॻΛݟͳ͕ΒCodableͳϞσϧΛ࡞Δ ࢓༷ॻ͕ΊͪΌΊͪΌ
 Θ͔Γ΍͍͢ʂ IUUQTHJUIVCDPN,ISPOPT(SPVQHM5'CMPCNBTUFSTQFDJpDBUJPO 3&"%.&NESFGFSFODFBDDFTTPS

Slide 17

Slide 17 text

VRMͷදࣔ

Slide 18

Slide 18 text

ϝογϡͷ࡞੒ (ൈਮ) let meshNode = SCNNode() for primitive in mesh.primitives { // primitive = GLTF.Mesh.Primitive let attributes: [SCNGeometrySource] = <௖఺ɾ๏ઢσʔλͷಡΈࠐΈ> let elements: [SCNGeometryElement] = <௖఺ΠϯσοΫεͷಡΈࠐΈ> let geometry = SCNGeometry(sources: attributes, elements: elements) geometry.materials = <ϚςϦΞϧͷಡΈࠐΈ> let primitiveNode = SCNNode() primitiveNode.geometry = geometry meshNode.addChildNode(primitiveNode) }

Slide 19

Slide 19 text

௖఺σʔλͷ࡞੒ (ൈਮ) let buffer = vrm.gltf.binaryBuffer let bufferView = buffer.subdata(in: byteOffset..

Slide 20

Slide 20 text

ීஈ͋·Γ࢖Θͳ͍໘ന͍Ϋϥε SCNGeometrySource = ௖఺΍๏ઢɺϘʔϯͳͲͷσʔλ SCNGeometryElement = ௖఺ΠϯσοΫε SCNMaterial / SCNMaterialProperty = ςΫενϟ΍ը૾ͳͲͷσʔλ SCNMorpher = ϞʔϑΟϯά (ද৘ͷมߋ) SCNSkinner = εΩχϯά (ϘʔϯΞχϝʔγϣϯ) CAKeyframeAnimation = ΩʔϑϨʔϜΞχϝʔγϣϯ

Slide 21

Slide 21 text

͕࣌ؒͳ͍ͷͰ
 ࠷ޙʹ

Slide 22

Slide 22 text

࠷ޙʹ QiitaʹϥΠϒϥϦͷ࢖͍ํΛॻ͖·ͨ͠ IUUQTRJJUBDPNUBUUOJUFNTDEGEBFG ͨ͘͞Μͷ͍͍ͶΛ௖͍ͨͷͰ
 ػೳ֦ுΛؤுΖ͏ͱࢥ͍·͢ IUUQTUXJUUFSDPNUBOBLBTBOTUBUVT

Slide 23

Slide 23 text

ࠓ͸UnityͷAnimationΛimportͰ͖Δ࢓૊ΈΛ࡞ͬͯ·͢ ↑͋ͱগͬ͠Ά͍ ࣦഊͯ͠δϣδϣཱͪʁʹ Mecanimͷ
 σϑΥϧτϙʔζ͸
 Ҡ২੒ޭ ˜6OJUZ5FDIOPMPHJFT+BQBO6$- Unityͷ๛෋ͳΞηοτ͕࢖͑ΔΑ͏ʹͳͬͨΒ࠷ߴͰ͢