├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Documentation~ ├── FacialARRemote.html ├── FacialARRemote.html.meta ├── images.meta └── images │ ├── image1.png │ ├── image1.png.meta │ ├── image10.png │ ├── image10.png.meta │ ├── image11.png │ ├── image11.png.meta │ ├── image12.png │ ├── image12.png.meta │ ├── image2.png │ ├── image2.png.meta │ ├── image3.png │ ├── image3.png.meta │ ├── image4.png │ ├── image4.png.meta │ ├── image5.png │ ├── image5.png.meta │ ├── image6.png │ ├── image6.png.meta │ ├── image7.png │ ├── image7.png.meta │ ├── image8.png │ ├── image8.png.meta │ ├── image9.png │ └── image9.png.meta ├── Editor.meta ├── Editor ├── BlendShapeOverrideDrawer.cs ├── BlendShapeOverrideDrawer.cs.meta ├── CharacterRigControllerEditor.cs ├── CharacterRigControllerEditor.cs.meta ├── ClipBaker.cs ├── ClipBaker.cs.meta ├── NetworkStreamEditor.cs ├── NetworkStreamEditor.cs.meta ├── PlaybackStreamEditor.cs ├── PlaybackStreamEditor.cs.meta ├── StreamReaderEditor.cs ├── StreamReaderEditor.cs.meta ├── Unity.FacialARRemote.Editor.asmdef └── Unity.FacialARRemote.Editor.asmdef.meta ├── LICENSE.md ├── LICENSE.md.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── BlendShapeIndexData.cs ├── BlendShapeIndexData.cs.meta ├── BlendShapeOverride.cs ├── BlendShapeOverride.cs.meta ├── BlendShapeUtils.cs ├── BlendShapeUtils.cs.meta ├── BlendShapesController.cs ├── BlendShapesController.cs.meta ├── CharacterRigController.cs ├── CharacterRigController.cs.meta ├── Client.cs ├── Client.cs.meta ├── ClientGUI.cs ├── ClientGUI.cs.meta ├── Interfaces.meta ├── Interfaces │ ├── IStreamReader.cs │ ├── IStreamReader.cs.meta │ ├── IStreamRecorder.cs │ ├── IStreamRecorder.cs.meta │ ├── IStreamSettings.cs │ ├── IStreamSettings.cs.meta │ ├── IStreamSource.cs │ ├── IStreamSource.cs.meta │ ├── IUsesStreamReader.cs │ └── IUsesStreamReader.cs.meta ├── Mapping.cs ├── Mapping.cs.meta ├── NetworkStream.cs ├── NetworkStream.cs.meta ├── PlaybackBuffer.cs ├── PlaybackBuffer.cs.meta ├── PlaybackData.cs ├── PlaybackData.cs.meta ├── PlaybackStream.cs ├── PlaybackStream.cs.meta ├── Prefabs.meta ├── Prefabs │ ├── AR Face.prefab │ ├── AR Face.prefab.meta │ ├── Client.prefab │ ├── Client.prefab.meta │ ├── FaceLostOverlay.mat │ ├── FaceLostOverlay.mat.meta │ ├── StreamReader.prefab │ └── StreamReader.prefab.meta ├── Scenes.meta ├── Scenes │ ├── Client.unity │ ├── Client.unity.meta │ ├── Server.unity │ └── Server.unity.meta ├── Settings.meta ├── Settings │ ├── Default Stream Settings.asset │ ├── Default Stream Settings.asset.meta │ ├── Legacy Stream Settings.asset │ └── Legacy Stream Settings.asset.meta ├── Shaders.meta ├── Shaders │ ├── ARFaceShader.shader │ └── ARFaceShader.shader.meta ├── StreamReader.cs ├── StreamReader.cs.meta ├── StreamSettings.cs ├── StreamSettings.cs.meta ├── Textures.meta ├── Textures │ ├── Button.png │ ├── Button.png.meta │ ├── Button@2x.png │ ├── Button@2x.png.meta │ ├── View_Finder_Corner.png │ ├── View_Finder_Corner.png.meta │ ├── View_Finder_Corner@2x.png │ └── View_Finder_Corner@2x.png.meta ├── Unity.FacialARRemote.asmdef └── Unity.FacialARRemote.asmdef.meta ├── Samples~ ├── Sloth Example.meta └── Sloth Example │ ├── .sample.json │ ├── Materials.meta │ ├── Materials │ ├── ARKitFaceMesh.mat │ └── ARKitFaceMesh.mat.meta │ ├── Scenes.meta │ ├── Scenes │ ├── SlothBlendShapes.unity │ └── SlothBlendShapes.unity.meta │ ├── Settings.meta │ ├── Settings │ ├── PlaybackData.asset │ └── PlaybackData.asset.meta │ ├── SlothCharacter.meta │ └── SlothCharacter │ ├── Materials.meta │ ├── Materials │ ├── sloth_all_1001_AlbedoTransparency.mat │ └── sloth_all_1001_AlbedoTransparency.mat.meta │ ├── Meshs.meta │ ├── Meshs │ ├── sloth_head_blendshapes.fbx │ └── sloth_head_blendshapes.fbx.meta │ ├── Textures.meta │ ├── Textures │ ├── sloth_all_1001_AlbedoTransparency.png │ ├── sloth_all_1001_AlbedoTransparency.png.meta │ ├── sloth_all_1001_MetallicSmoothness.png │ ├── sloth_all_1001_MetallicSmoothness.png.meta │ ├── sloth_all_1001_Normal.png │ └── sloth_all_1001_Normal.png.meta │ ├── sloth_head_blendshapes.prefab │ └── sloth_head_blendshapes.prefab.meta ├── package.json └── package.json.meta /.gitattributes: -------------------------------------------------------------------------------- 1 | *.FBX filter=lfs diff=lfs merge=lfs -crlf 2 | *.a filter=lfs diff=lfs merge=lfs -crlf 3 | *.ai filter=lfs diff=lfs merge=lfs -crlf 4 | *.aif filter=lfs diff=lfs merge=lfs -crlf 5 | *.blend filter=lfs diff=lfs merge=lfs -crlf 6 | *.cubemap filter=lfs diff=lfs merge=lfs -crlf 7 | *.dll filter=lfs diff=lfs merge=lfs -crlf 8 | *.exr filter=lfs diff=lfs merge=lfs -crlf 9 | *.fbx filter=lfs diff=lfs merge=lfs -crlf 10 | *.gif filter=lfs diff=lfs merge=lfs -crlf 11 | *.jpeg filter=lfs diff=lfs merge=lfs -crlf 12 | *.jpg filter=lfs diff=lfs merge=lfs -crlf 13 | *.lxo filter=lfs diff=lfs merge=lfs -crlf 14 | *.mov filter=lfs diff=lfs merge=lfs -crlf 15 | *.mp3 filter=lfs diff=lfs merge=lfs -crlf 16 | *.mp4 filter=lfs diff=lfs merge=lfs -crlf 17 | *.obj filter=lfs diff=lfs merge=lfs -crlf 18 | *.ogg filter=lfs diff=lfs merge=lfs -crlf 19 | *.pdf filter=lfs diff=lfs merge=lfs -crlf 20 | *.png filter=lfs diff=lfs merge=lfs -crlf 21 | *.psd filter=lfs diff=lfs merge=lfs -crlf 22 | *.reason filter=lfs diff=lfs merge=lfs -crlf 23 | *.rns filter=lfs diff=lfs merge=lfs -crlf 24 | *.tga filter=lfs diff=lfs merge=lfs -crlf 25 | *.tif filter=lfs diff=lfs merge=lfs -crlf 26 | *.ttf filter=lfs diff=lfs merge=lfs -crlf 27 | *.wav filter=lfs diff=lfs merge=lfs -crlf 28 | *.zip filter=lfs diff=lfs merge=lfs -crlf 29 | *.lfs.* filter=lfs diff=lfs merge=lfs -crlf 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS 2 | *.DS_STORE 3 | 4 | [Ii]gnored 5 | [Ii]gnored.meta 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this package will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.1.0-preview] - 1212-12-12 8 | 9 | ### This is the first release of *Facial AR Remote*. 10 | ### Changed 11 | - Updated Unity version to 2019.4 12 | - Converted to package format 13 | - Updated to use AR Foundation 14 | 15 | ### Removed 16 | - BlendShapeCount field in StreamSettings 17 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d5dc2f6f654128048856e6e505fbb8c9 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/FacialARRemote.html.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eafa2c797c7bd40db945db4e864b5e53 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/images.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1db1a61ba49d806489bf2b55c5070632 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Documentation~/images/image1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7b72be51615efe444cfbeb70079d77974b005edc512f57c44c40191be005e8cc 3 | size 320 4 | -------------------------------------------------------------------------------- /Documentation~/images/image1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43c9dc462b6011245bc8a070979089fe 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image10.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0cbb6595d5c3aed1ccb8ff5ccd3261ec825acf0f5fae48f4e8aa6fe1222ae962 3 | size 49590 4 | -------------------------------------------------------------------------------- /Documentation~/images/image10.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f23852070e78bf419fb0748f0adb45d 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image11.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:758b7118ed784a7ad66f96e72a6f8ffbc9ce3de7e7f495b295cf2215f75dcba1 3 | size 22695 4 | -------------------------------------------------------------------------------- /Documentation~/images/image11.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f79c184cf250b3b4e96d21f045d58a73 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image12.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d89279d21bbce9cb531de63f2cea7dd1191bdebc8d94adf352413c76a5917214 3 | size 289 4 | -------------------------------------------------------------------------------- /Documentation~/images/image12.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ef937561e97927a41aea13585fe164f6 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:44cd028b92bb21646027bc511ad0a573bd9f699e9fe06d1de058aa9f2c5c5bda 3 | size 44872 4 | -------------------------------------------------------------------------------- /Documentation~/images/image2.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 94bf79298e15af7489412e0820f0a2bb 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image3.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:935bc0117c1427c3d86ba366bc80395e8fb8882ced5310348c34b0f331ecc12a 3 | size 285 4 | -------------------------------------------------------------------------------- /Documentation~/images/image3.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e66bc5a48e144d4c9811006cec60bc6 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image4.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eb8aec7b44ea915e483b39c9b849cd38ba8765dd985ae9a94b54cd3e95800c6d 3 | size 35139 4 | -------------------------------------------------------------------------------- /Documentation~/images/image4.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: abe3146f39b376e4cb922c9958160ac1 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image5.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8dfbdb72041e68bb937915516e5b9baf90335459e50361573bba134a3268b3b3 3 | size 22848 4 | -------------------------------------------------------------------------------- /Documentation~/images/image5.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 746de3bb54d5a65429bee555247ad698 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image6.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d55855bb8f5ce94a5181c4b9a93e027ca8fd172902a38b6308144e4a1d74327d 3 | size 16922 4 | -------------------------------------------------------------------------------- /Documentation~/images/image6.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e09c9a8a794c3a4ca5a2928b07c91d1 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image7.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dc69a5be1558195470b457657fbac6943994c87fb56f7051cf47ca61cd1b4e5f 3 | size 9874 4 | -------------------------------------------------------------------------------- /Documentation~/images/image7.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5ef172ec084a1a44bcc115a0552c0df 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image8.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2a81422833eeac4793f10f9d99c324381bade105aceb699f72aa2d4e047df0fc 3 | size 20582 4 | -------------------------------------------------------------------------------- /Documentation~/images/image8.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44da1fe6316593f4590daf6904f33f2e 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Documentation~/images/image9.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bb6a843ec09fd2e3e81c5dc3082fe2893fd78ae164e3b24a0bde0d00e89025d0 3 | size 2282 4 | -------------------------------------------------------------------------------- /Documentation~/images/image9.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c45057f3b3da4064885689845f143bbf 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16a0989f44dbe4274aeb18c4eebba515 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BlendShapeOverrideDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Unity.Labs.FacialRemote.Unity.Labs.FacialRemote 5 | { 6 | [CustomPropertyDrawer(typeof(BlendShapeOverride))] 7 | public class BlendShapeOverrideInspector : PropertyDrawer 8 | { 9 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 10 | { 11 | using (new EditorGUI.PropertyScope(position, label, property)) 12 | { 13 | // Draw label 14 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), 15 | new GUIContent(property.FindPropertyRelative("m_Name").stringValue)); 16 | 17 | var lineHeight = EditorGUIUtility.singleLineHeight; 18 | 19 | var overrideRect = new Rect(position.x, position.y, position.width, lineHeight); 20 | var smoothingRect = new Rect(position.x, position.y + lineHeight, position.width, lineHeight); 21 | var thresholdRect = new Rect(position.x, position.y + lineHeight * 2, position.width, lineHeight); 22 | var coefficientRect = new Rect(position.x, position.y + lineHeight * 3, position.width, lineHeight); 23 | var maxRect = new Rect(position.x, position.y + lineHeight * 4, position.width, lineHeight); 24 | 25 | var useOverride = property.FindPropertyRelative("m_UseOverride"); 26 | var overrideLabel = new GUIContent(useOverride.displayName); 27 | EditorGUI.PropertyField(overrideRect, useOverride, overrideLabel); 28 | 29 | var guiEnabled = GUI.enabled; 30 | 31 | if (guiEnabled) 32 | GUI.enabled = useOverride.boolValue; 33 | 34 | var blendShapeSmoothing = property.FindPropertyRelative("m_BlendShapeSmoothing"); 35 | var blendShapeSmoothingLabel = new GUIContent(blendShapeSmoothing.displayName); 36 | EditorGUI.PropertyField(smoothingRect, blendShapeSmoothing, blendShapeSmoothingLabel); 37 | 38 | var threshold = property.FindPropertyRelative("m_BlendShapeThreshold"); 39 | var thresholdLabel = new GUIContent(threshold.displayName); 40 | EditorGUI.PropertyField(thresholdRect, threshold, thresholdLabel); 41 | 42 | var coefficient = property.FindPropertyRelative("m_BlendShapeCoefficient"); 43 | var coefficientLabel = new GUIContent(coefficient.displayName); 44 | EditorGUI.PropertyField(coefficientRect, coefficient, coefficientLabel); 45 | 46 | var max = property.FindPropertyRelative("m_BlendShapeMax"); 47 | var maxLabel = new GUIContent(max.displayName); 48 | EditorGUI.PropertyField(maxRect, max, maxLabel); 49 | 50 | GUI.enabled = guiEnabled; 51 | } 52 | } 53 | 54 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 55 | { 56 | return EditorGUIUtility.singleLineHeight * 5 + 2; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Editor/BlendShapeOverrideDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1af920682a7452341b46a13cd3d9a515 3 | timeCreated: 1526497212 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Editor/CharacterRigControllerEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | [CustomEditor(typeof(CharacterRigController))] 6 | public class CharacterRigControllerEditor : Editor 7 | { 8 | SerializedProperty m_EyeSmoothing; 9 | SerializedProperty m_HeadSmoothing; 10 | SerializedProperty m_TrackingLossSmoothing; 11 | SerializedProperty m_DriveEyes; 12 | SerializedProperty m_LeftEye; 13 | SerializedProperty m_RightEye; 14 | SerializedProperty m_RightEyeNegZ; 15 | SerializedProperty m_LeftEyeNegZ; 16 | SerializedProperty m_EyeAngleRange; 17 | SerializedProperty m_EyeLookDistance; 18 | SerializedProperty m_DriveHead; 19 | SerializedProperty m_HeadBone; 20 | SerializedProperty m_HeadFollowAmount; 21 | SerializedProperty m_DriveNeck; 22 | SerializedProperty m_NeckBone; 23 | SerializedProperty m_NeckFollowAmount; 24 | 25 | bool m_EyeFoldout; 26 | bool m_HeadFoldout; 27 | bool m_NeckFoldout; 28 | 29 | void OnEnable() 30 | { 31 | m_HeadBone = serializedObject.FindProperty("m_HeadBone"); 32 | m_NeckBone = serializedObject.FindProperty("m_NeckBone"); 33 | m_LeftEye = serializedObject.FindProperty("m_LeftEye"); 34 | m_RightEye = serializedObject.FindProperty("m_RightEye"); 35 | m_TrackingLossSmoothing = serializedObject.FindProperty("m_TrackingLossSmoothing"); 36 | 37 | m_DriveEyes = serializedObject.FindProperty("m_DriveEyes"); 38 | m_RightEyeNegZ = serializedObject.FindProperty("m_RightEyeNegZ"); 39 | m_LeftEyeNegZ = serializedObject.FindProperty("m_LeftEyeNegZ"); 40 | m_EyeAngleRange = serializedObject.FindProperty("m_EyeAngleRange"); 41 | m_EyeSmoothing = serializedObject.FindProperty("m_EyeSmoothing"); 42 | m_EyeLookDistance = serializedObject.FindProperty("m_EyeLookDistance"); 43 | 44 | m_DriveHead = serializedObject.FindProperty("m_DriveHead"); 45 | m_HeadFollowAmount = serializedObject.FindProperty("m_HeadFollowAmount"); 46 | m_HeadSmoothing = serializedObject.FindProperty("m_HeadSmoothing"); 47 | 48 | m_DriveNeck = serializedObject.FindProperty("m_DriveNeck"); 49 | m_NeckFollowAmount = serializedObject.FindProperty("m_NeckFollowAmount"); 50 | } 51 | 52 | public override void OnInspectorGUI() 53 | { 54 | using (var check = new EditorGUI.ChangeCheckScope()) 55 | { 56 | EditorGUILayout.LabelField("General Settings", EditorStyles.boldLabel); 57 | EditorGUILayout.PropertyField(m_HeadBone); 58 | EditorGUILayout.PropertyField(m_NeckBone); 59 | EditorGUILayout.PropertyField(m_LeftEye); 60 | EditorGUILayout.PropertyField(m_RightEye); 61 | EditorGUILayout.PropertyField(m_TrackingLossSmoothing); 62 | 63 | m_EyeFoldout = EditorGUILayout.Foldout(m_EyeFoldout, "Eye Settings"); 64 | if (m_EyeFoldout) 65 | { 66 | EditorGUILayout.PropertyField(m_DriveEyes); 67 | EditorGUILayout.PropertyField(m_EyeLookDistance); 68 | EditorGUILayout.PropertyField(m_RightEyeNegZ); 69 | EditorGUILayout.PropertyField(m_LeftEyeNegZ); 70 | EditorGUILayout.PropertyField(m_EyeAngleRange); 71 | EditorGUILayout.PropertyField(m_EyeSmoothing); 72 | } 73 | 74 | m_HeadFoldout = EditorGUILayout.Foldout(m_HeadFoldout, "Head Settings"); 75 | if (m_HeadFoldout) 76 | { 77 | EditorGUILayout.PropertyField(m_DriveHead); 78 | EditorGUILayout.PropertyField(m_HeadFollowAmount); 79 | EditorGUILayout.PropertyField(m_HeadSmoothing); 80 | } 81 | 82 | m_NeckFoldout = EditorGUILayout.Foldout(m_NeckFoldout, "Neck Settings"); 83 | if (m_NeckFoldout) 84 | { 85 | EditorGUILayout.PropertyField(m_DriveNeck); 86 | EditorGUILayout.PropertyField(m_NeckFollowAmount); 87 | } 88 | 89 | if (check.changed) 90 | serializedObject.ApplyModifiedProperties(); 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Editor/CharacterRigControllerEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6836fc3f8425925438bc844e3d55dccb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ClipBaker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEngine; 5 | using UnityObject = UnityEngine.Object; 6 | 7 | namespace Unity.Labs.FacialRemote 8 | { 9 | public class ClipBaker 10 | { 11 | const int k_FramesPerStep = 16; 12 | const string k_BlendShapeProp = "blendShape.{0}"; 13 | const string k_RotationX = "localRotation.x"; 14 | const string k_RotationY = "localRotation.y"; 15 | const string k_RotationZ = "localRotation.z"; 16 | const string k_RotationW = "localRotation.w"; 17 | static readonly string[] k_RotParams = 18 | { 19 | k_RotationX, 20 | k_RotationY, 21 | k_RotationZ, 22 | k_RotationW 23 | }; 24 | 25 | AnimationClip m_Clip; 26 | StreamReader m_StreamReader; 27 | PlaybackStream m_PlaybackStream; 28 | CharacterRigController m_CharacterRigController; 29 | BlendShapesController m_BlendShapesController; 30 | 31 | readonly Dictionary> m_AnimationCurves = 32 | new Dictionary>(); 33 | 34 | readonly List m_AnimationClipCurveData = new List(); 35 | 36 | readonly float[] m_FrameTime = new float[1]; 37 | float m_FirstFrameTime; 38 | 39 | string m_FilePath; 40 | 41 | public int currentFrame { get; private set; } 42 | public int frameCount { get; private set; } 43 | public bool baking { get; private set; } 44 | 45 | public ClipBaker(AnimationClip clip, StreamReader streamReader, PlaybackStream playbackStream, 46 | BlendShapesController blendShapesController, CharacterRigController characterRigController, string filePath) 47 | { 48 | m_Clip = clip; 49 | m_StreamReader = streamReader; 50 | m_PlaybackStream = playbackStream; 51 | m_BlendShapesController = blendShapesController; 52 | m_CharacterRigController = characterRigController; 53 | m_FilePath = filePath; 54 | 55 | StartClipBaker(m_BlendShapesController != null 56 | ? m_BlendShapesController.transform 57 | : m_CharacterRigController.transform); 58 | } 59 | 60 | void StartClipBaker(Transform transform) 61 | { 62 | var playbackBuffer = m_PlaybackStream.activePlaybackBuffer; 63 | if (playbackBuffer == null) 64 | return; 65 | 66 | if (m_CharacterRigController == null) 67 | Debug.LogWarning("No Character Rig Controller Found! Will not be able to bake Character Bone Animations."); 68 | 69 | if (m_BlendShapesController == null) 70 | Debug.LogWarning("No Blend Shape Controller Found! Will not be able to bake Character Blend Shape Animations."); 71 | 72 | m_AnimationClipCurveData.Clear(); 73 | 74 | baking = true; 75 | 76 | if (m_BlendShapesController != null) 77 | { 78 | m_BlendShapesController.UpdateBlendShapeIndices(playbackBuffer); 79 | 80 | // Get curve data for blend shapes 81 | foreach (var skinnedMeshRenderer in m_BlendShapesController.skinnedMeshRenderers) 82 | { 83 | if (skinnedMeshRenderer == null || m_AnimationCurves.ContainsKey(skinnedMeshRenderer)) // Skip duplicates 84 | continue; 85 | 86 | var path = AnimationUtility.CalculateTransformPath(skinnedMeshRenderer.transform, transform); 87 | path = path.Replace(string.Format("{0}/", skinnedMeshRenderer.transform), ""); 88 | 89 | var mesh = skinnedMeshRenderer.sharedMesh; 90 | var count = mesh.blendShapeCount; 91 | 92 | var animationCurves = new Dictionary(); 93 | for (var i = 0; i < count; i++) 94 | { 95 | var shapeName = mesh.GetBlendShapeName(i); 96 | var prop = string.Format(k_BlendShapeProp, shapeName); 97 | var curve = new AnimationCurve(); 98 | var curveData = new AnimationClipCurveData 99 | { 100 | path = path, 101 | curve = curve, 102 | propertyName = prop, 103 | type = skinnedMeshRenderer.GetType() 104 | }; 105 | 106 | m_AnimationClipCurveData.Add(curveData); 107 | animationCurves.Add(prop, curveData); 108 | } 109 | 110 | m_AnimationCurves.Add(skinnedMeshRenderer, animationCurves); 111 | } 112 | } 113 | 114 | if (m_CharacterRigController != null) 115 | { 116 | m_CharacterRigController.UpdateBlendShapeIndices(playbackBuffer); 117 | 118 | m_CharacterRigController.SetupCharacterRigController(); 119 | 120 | // Get curve data for bone transforms 121 | var transformType = typeof(Transform); 122 | foreach (var bone in m_CharacterRigController.animatedBones) 123 | { 124 | if (bone == null || m_AnimationCurves.ContainsKey(bone)) // Skip duplicates 125 | continue; 126 | 127 | var path = AnimationUtility.CalculateTransformPath(bone, transform); 128 | var animationCurves = new Dictionary(); 129 | foreach (var prop in k_RotParams) 130 | { 131 | var curve = new AnimationCurve(); 132 | var curveData = new AnimationClipCurveData 133 | { 134 | path = path, 135 | curve = curve, 136 | propertyName = prop, 137 | type = transformType 138 | }; 139 | 140 | m_AnimationClipCurveData.Add(curveData); 141 | animationCurves.Add(prop, curveData); 142 | } 143 | 144 | m_AnimationCurves.Add(bone, animationCurves); 145 | } 146 | } 147 | 148 | currentFrame = 0; 149 | var recordStream = playbackBuffer.recordStream; 150 | frameCount = recordStream.Length / playbackBuffer.bufferSize; 151 | 152 | Buffer.BlockCopy(recordStream, playbackBuffer.FrameTimeOffset, m_FrameTime, 0, playbackBuffer.FrameTimeSize); 153 | m_FirstFrameTime = m_FrameTime[0]; 154 | } 155 | 156 | public void StopBake() 157 | { 158 | baking = false; 159 | m_CharacterRigController.ResetBonePoses(); 160 | } 161 | 162 | public void ApplyAnimationCurves() 163 | { 164 | foreach (var curveData in m_AnimationClipCurveData) 165 | { 166 | var path = curveData.path; 167 | var propertyName = curveData.propertyName; 168 | var type = curveData.type; 169 | var curve = curveData.curve; 170 | m_Clip.SetCurve(path, type, propertyName, curve); 171 | AnimationUtility.SetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(path, type, propertyName), curve); 172 | } 173 | 174 | var fileClip = AssetDatabase.LoadAssetAtPath(m_FilePath, typeof(AnimationClip)); 175 | if (fileClip == null) 176 | { 177 | AssetDatabase.CreateAsset(m_Clip, m_FilePath); 178 | } 179 | else 180 | { 181 | // This overrides the reference in the asset file 182 | // ReSharper disable once RedundantAssignment 183 | fileClip = m_Clip; 184 | AssetDatabase.SaveAssets(); 185 | AssetDatabase.ImportAsset(m_FilePath); 186 | } 187 | 188 | StopBake(); 189 | Debug.Log("End Bake"); 190 | } 191 | 192 | public void BakeClipLoop() 193 | { 194 | if (!BakeClipLoopInternal()) 195 | StopBake(); 196 | } 197 | 198 | bool BakeClipLoopInternal() 199 | { 200 | if (frameCount < 1) 201 | return false; 202 | 203 | var streamSettings = m_StreamReader.streamSource.streamSettings; 204 | var bufferSize = streamSettings.bufferSize; 205 | var frameTimeOffset = streamSettings.FrameTimeOffset; 206 | var frameTimeSize = streamSettings.FrameTimeSize; 207 | var recordStream = m_PlaybackStream.activePlaybackBuffer.recordStream; 208 | for (var i = 0; i < k_FramesPerStep && currentFrame < frameCount; i++, currentFrame++) 209 | { 210 | Buffer.BlockCopy(recordStream, currentFrame * bufferSize + frameTimeOffset, m_FrameTime, 0, frameTimeSize); 211 | 212 | // Run normal playback to record transform keyframes 213 | m_PlaybackStream.PlayBackLoop(); 214 | m_PlaybackStream.UpdateCurrentFrameBuffer(true); 215 | 216 | if (m_BlendShapesController != null) 217 | m_BlendShapesController.InterpolateBlendShapes(true); 218 | 219 | if (m_CharacterRigController != null) 220 | m_CharacterRigController.InterpolateBlendShapes(true); 221 | 222 | KeyFrame(m_FrameTime[0] - m_FirstFrameTime); 223 | } 224 | 225 | return true; 226 | } 227 | 228 | void KeyFrame(float time) 229 | { 230 | // Key blend shapes 231 | if (m_BlendShapesController != null) 232 | { 233 | foreach (var skinnedMeshRenderer in m_BlendShapesController.skinnedMeshRenderers) 234 | { 235 | Dictionary animationCurves; 236 | if (m_AnimationCurves.TryGetValue(skinnedMeshRenderer, out animationCurves)) 237 | { 238 | BlendShapeIndexData[] shapeIndices; 239 | if (m_BlendShapesController.blendShapeIndices.TryGetValue(skinnedMeshRenderer, out shapeIndices)) 240 | { 241 | var length = shapeIndices.Length; 242 | for (var i = 0; i < length; i++) 243 | { 244 | var datum = shapeIndices[i]; 245 | var index = datum.index; 246 | if (index < 0) 247 | continue; 248 | 249 | var curve = animationCurves[string.Format(k_BlendShapeProp, datum.name)].curve; 250 | curve.AddKey(time, m_BlendShapesController.blendShapesScaled[index]); 251 | } 252 | } 253 | } 254 | } 255 | } 256 | 257 | // Key bone rotation 258 | if (m_CharacterRigController) 259 | { 260 | for (var i = 0; i < m_CharacterRigController.animatedBones.Length; i++) 261 | { 262 | // Use head 263 | if (i == 0 && !m_CharacterRigController.driveHead) 264 | continue; 265 | 266 | // Use neck 267 | if (i == 1 && !m_CharacterRigController.driveNeck) 268 | continue; 269 | 270 | // Use Eyes 271 | if (i == 2 && !m_CharacterRigController.driveEyes) 272 | continue; 273 | 274 | if (i == 3 && !m_CharacterRigController.driveEyes) 275 | continue; 276 | 277 | var bone = m_CharacterRigController.animatedBones[i]; 278 | Dictionary animationCurves; 279 | if (m_AnimationCurves.TryGetValue(bone, out animationCurves)) 280 | { 281 | foreach (var datum in animationCurves) 282 | { 283 | var curveData = datum.Value; 284 | var prop = curveData.propertyName; 285 | var curve = curveData.curve; 286 | switch (prop) { 287 | case k_RotationX: 288 | curve.AddKey(time, bone.localRotation.x); 289 | break; 290 | case k_RotationY: 291 | curve.AddKey(time, bone.localRotation.y); 292 | break; 293 | case k_RotationZ: 294 | curve.AddKey(time, bone.localRotation.z); 295 | break; 296 | case k_RotationW: 297 | curve.AddKey(time, bone.localRotation.w); 298 | break; 299 | default: 300 | Debug.LogErrorFormat("Fell through on {0} : {1}", datum.Key, prop); 301 | break; 302 | } 303 | } 304 | } 305 | } 306 | } 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /Editor/ClipBaker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd15bedae52273d4d98632f22084c5f2 3 | timeCreated: 1528230228 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Editor/NetworkStreamEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | [CustomEditor(typeof(NetworkStream))] 6 | public class NetworkStreamEditor : Editor 7 | { 8 | SerializedProperty m_StreamSettings; 9 | SerializedProperty m_Port; 10 | SerializedProperty m_CatchUpThreshold; 11 | SerializedProperty m_CatchUpSize; 12 | SerializedProperty m_StreamRecorderOverride; 13 | 14 | void OnEnable() 15 | { 16 | m_StreamSettings = serializedObject.FindProperty("m_StreamSettings"); 17 | m_Port = serializedObject.FindProperty("m_Port"); 18 | m_CatchUpThreshold = serializedObject.FindProperty("m_CatchUpThreshold"); 19 | m_CatchUpSize = serializedObject.FindProperty("m_CatchUpSize"); 20 | m_StreamRecorderOverride = serializedObject.FindProperty("m_StreamRecorderOverride"); 21 | 22 | var networkStream = (NetworkStream)target; 23 | var streamReader = networkStream.gameObject.GetComponent(); 24 | if (streamReader != null) 25 | { 26 | streamReader.ConnectDependencies(); 27 | } 28 | } 29 | 30 | public override void OnInspectorGUI() 31 | { 32 | 33 | using (var check = new EditorGUI.ChangeCheckScope()) 34 | { 35 | EditorGUILayout.PropertyField(m_StreamSettings); 36 | EditorGUILayout.PropertyField(m_Port); 37 | EditorGUILayout.PropertyField(m_CatchUpThreshold); 38 | EditorGUILayout.PropertyField(m_CatchUpSize); 39 | EditorGUILayout.PropertyField(m_StreamRecorderOverride); 40 | 41 | if (check.changed) 42 | { 43 | serializedObject.ApplyModifiedProperties(); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Editor/NetworkStreamEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3f8585d5dd774a4781a335573c16718 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/PlaybackStreamEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | [CustomEditor(typeof(PlaybackStream))] 6 | public class PlaybackStreamEditor : Editor 7 | { 8 | SerializedProperty m_PlaybackData; 9 | 10 | void OnEnable() 11 | { 12 | m_PlaybackData = serializedObject.FindProperty("m_PlaybackData"); 13 | 14 | var playbackStream = (PlaybackStream)target; 15 | var streamReader = playbackStream.gameObject.GetComponent(); 16 | if (streamReader != null) 17 | { 18 | streamReader.ConnectDependencies(); 19 | } 20 | } 21 | 22 | public override void OnInspectorGUI() 23 | { 24 | 25 | using (var check = new EditorGUI.ChangeCheckScope()) 26 | { 27 | EditorGUILayout.PropertyField(m_PlaybackData); 28 | 29 | if (m_PlaybackData.objectReferenceValue == null) 30 | { 31 | EditorGUILayout.HelpBox("No Playback Data has been set. You Will be unable to Record, Playback, " + 32 | "or Bake a Stream Data!", MessageType.Warning); 33 | } 34 | 35 | if (check.changed) 36 | { 37 | serializedObject.ApplyModifiedProperties(); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Editor/PlaybackStreamEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1f1e6a2c8eba4204195357e246408304 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/StreamReaderEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a2bb5c2a97240d24eb552ba7496059ee 3 | timeCreated: 1528405512 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Editor/Unity.FacialARRemote.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Unity.FacialARRemote.Editor", 3 | "references": [ 4 | "Unity.FacialARRemote" 5 | ], 6 | "includePlatforms": [ 7 | "Editor" 8 | ], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": false, 11 | "overrideReferences": false, 12 | "precompiledReferences": [], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /Editor/Unity.FacialARRemote.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d6b001f771c74cea8542e0b1df9f610 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Facial AR Remote copyright © 2020 Unity Technologies ApS 2 | 3 | Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). 4 | 5 | Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. 6 | -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44eeb5ec5616e684289cc9675e29312f 3 | timeCreated: 1529017821 4 | licenseType: Pro 5 | DefaultImporter: 6 | externalObjects: {} 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Facial AR Remote (Preview) 2 | 3 | ## Notice 4 | **This project has been discontinued and replaced by the [Live Capture](https://docs.unity3d.com/Packages/com.unity.live-capture@latest) package and [Unity Face Capture](https://apps.apple.com/nz/app/unity-face-capture/id1544159771) app. This repository is no longer supported or maintained.** 5 | 6 | ## About 7 | 8 | Facial AR Remote is a tool that allows you to capture blendshape animations directly from a compatible iOS device to the Unity Editor. Download the [Facial AR Remote Integration Project](https://github.com/Unity-Technologies/Facial-AR-Remote-Project) if you want a Unity project with all dependencies built in. 9 | 10 | ### Experimental Status 11 | 12 | This repository is tested against the latest stable version of Unity and requires the user to build the iOS app to use as a remote. It is presented on an experimental basis - there is no formal support. 13 | 14 | ## Download 15 | Install the package through the Package Manager [using the Git URL](https://docs.unity3d.com/Manual/upm-ui-giturl.html). 16 | 17 | ## How To Use/Quick Start Guide 18 | 19 | This repository uses [Git LFS](https://git-lfs.github.com/) so make sure you have LFS installed to get all the files. Unfortunately this means that the large files are also not included in the "Download ZIP" option on GitHub, and the example head model, among other assets, will be missing. 20 | 21 | ### iOS Build Setup 22 | 23 | 1. Set your build target to iOS 24 | 1. In `Project Settings > Player Settings` go to `Other Settings > Camera Usage Description` and type a description of why you are requesting camera access. This will be presented when you first open the app. 25 | 1. Set the `Client.scene` as your build scene in the Build Settings and build the Xcode project. 26 | 27 | ### Editor Animation Setup 28 | 29 | #### Install and Connection Testing 30 | 31 | 1. (Optional) install the Sloth Example from the Package Manager by selecting the ARKit Facial Remote package and installing the sample 32 | 33 | 1. Be sure your device and editor are on the same network. Launch the app on your device and press play in the editor. 34 | 35 | 1. Set the `Port` number on the device to the same `Port` listed on the `Stream Reader` component of the `Stream Reader` game object. 36 | 37 | 1. Set the `IP` of the device to one listed in the console debug log. 38 | 39 | 1. Press `Connect` on the device. If your face is in view you should now see your expressions driving the character on screen. 40 | *Note* You need to be on the same network and you may have to disable any active VPNs and/or disable firewall(s) on the ports you are using. This may be necessary on your computer and/or on the network. 41 | *Note* Our internal setup was using a dedicated wireless router attached to the editor computer or lighting port to ethernet adaptor. 42 | 43 | 44 | ### Known Issues 45 | 46 | 1. Character Rig Controller does not support Humanoid Avatar for bone animation. 47 | 48 | 1. Animation Baking does not support Humanoid Avatar for avatar bone animation. 49 | 50 | 1. Stream source can only connect to a single stream reader. 51 | 52 | 1. Some network setups cause an issue with DNS lookup for getting IP addresses of the server computer. 53 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9fa33fc8235ab43139ee20fb8848c12c 3 | timeCreated: 1524952536 4 | licenseType: Pro 5 | TextScriptImporter: 6 | externalObjects: {} 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8bab4068a932e434689f761a4f0b6cb1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/BlendShapeIndexData.cs: -------------------------------------------------------------------------------- 1 | namespace Unity.Labs.FacialRemote 2 | { 3 | public struct BlendShapeIndexData 4 | { 5 | readonly int m_Index; 6 | readonly string m_Name; 7 | 8 | public int index { get { return m_Index; } } 9 | public string name { get { return m_Name; } } 10 | 11 | public BlendShapeIndexData(int index, string name) 12 | { 13 | m_Index = index; 14 | m_Name = name; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Runtime/BlendShapeIndexData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84c8156d6dde47cdbc99ed6c6342263d 3 | timeCreated: 1529440907 -------------------------------------------------------------------------------- /Runtime/BlendShapeOverride.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Unity.Labs.FacialRemote 5 | { 6 | /// 7 | /// Stores the override values for an individual blend shape. 8 | /// 9 | [Serializable] 10 | public class BlendShapeOverride 11 | { 12 | #pragma warning disable 649 13 | [SerializeField] 14 | [Tooltip("Enables the use of these override values on a blend shape.")] 15 | bool m_UseOverride; 16 | 17 | [SerializeField] 18 | [Tooltip("Blend shape name to be overridden.")] 19 | string m_Name; 20 | 21 | [Range(0f, 1)] 22 | [SerializeField] 23 | [Tooltip("Smoothing to apply to blend shape values coming from the stream reader.")] 24 | float m_BlendShapeSmoothing = 0.1f; 25 | 26 | [Range(0, 0.1f)] 27 | [SerializeField] 28 | [Tooltip("Min threshold of change to register as a new blend shape value.")] 29 | float m_BlendShapeThreshold = 0.01f; 30 | 31 | [Range(-100, 100)] 32 | [SerializeField] 33 | [Tooltip("Offsets the zero value of the blend shape.")] 34 | float m_BlendShapeOffset; 35 | 36 | [Range(0, 200f)] 37 | [SerializeField] 38 | [Tooltip("Scaling coefficient applied to the blend shape values from the stream reader.")] 39 | float m_BlendShapeCoefficient = 120f; 40 | 41 | [Range(0, 100)] 42 | [SerializeField] 43 | [Tooltip("Max value a scaled blend shape can reach.")] 44 | float m_BlendShapeMax = 100f; 45 | #pragma warning restore 649 46 | 47 | public bool useOverride { get { return m_UseOverride; } } 48 | public string name { get { return m_Name; } } 49 | public float blendShapeSmoothing { get { return m_BlendShapeSmoothing; } } 50 | public float blendShapeThreshold { get { return m_BlendShapeThreshold; } } 51 | public float blendShapeOffset { get { return m_BlendShapeOffset; } } 52 | public float blendShapeCoefficient { get { return m_BlendShapeCoefficient; } } 53 | public float blendShapeMax { get { return m_BlendShapeMax; } } 54 | 55 | BlendShapeOverride(){} 56 | 57 | public BlendShapeOverride(string name) 58 | { 59 | m_Name = name; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Runtime/BlendShapeOverride.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b849b8f4813b44a1a5b0635be837fca3 3 | timeCreated: 1526497119 -------------------------------------------------------------------------------- /Runtime/BlendShapeUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ad5b2e9a016468399c1a4853a75150a 3 | timeCreated: 1529177459 -------------------------------------------------------------------------------- /Runtime/BlendShapesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace Unity.Labs.FacialRemote 7 | { 8 | /// 9 | /// 10 | /// Updates blend shape values from the stream reader to the skinned mesh renders referenced in this script. 11 | /// 12 | public class BlendShapesController : MonoBehaviour, IUsesStreamReader 13 | { 14 | [SerializeField] 15 | [Tooltip("Skinned Mesh Renders that contain the blend shapes that will be driven by this controller.")] 16 | SkinnedMeshRenderer[] m_SkinnedMeshRenderers = {}; 17 | 18 | [Range(0f, 1)] 19 | [SerializeField] 20 | [Tooltip("Smoothing to apply to blend shape values coming from the stream reader.")] 21 | float m_BlendShapeSmoothing = 0.1f; 22 | 23 | [Range(0, 0.1f)] 24 | [SerializeField] 25 | [Tooltip("Min threshold of change to register as a new blend shape value.")] 26 | float m_BlendShapeThreshold = 0.01f; 27 | 28 | [Range(0, 200f)] 29 | [SerializeField] 30 | [Tooltip("Scaling coefficient applied to the blend shape values from the stream reader.")] 31 | float m_BlendShapeCoefficient = 120f; 32 | 33 | [Range(0, 100)] 34 | [SerializeField] 35 | [Tooltip("Max value a scaled blend shape can reach.")] 36 | float m_BlendShapeMax = 100f; 37 | 38 | [SerializeField] 39 | [Range(0f, 1f)] 40 | [Tooltip("Smoothing to return to zero pose of character's blend shapes when tracking is lost.")] 41 | float m_TrackingLossSmoothing = 0.1f; 42 | 43 | [SerializeField] 44 | [Tooltip("Overrides settings for individual blend shapes.")] 45 | BlendShapeOverride[] m_Overrides; 46 | 47 | readonly Dictionary m_Indices = new Dictionary(); 48 | float[] m_BlendShapes; 49 | 50 | IStreamSettings m_LastStreamSettings; 51 | 52 | public SkinnedMeshRenderer[] skinnedMeshRenderers { get { return m_SkinnedMeshRenderers; }} 53 | public Dictionary blendShapeIndices { get { return m_Indices; } } 54 | 55 | public float[] blendShapesScaled { get; private set; } 56 | 57 | public IStreamReader streamReader { private get; set; } 58 | 59 | void Start() 60 | { 61 | var streamSource = streamReader.streamSource; 62 | if (streamSource == null) 63 | { 64 | Debug.LogError("Disabling BlendShapesController. No stream source set.", this); 65 | enabled = false; 66 | return; 67 | } 68 | 69 | var streamSettings = streamSource.streamSettings; 70 | if (streamSettings == null) 71 | { 72 | Debug.LogError("Disabling BlendShapesController. No stream settings", this); 73 | enabled = false; 74 | return; 75 | } 76 | 77 | var blendShapesCount = streamSettings.locations.Length; 78 | if (m_Overrides.Length != blendShapesCount) 79 | Array.Resize(ref m_Overrides, blendShapesCount); 80 | 81 | var filteredList = new List(); 82 | foreach (var renderer in m_SkinnedMeshRenderers) 83 | { 84 | if (renderer == null) 85 | { 86 | Debug.LogWarning("Null element in SkinnedMeshRenderer list in " + this); 87 | continue; 88 | } 89 | 90 | if (renderer.sharedMesh == null) 91 | { 92 | Debug.LogWarning("Missing mesh in " + renderer); 93 | continue; 94 | } 95 | 96 | filteredList.Add(renderer); 97 | } 98 | 99 | m_SkinnedMeshRenderers = filteredList.ToArray(); 100 | 101 | if (m_SkinnedMeshRenderers.Length < 1) 102 | { 103 | Debug.LogWarning("Blend Shape Controller has no valid Skinned Mesh Renderers."); 104 | enabled = false; 105 | } 106 | } 107 | 108 | void Update() 109 | { 110 | var streamSource = streamReader.streamSource; 111 | if (streamSource == null || !streamSource.active) 112 | return; 113 | 114 | var streamSettings = streamSource.streamSettings; 115 | if (streamSettings != m_LastStreamSettings) 116 | UpdateBlendShapeIndices(streamSettings); 117 | 118 | InterpolateBlendShapes(); 119 | 120 | foreach (var meshRenderer in m_SkinnedMeshRenderers) 121 | { 122 | var indices = m_Indices[meshRenderer]; 123 | var length = indices.Length; 124 | for (var i = 0; i < length; i++) 125 | { 126 | var datum = indices[i]; 127 | if (datum.index < 0) 128 | continue; 129 | 130 | meshRenderer.SetBlendShapeWeight(i, blendShapesScaled[datum.index]); 131 | } 132 | } 133 | } 134 | 135 | public void UpdateBlendShapeIndices(IStreamSettings settings) 136 | { 137 | m_LastStreamSettings = settings; 138 | var locations = settings.locations; 139 | var blendShapeCount = locations.Length; 140 | m_BlendShapes = new float[blendShapeCount]; 141 | blendShapesScaled = new float[blendShapeCount]; 142 | m_Indices.Clear(); 143 | var streamSettings = streamReader.streamSource.streamSettings; 144 | foreach (var meshRenderer in m_SkinnedMeshRenderers) 145 | { 146 | var mesh = meshRenderer.sharedMesh; 147 | var count = mesh.blendShapeCount; 148 | var indices = new BlendShapeIndexData[count]; 149 | for (var i = 0; i < count; i++) 150 | { 151 | var shapeName = mesh.GetBlendShapeName(i); 152 | var index = -1; 153 | foreach (var mapping in streamSettings.mappings) 154 | { 155 | var to = mapping.to; 156 | var from = mapping.from; 157 | if (shapeName.Contains(from)) 158 | index = Array.IndexOf(streamSettings.locations, from); 159 | 160 | if (shapeName.Contains(to)) 161 | index = Array.IndexOf(streamSettings.locations, from); 162 | } 163 | 164 | if (index < 0) 165 | { 166 | for (var j = 0; j < streamSettings.locations.Length; j++) 167 | { 168 | if (shapeName.Contains(streamSettings.locations[j])) 169 | { 170 | index = j; 171 | break; 172 | } 173 | } 174 | } 175 | 176 | indices[i] = new BlendShapeIndexData(index, shapeName); 177 | 178 | if (index < 0) 179 | Debug.LogWarningFormat("Blend shape {0} is not a valid AR blend shape", shapeName); 180 | } 181 | 182 | m_Indices.Add(meshRenderer, indices); 183 | } 184 | } 185 | 186 | public void InterpolateBlendShapes(bool force = false) 187 | { 188 | var streamSettings = streamReader.streamSource.streamSettings; 189 | var blendShapeCount = streamSettings.locations.Length; 190 | for (var i = 0; i < blendShapeCount; i++) 191 | { 192 | var blendShape = m_BlendShapes[i]; 193 | var blendShapeTarget = streamReader.blendShapesBuffer[i]; 194 | var useOverride = UseOverride(i); 195 | var blendShapeOverride = m_Overrides[i]; 196 | var threshold = useOverride ? blendShapeOverride.blendShapeThreshold : m_BlendShapeThreshold; 197 | var offset = useOverride ? blendShapeOverride.blendShapeOffset : 0f; 198 | var smoothing = useOverride ? blendShapeOverride.blendShapeSmoothing : m_BlendShapeSmoothing; 199 | 200 | if (force || streamReader.trackingActive) 201 | { 202 | if (Mathf.Abs(blendShapeTarget - blendShape) > threshold) 203 | m_BlendShapes[i] = Mathf.Lerp(blendShapeTarget, blendShape, smoothing); 204 | } 205 | else 206 | { 207 | m_BlendShapes[i] = Mathf.Lerp(0f, blendShape, m_TrackingLossSmoothing); 208 | } 209 | 210 | if (useOverride) 211 | { 212 | blendShapesScaled[i] = Mathf.Min(blendShape * blendShapeOverride.blendShapeCoefficient + offset, 213 | blendShapeOverride.blendShapeMax); 214 | } 215 | else 216 | { 217 | blendShapesScaled[i] = Mathf.Min(blendShape * m_BlendShapeCoefficient, m_BlendShapeMax); 218 | } 219 | } 220 | } 221 | 222 | void OnValidate() 223 | { 224 | if (streamReader == null) 225 | return; 226 | 227 | var streamSource = streamReader.streamSource; 228 | if (streamSource == null) 229 | return; 230 | 231 | var streamSettings = streamSource.streamSettings; 232 | // if (streamSettings == null || streamSettings.locations == null || streamSettings.locations.Length == 0) 233 | // return; 234 | 235 | // We do our best to keep the overrides up-to-date with current settings, but it's possible to get out of sync 236 | var locations = streamSettings.locations; 237 | var blendshapeCount = locations.Length; 238 | if (m_Overrides.Length != blendshapeCount) 239 | { 240 | #if UNITY_EDITOR 241 | var overridesCopy = new BlendShapeOverride[blendshapeCount]; 242 | 243 | for (var i = 0; i < blendshapeCount; i++) 244 | { 245 | var location = locations[i]; 246 | var blendShapeOverride = m_Overrides.FirstOrDefault(f => f.name == location) 247 | ?? new BlendShapeOverride(location); 248 | 249 | overridesCopy[i] = blendShapeOverride; 250 | } 251 | 252 | m_Overrides = overridesCopy; 253 | #endif 254 | } 255 | } 256 | 257 | bool UseOverride(int index) 258 | { 259 | return m_Overrides != null && index < m_Overrides.Length 260 | && m_Overrides[index] != null && m_Overrides[index].useOverride; 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /Runtime/BlendShapesController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db8052edd37c5da4ba56c08244eb648a 3 | timeCreated: 1526000630 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/CharacterRigController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 601c475b43c9a4e46b969b376a0d7d1a 3 | timeCreated: 1526002373 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/Client.cs: -------------------------------------------------------------------------------- 1 | #if INCLUDE_ARKIT_FACE_PLUGIN && INCLUDE_AR_FOUNDATION 2 | #define FACETRACKING 3 | #endif 4 | 5 | using System; 6 | using System.Net.Sockets; 7 | using System.Threading; 8 | using Unity.Collections; 9 | using UnityEngine; 10 | using UnityEngine.XR.ARKit; 11 | 12 | #if FACETRACKING 13 | using System.Linq; 14 | using System.Collections.Generic; 15 | using UnityEngine.XR.ARFoundation; 16 | #else 17 | using UnityObject = UnityEngine.Object; 18 | #endif 19 | 20 | namespace Unity.Labs.FacialRemote 21 | { 22 | /// 23 | /// Streams blend shape data from a device to a connected server. 24 | /// 25 | class Client : MonoBehaviour 26 | { 27 | const float k_Timeout = 5; 28 | const int k_SleepTime = 4; 29 | 30 | #pragma warning disable 649 31 | [SerializeField] 32 | [Tooltip("Stream settings that contain the settings for encoding the blend shapes' byte stream.")] 33 | StreamSettings m_StreamSettings; 34 | 35 | #if FACETRACKING 36 | [SerializeField] 37 | ARFaceManager m_FaceManager; 38 | #else 39 | [SerializeField] 40 | UnityObject m_FaceManager; 41 | #endif 42 | #pragma warning restore 649 43 | 44 | float[] m_BlendShapes; 45 | 46 | byte[] m_Buffer; 47 | Pose m_CameraPose; 48 | 49 | Transform m_CameraTransform; 50 | float m_CurrentTime = -1; 51 | 52 | Pose m_FacePose = new Pose(Vector3.zero, Quaternion.identity); 53 | bool m_Running; 54 | 55 | float m_StartTime; 56 | 57 | #if FACETRACKING 58 | bool m_ARFaceActive; 59 | Dictionary m_BlendShapeIndices; 60 | #endif 61 | 62 | public Transform faceAnchor { get; private set; } 63 | 64 | void Awake() 65 | { 66 | m_Buffer = new byte[m_StreamSettings.bufferSize]; 67 | m_BlendShapes = new float[m_StreamSettings.locations.Length]; 68 | m_CameraTransform = Camera.main.transform; 69 | 70 | Screen.sleepTimeout = SleepTimeout.NeverSleep; 71 | 72 | #if FACETRACKING 73 | m_FaceManager.facesChanged += ARFaceManagerOnFacesChanged; 74 | #endif 75 | } 76 | 77 | void Start() 78 | { 79 | // Wait to be enabled on StartCapture 80 | enabled = false; 81 | if (m_StreamSettings == null) 82 | { 83 | Debug.LogError("Stream settings is not assigned! Deactivating Client."); 84 | gameObject.SetActive(false); 85 | } 86 | } 87 | 88 | void Update() 89 | { 90 | m_CameraPose = new Pose(m_CameraTransform.position, m_CameraTransform.rotation); 91 | m_CurrentTime = Time.time; 92 | } 93 | 94 | void OnDestroy() 95 | { 96 | #if FACETRACKING 97 | m_FaceManager.facesChanged -= ARFaceManagerOnFacesChanged; 98 | #endif 99 | 100 | m_Running = false; 101 | } 102 | 103 | /// 104 | /// Starts stream thread using the provided socket. 105 | /// 106 | /// The socket to use when streaming blend shape data. 107 | public void StartCapture(Socket socket) 108 | { 109 | m_CameraTransform = Camera.main.transform; 110 | if (!m_CameraTransform) 111 | { 112 | Debug.LogWarning("Could not find main camera. Camera pose will not be captured"); 113 | m_CameraTransform = transform; // Use this transform to avoid null references 114 | } 115 | 116 | m_StartTime = Time.time; 117 | enabled = true; 118 | var poseArray = new float[BlendShapeUtils.PoseFloatCount]; 119 | var cameraPoseArray = new float[BlendShapeUtils.PoseFloatCount]; 120 | var frameNum = new int[1]; 121 | var frameTime = new float[1]; 122 | 123 | Application.targetFrameRate = 60; 124 | m_Running = true; 125 | 126 | new Thread(() => 127 | { 128 | var count = 0; 129 | #if FACETRACKING 130 | var lastIndex = m_Buffer.Length - 1; 131 | #endif 132 | while (m_Running) 133 | { 134 | try 135 | { 136 | if (socket.Connected) 137 | { 138 | if (m_CurrentTime > 0) 139 | { 140 | frameNum[0] = count++; 141 | frameTime[0] = m_CurrentTime - m_StartTime; 142 | m_CurrentTime = -1; 143 | 144 | m_Buffer[0] = m_StreamSettings.ErrorCheck; 145 | Buffer.BlockCopy(m_BlendShapes, 0, m_Buffer, 1, m_StreamSettings.BlendShapeSize); 146 | 147 | BlendShapeUtils.PoseToArray(m_FacePose, poseArray); 148 | BlendShapeUtils.PoseToArray(m_CameraPose, cameraPoseArray); 149 | 150 | Buffer.BlockCopy(poseArray, 0, m_Buffer, m_StreamSettings.HeadPoseOffset, BlendShapeUtils.PoseSize); 151 | Buffer.BlockCopy(cameraPoseArray, 0, m_Buffer, m_StreamSettings.CameraPoseOffset, BlendShapeUtils.PoseSize); 152 | Buffer.BlockCopy(frameNum, 0, m_Buffer, m_StreamSettings.FrameNumberOffset, m_StreamSettings.FrameNumberSize); 153 | Buffer.BlockCopy(frameTime, 0, m_Buffer, m_StreamSettings.FrameTimeOffset, m_StreamSettings.FrameTimeSize); 154 | #if FACETRACKING 155 | m_Buffer[lastIndex] = (byte)(m_ARFaceActive ? 1 : 0); 156 | #endif 157 | 158 | socket.Send(m_Buffer); 159 | } 160 | } 161 | else 162 | { 163 | TryTimeout(); 164 | } 165 | } 166 | catch (Exception e) 167 | { 168 | Debug.LogError(e.Message); 169 | TryTimeout(); 170 | } 171 | 172 | Thread.Sleep(k_SleepTime); 173 | } 174 | }).Start(); 175 | } 176 | 177 | #if FACETRACKING 178 | void ARFaceManagerOnFacesChanged(ARFacesChangedEventArgs changedEvent) 179 | { 180 | foreach (var arFace in changedEvent.removed) 181 | { 182 | FaceRemoved(arFace); 183 | } 184 | 185 | foreach (var arFace in changedEvent.updated) 186 | { 187 | FaceUpdated(arFace); 188 | } 189 | 190 | foreach (var arFace in changedEvent.added) 191 | { 192 | FaceAdded(arFace); 193 | } 194 | } 195 | 196 | void FaceAdded(ARFace anchorData) 197 | { 198 | var anchorTransform = anchorData.transform; 199 | m_FacePose.position = anchorTransform.localPosition; 200 | m_FacePose.rotation = anchorTransform.localRotation; 201 | m_ARFaceActive = true; 202 | faceAnchor = anchorTransform; 203 | 204 | UpdateBlendShapes(anchorData); 205 | } 206 | 207 | void FaceUpdated(ARFace anchorData) 208 | { 209 | var anchorTransform = anchorData.transform; 210 | m_FacePose.position = anchorTransform.localPosition; 211 | m_FacePose.rotation = anchorTransform.localRotation; 212 | 213 | UpdateBlendShapes(anchorData); 214 | } 215 | 216 | void FaceRemoved(ARFace anchorData) 217 | { 218 | // TODO: fix edge cases for multiple faces 219 | if (faceAnchor == anchorData.transform) 220 | faceAnchor = null; 221 | 222 | m_ARFaceActive = false; 223 | } 224 | 225 | void UpdateBlendShapes(ARFace anchorData) 226 | { 227 | var xrFaceSubsystem = m_FaceManager.subsystem; 228 | var arKitFaceSubsystem = (ARKitFaceSubsystem)xrFaceSubsystem; 229 | 230 | var faceId = anchorData.trackableId; 231 | using (var blendShapeCoefficients = arKitFaceSubsystem.GetBlendShapeCoefficients(faceId, Allocator.Temp)) 232 | { 233 | if (m_BlendShapeIndices == null) 234 | { 235 | m_BlendShapeIndices = new Dictionary(); 236 | 237 | var names = m_StreamSettings.locations.ToList(); 238 | names.Sort(); 239 | 240 | foreach (var featureCoefficient in blendShapeCoefficients) 241 | { 242 | var location = featureCoefficient.blendShapeLocation; 243 | var index = names.IndexOf(location.ToString()); 244 | if (index >= 0) 245 | m_BlendShapeIndices[(int)location] = index; 246 | } 247 | } 248 | 249 | foreach (var featureCoefficient in blendShapeCoefficients) 250 | { 251 | var location = (int)featureCoefficient.blendShapeLocation; 252 | if (m_BlendShapeIndices.TryGetValue(location, out var index)) 253 | m_BlendShapes[index] = featureCoefficient.coefficient; 254 | } 255 | } 256 | } 257 | #endif 258 | 259 | void TryTimeout() 260 | { 261 | if (m_CurrentTime - m_StartTime > k_Timeout) 262 | { 263 | m_Running = false; 264 | enabled = false; 265 | } 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /Runtime/Client.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2bee8c0b839d4394a9d27a7b36be2eea 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_StreamSettings: {fileID: 11400000, guid: a40a3380648a240bab934a19984df455, type: 2} 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Runtime/ClientGUI.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_IOS && !UNITY_EDITOR && INCLUDE_ARKIT_FACE_PLUGIN 2 | #define SUPPORTED 3 | #endif 4 | 5 | using System; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.Threading; 9 | using TMPro; 10 | using UnityEngine; 11 | using UnityEngine.UI; 12 | 13 | namespace Unity.Labs.FacialRemote 14 | { 15 | class ClientGUI : MonoBehaviour 16 | { 17 | #pragma warning disable 649 18 | [Tooltip("Percentage of screen width outside which the Face Lost GUI will appear")] 19 | [Range(0, 1)] 20 | [SerializeField] 21 | float m_WidthPercent = 0.5f; 22 | 23 | [Tooltip("Percentage of screen height outside which the Face Lost GUI will appear")] 24 | [Range(0, 1)] 25 | [SerializeField] 26 | float m_HeightPercent = 0.5f; 27 | 28 | [SerializeField] 29 | int m_Port = 9000; 30 | 31 | [SerializeField] 32 | string m_ServerIP = "192.168.1.2"; 33 | 34 | [SerializeField] 35 | Client m_Client; 36 | 37 | [SerializeField] 38 | Canvas m_MainGUI; 39 | 40 | [SerializeField] 41 | Canvas m_FaceLostGUI; 42 | 43 | [SerializeField] 44 | Canvas m_NotSupportedGUI; 45 | 46 | [SerializeField] 47 | Button m_ConnectButton; 48 | 49 | [SerializeField] 50 | TMP_InputField m_PortTextField; 51 | 52 | [SerializeField] 53 | TMP_InputField m_IPTextField; 54 | #pragma warning restore 649 55 | 56 | Camera m_Camera; 57 | 58 | float m_CenterX; 59 | float m_CenterY; 60 | 61 | Socket m_Socket; 62 | 63 | void Awake() 64 | { 65 | m_Camera = Camera.main; 66 | #if SUPPORTED 67 | m_MainGUI.enabled = false; 68 | m_FaceLostGUI.enabled = false; 69 | m_NotSupportedGUI.enabled = false; 70 | 71 | #else 72 | m_MainGUI.enabled = false; 73 | m_FaceLostGUI.enabled = false; 74 | m_NotSupportedGUI.enabled = true; 75 | enabled = false; 76 | #endif 77 | } 78 | 79 | void Start() 80 | { 81 | m_PortTextField.onValueChanged.AddListener(OnPortValueChanged); 82 | m_IPTextField.onValueChanged.AddListener(OnIPValueChanged); 83 | 84 | m_ConnectButton.onClick.AddListener(OnConnectClick); 85 | 86 | m_CenterX = Screen.width / 2f; 87 | m_CenterY = Screen.height / 2f; 88 | 89 | // Make sure text fields match serialized values 90 | m_PortTextField.text = m_Port.ToString(); 91 | m_IPTextField.text = m_ServerIP; 92 | } 93 | 94 | void Update() 95 | { 96 | m_FaceLostGUI.enabled = !FaceInView(); 97 | 98 | var connected = m_Socket != null && m_Socket.Connected; 99 | if (m_MainGUI.enabled && connected) 100 | m_Client.StartCapture(m_Socket); 101 | 102 | m_MainGUI.enabled = !connected; 103 | } 104 | 105 | void OnPortValueChanged(string value) 106 | { 107 | int port; 108 | if (int.TryParse(value, out port)) 109 | m_Port = port; 110 | else 111 | m_PortTextField.text = m_Port.ToString(); 112 | } 113 | 114 | void OnIPValueChanged(string value) 115 | { 116 | IPAddress ip; 117 | m_ConnectButton.gameObject.SetActive(IPAddress.TryParse(value, out ip)); 118 | m_ServerIP = value; 119 | } 120 | 121 | void OnConnectClick() 122 | { 123 | IPAddress ip; 124 | if (!IPAddress.TryParse(m_ServerIP, out ip)) 125 | return; 126 | 127 | new Thread(() => 128 | { 129 | try 130 | { 131 | var endPoint = new IPEndPoint(ip, m_Port); 132 | var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 133 | socket.Connect(endPoint); 134 | 135 | while (!socket.Connected) 136 | { 137 | Thread.Sleep(5); 138 | } 139 | 140 | m_Socket = socket; 141 | } 142 | catch (Exception e) 143 | { 144 | Debug.Log("Exception trying to connect: " + e.Message); 145 | } 146 | }).Start(); 147 | } 148 | 149 | bool FaceInView() 150 | { 151 | if (m_Client.faceAnchor == null) 152 | return false; 153 | 154 | var anchorScreenPos = m_Camera.WorldToScreenPoint(m_Client.faceAnchor.position); 155 | 156 | return !(Mathf.Abs(anchorScreenPos.x - m_CenterX) / m_CenterX > m_WidthPercent) 157 | && !(Mathf.Abs(anchorScreenPos.y - m_CenterY) / m_CenterY > m_HeightPercent); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Runtime/ClientGUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3b1e10d4ad0184a71abf8c4609ac8486 3 | timeCreated: 1524721802 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/Interfaces.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e68c382cda9c546d4b319ec431c5dda6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamReader.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | /// 6 | /// APIs provided by a stream reader 7 | /// 8 | public interface IStreamReader 9 | { 10 | /// 11 | /// The currently active stream source 12 | /// 13 | IStreamSource streamSource { get; } 14 | 15 | /// 16 | /// If true, log debug information to the console 17 | /// 18 | bool verboseLogging { get; } 19 | 20 | /// 21 | /// True when currently getting valid pose tracking data 22 | /// 23 | bool trackingActive { get; } 24 | 25 | /// 26 | /// Current blendshape weight values 27 | /// 28 | float[] blendShapesBuffer { get; } 29 | 30 | /// 31 | /// Current head pose 32 | /// 33 | Pose headPose { get; } 34 | 35 | /// 36 | /// Current camera pose 37 | /// 38 | Pose cameraPose { get; } 39 | 40 | /// 41 | /// Called by a StreamSource to when new data is available 42 | /// 43 | /// Data for this frame 44 | /// Offset into this buffer where the data starts 45 | void UpdateStreamData(byte[] buffer, int offset = 0); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamReader.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67d1ac31d58464ac48bc34e7a425651a 3 | timeCreated: 1529346994 -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamRecorder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | /// 6 | /// APIs provided by a stream recorder 7 | /// 8 | public interface IStreamRecorder 9 | { 10 | /// 11 | /// Start recording the current stream 12 | /// 13 | /// Settings for the current stream 14 | /// Current take number 15 | void StartRecording(IStreamSettings streamSettings, int take); 16 | 17 | /// 18 | /// Adds data from the given buffer to the current recording 19 | /// 20 | /// Data to be added 21 | /// Offset into this buffer where the data starts 22 | void AddDataToRecording(byte[] buffer, int offset = 0); 23 | 24 | /// 25 | /// Finish/finalize the current recording 26 | /// 27 | void FinishRecording(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamRecorder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf04cf4ba182e4ec78c0b1a7ce3d8166 3 | timeCreated: 1529346994 -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Unity.Labs.FacialRemote 2 | { 3 | /// 4 | /// Interface for common stream settings values. That contain the settings for the byte stream and decoding information. 5 | /// 6 | public interface IStreamSettings 7 | { 8 | /// 9 | /// Error check byte value. 10 | /// 11 | byte ErrorCheck { get; } 12 | 13 | /// 14 | /// Size of blend shapes in the byte array. 15 | /// 16 | int BlendShapeSize { get; } 17 | 18 | /// 19 | /// Size of frame number value in byte array. 20 | /// 21 | int FrameNumberSize { get; } 22 | 23 | /// 24 | /// Size of frame time value in byte array. 25 | /// 26 | int FrameTimeSize { get; } 27 | 28 | /// 29 | /// Location of head pose in byte array. 30 | /// 31 | int HeadPoseOffset { get; } 32 | 33 | /// 34 | /// Location of camera pose in byte array. 35 | /// 36 | int CameraPoseOffset { get; } 37 | 38 | /// 39 | /// Location of frame number value in byte array. 40 | /// 41 | int FrameNumberOffset { get; } 42 | 43 | /// 44 | /// Location of frame time value in byte array. 45 | /// 46 | int FrameTimeOffset { get; } 47 | 48 | /// 49 | /// Total size of buffer of byte array for single same of data. 50 | /// 51 | int bufferSize { get; } 52 | 53 | /// 54 | /// String names of the blend shapes in the stream with their index in the array being their relative location. 55 | /// 56 | string[] locations { get; } 57 | 58 | /// 59 | /// Rename mapping values to apply blend shape locations to a blend shape controller. 60 | /// 61 | Mapping[] mappings { get; } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c206bab795c24846ac211b9d592b67eb 3 | timeCreated: 1529339281 -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamSource.cs: -------------------------------------------------------------------------------- 1 | namespace Unity.Labs.FacialRemote 2 | { 3 | /// 4 | /// 5 | /// Interface for common values of a stream source. 6 | /// 7 | public interface IStreamSource : IUsesStreamReader 8 | { 9 | /// 10 | /// The IStreamSettings used to describe the data from this stream source 11 | /// 12 | IStreamSettings streamSettings { get; } 13 | 14 | /// 15 | /// Whether this stream source is currently updating tracking data 16 | /// 17 | bool active { get; } 18 | 19 | /// 20 | /// Called after the StreamReader updates 21 | /// 22 | void StreamSourceUpdate(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IStreamSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32a3e9a048aa43338ab464dacf530ed9 3 | timeCreated: 1529346994 -------------------------------------------------------------------------------- /Runtime/Interfaces/IUsesStreamReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unity.Labs.FacialRemote 4 | { 5 | /// 6 | /// Interface for getting access to the stream reader 7 | /// 8 | public interface IUsesStreamReader 9 | { 10 | /// 11 | /// The StreamReader that controls the session 12 | /// 13 | IStreamReader streamReader { set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Runtime/Interfaces/IUsesStreamReader.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65d54f4c45a44c079ac01b94f6e390ac 3 | timeCreated: 1529347022 -------------------------------------------------------------------------------- /Runtime/Mapping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Unity.Labs.FacialRemote 5 | { 6 | /// 7 | /// Use to hold name remapping for blend shapes. 8 | /// 9 | [Serializable] 10 | public struct Mapping 11 | { 12 | /// 13 | /// Name of the blend shape in the skinned mesh. 14 | /// 15 | [SerializeField] 16 | string m_From; 17 | 18 | /// 19 | /// Name of the blend shape in the controller. 20 | /// 21 | [SerializeField] 22 | string m_To; 23 | 24 | public string from 25 | { 26 | get { return m_From; } 27 | } 28 | 29 | public string to 30 | { 31 | get { return m_To; } 32 | } 33 | 34 | public Mapping(string from, string to) 35 | { 36 | m_From = from; 37 | m_To = to; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Runtime/Mapping.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 70b8698d0c99477aa5386692054bb594 3 | timeCreated: 1533740372 -------------------------------------------------------------------------------- /Runtime/NetworkStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Net.NetworkInformation; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using UnityEngine; 8 | 9 | namespace Unity.Labs.FacialRemote 10 | { 11 | /// 12 | /// 13 | /// A network-based stream source 14 | /// Sets up a listen server on the given port to which Clients connect 15 | /// 16 | public class NetworkStream : MonoBehaviour, IStreamSource 17 | { 18 | /// 19 | /// Maximum buffer queue size, after which old frames are discarded 20 | /// 21 | const int k_MaxBufferQueue = 512; 22 | 23 | /// 24 | /// Value for "backlog" argument in Socket.Listen 25 | /// 26 | const int k_MaxConnections = 64; 27 | 28 | #pragma warning disable 649 29 | [SerializeField] 30 | [Tooltip("Contains the buffer layout and blend shape name and mapping information for interpreting the data stream from a connected device.")] 31 | StreamSettings m_StreamSettings; 32 | 33 | [SerializeField] 34 | [Tooltip("Port number that the device will connect to, be sure to have this match the port set on the device.")] 35 | int m_Port = 9000; 36 | 37 | [SerializeField] 38 | [Tooltip("Threshold for number of missed frames before trying to skip frames with catch up size.")] 39 | int m_CatchUpThreshold = 16; 40 | 41 | [SerializeField] 42 | [Tooltip("How many frames should be processed at once if the editor falls behind processing the device stream. In an active recording these frames are still captured even if they are skipped in editor.")] 43 | int m_CatchUpSize = 3; 44 | 45 | [SerializeField] 46 | [Tooltip("(Optional) Manual override to use a specific stream recorder. Default behavior is to use GetComponentInChildren on this object.")] 47 | GameObject m_StreamRecorderOverride; 48 | #pragma warning restore 649 49 | 50 | int m_LastFrameNum; 51 | 52 | bool m_Running; 53 | 54 | readonly List m_ListenSockets = new List(); 55 | readonly List m_ActiveThreads = new List(); 56 | 57 | Socket m_TransferSocket; 58 | int m_TakeNumber; 59 | IStreamRecorder m_StreamRecorder; 60 | 61 | readonly Queue m_BufferQueue = new Queue(); 62 | readonly Queue m_UnusedBuffers = new Queue(); 63 | 64 | public bool recording { get; private set; } 65 | 66 | public IStreamReader streamReader { private get; set; } 67 | 68 | public bool active 69 | { 70 | get { return m_TransferSocket != null && m_TransferSocket.Connected; } 71 | } 72 | 73 | public IStreamSettings streamSettings { get { return m_StreamSettings; } } 74 | 75 | void Start() 76 | { 77 | if (m_StreamSettings == null) 78 | { 79 | Debug.LogErrorFormat("No Stream Setting set on {0}. Unable to run Server.", this); 80 | enabled = false; 81 | return; 82 | } 83 | 84 | m_StreamRecorder = m_StreamRecorderOverride 85 | ? m_StreamRecorderOverride.GetComponentInChildren() 86 | : GetComponentInChildren(); 87 | 88 | if (m_StreamRecorder == null) 89 | Debug.LogWarningFormat("No Stream Recorder found in {0}. You will not be able to record anything.", this); 90 | 91 | m_TakeNumber = 0; 92 | Debug.Log("Possible IP addresses:"); 93 | 94 | IPAddress[] addresses; 95 | try 96 | { 97 | addresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList; 98 | } 99 | catch (Exception) 100 | { 101 | Debug.LogWarning("DNS-based method failed, using network interfaces to find local IP"); 102 | var addressList = new List(); 103 | foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces()) 104 | { 105 | if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback) 106 | continue; 107 | 108 | switch (networkInterface.OperationalStatus) 109 | { 110 | case OperationalStatus.Up: 111 | case OperationalStatus.Unknown: 112 | foreach (var ip in networkInterface.GetIPProperties().UnicastAddresses) 113 | { 114 | addressList.Add(ip.Address); 115 | } 116 | 117 | break; 118 | } 119 | } 120 | 121 | addresses = addressList.ToArray(); 122 | } 123 | 124 | 125 | foreach (var address in addresses) 126 | { 127 | if (address.AddressFamily != AddressFamily.InterNetwork) 128 | continue; 129 | 130 | if (IPAddress.IsLoopback(address)) 131 | continue; 132 | 133 | var connectionAddress = address; 134 | Debug.Log(connectionAddress); 135 | 136 | Socket listenSocket; 137 | try 138 | { 139 | var endPoint = new IPEndPoint(connectionAddress, m_Port); 140 | listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 141 | listenSocket.Bind(endPoint); 142 | listenSocket.Listen(k_MaxConnections); 143 | m_ListenSockets.Add(listenSocket); 144 | 145 | m_LastFrameNum = -1; 146 | m_Running = true; 147 | } 148 | catch (Exception e) 149 | { 150 | Debug.LogErrorFormat("Error creating listen socket on address {0} : {1}", connectionAddress, e); 151 | continue; 152 | } 153 | 154 | var newtworkThread = new Thread(() => 155 | { 156 | // Block until timeout or successful connection 157 | var socket = listenSocket.Accept(); 158 | 159 | // If another socket has already accepted a connection, exit the thread 160 | if (m_TransferSocket != null) 161 | return; 162 | 163 | m_TransferSocket = socket; 164 | Debug.Log(string.Format("Client connected on {0}", connectionAddress)); 165 | 166 | var frameNumArray = new int[1]; 167 | var bufferSize = m_StreamSettings.bufferSize; 168 | 169 | while (m_Running) 170 | { 171 | if (streamReader == null) 172 | continue; 173 | 174 | var source = streamReader.streamSource; 175 | if (socket.Connected && source != null && source.Equals(this)) 176 | { 177 | try 178 | { 179 | if (m_StreamSettings == null || m_StreamSettings.bufferSize != bufferSize) 180 | { 181 | Debug.LogError("Settings changed while connnected. Please exit play mode before changing settings"); 182 | break; 183 | } 184 | 185 | var buffer = m_UnusedBuffers.Count == 0 ? new byte[bufferSize] : m_UnusedBuffers.Dequeue(); 186 | 187 | for (var i = 0; i < bufferSize; i++) 188 | { 189 | buffer[i] = 0; 190 | } 191 | 192 | socket.Receive(buffer); 193 | 194 | // Receive can fail and return an empty buffer 195 | if (buffer[0] == m_StreamSettings.ErrorCheck) 196 | { 197 | m_BufferQueue.Enqueue(buffer); 198 | 199 | if (recording) 200 | m_StreamRecorder.AddDataToRecording(buffer); 201 | 202 | Buffer.BlockCopy(buffer, m_StreamSettings.FrameNumberOffset, frameNumArray, 0, 203 | m_StreamSettings.FrameNumberSize); 204 | 205 | var frameNum = frameNumArray[0]; 206 | if (streamReader.verboseLogging && m_LastFrameNum != frameNum - 1) 207 | Debug.LogFormat("Dropped frame {0} (last frame: {1}) ", frameNum, m_LastFrameNum); 208 | 209 | m_LastFrameNum = frameNum; 210 | } 211 | } 212 | catch (Exception e) 213 | { 214 | // Expect an exception on the last frame when OnDestroy closes the socket 215 | if (m_Running) 216 | Debug.LogError(e.Message + "\n" + e.StackTrace); 217 | } 218 | } 219 | 220 | if (m_BufferQueue.Count > k_MaxBufferQueue) 221 | m_UnusedBuffers.Enqueue(m_BufferQueue.Dequeue()); 222 | 223 | Thread.Sleep(1); 224 | } 225 | 226 | socket.Disconnect(false); 227 | }); 228 | newtworkThread.Start(); 229 | m_ActiveThreads.Add(newtworkThread); 230 | } 231 | } 232 | 233 | public void StartRecording() 234 | { 235 | if (m_StreamRecorder == null) 236 | return; 237 | 238 | if (streamReader.streamSource.Equals(this) && !recording) 239 | { 240 | m_StreamRecorder.StartRecording(m_StreamSettings, m_TakeNumber); 241 | recording = true; 242 | 243 | m_TakeNumber++; 244 | } 245 | } 246 | 247 | public void StopRecording() 248 | { 249 | if (m_StreamRecorder == null) 250 | return; 251 | 252 | recording = false; 253 | m_StreamRecorder.FinishRecording(); 254 | } 255 | 256 | void UpdateCurrentFrameBuffer() 257 | { 258 | if (m_BufferQueue.Count == 0) 259 | return; 260 | 261 | // Throw out some old frames if we are too far behind 262 | if (m_BufferQueue.Count > m_CatchUpThreshold) 263 | { 264 | for (var i = 0; i < m_CatchUpSize; i++) 265 | { 266 | m_UnusedBuffers.Enqueue(m_BufferQueue.Dequeue()); 267 | } 268 | } 269 | 270 | var buffer = m_BufferQueue.Dequeue(); 271 | 272 | if (streamReader.streamSource.Equals(this)) 273 | streamReader.UpdateStreamData(buffer); 274 | 275 | m_UnusedBuffers.Enqueue(buffer); 276 | } 277 | 278 | public void StreamSourceUpdate() 279 | { 280 | var source = streamReader.streamSource; 281 | var notSource = source == null || !source.Equals(this); 282 | if (notSource && recording) 283 | StopRecording(); 284 | 285 | if (notSource || !active) 286 | return; 287 | 288 | if (streamReader.verboseLogging) 289 | { 290 | if (m_BufferQueue.Count > m_CatchUpSize) 291 | Debug.LogWarning(string.Format("{0} is larger than Catchup Size of {1} Dropping Frames!", 292 | m_BufferQueue.Count, m_CatchUpSize)); 293 | } 294 | 295 | UpdateCurrentFrameBuffer(); 296 | } 297 | 298 | void OnDestroy() 299 | { 300 | m_Running = false; 301 | 302 | foreach (var thread in m_ActiveThreads) 303 | { 304 | thread.Abort(); 305 | } 306 | 307 | foreach (var socket in m_ListenSockets) 308 | { 309 | if (socket.Connected) 310 | socket.Disconnect(false); 311 | 312 | socket.Close(); 313 | } 314 | } 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /Runtime/NetworkStream.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8172ccacadb6046a58bb68b5e91ff386 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_StreamSettings: {fileID: 11400000, guid: a40a3380648a240bab934a19984df455, type: 2} 8 | - m_StreamRecorderOverride: {instanceID: 0} 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/PlaybackBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Unity.Labs.FacialRemote 6 | { 7 | /// 8 | /// 9 | /// Contains settings and stream data for a recorded session. 10 | /// 11 | [Serializable] 12 | public class PlaybackBuffer : IStreamSettings 13 | { 14 | [SerializeField] 15 | [Tooltip("Name of the recorded stream.")] 16 | string m_Name; 17 | 18 | [SerializeField] 19 | [HideInInspector] 20 | [Tooltip("Recorded byte stream of blend shape data.")] 21 | byte[] m_RecordStream = { }; 22 | 23 | [SerializeField] 24 | [HideInInspector] 25 | [Tooltip("Error check byte value.")] 26 | byte m_ErrorCheck; 27 | 28 | [SerializeField] 29 | [HideInInspector] 30 | [Tooltip("Size of blend shapes in the byte array.")] 31 | int m_BlendShapeSize; 32 | 33 | [SerializeField] 34 | [HideInInspector] 35 | [Tooltip("Size of frame number value in byte array.")] 36 | int m_FrameNumberSize; 37 | 38 | [SerializeField] 39 | [HideInInspector] 40 | [Tooltip("Size of frame time value in byte array.")] 41 | int m_FrameTimeSize; 42 | 43 | [SerializeField] 44 | [HideInInspector] 45 | [Tooltip("Location of head pose in byte array.")] 46 | int m_HeadPoseOffset; 47 | 48 | [SerializeField] 49 | [HideInInspector] 50 | [Tooltip("Location of camera pose in byte array.")] 51 | int m_CameraPoseOffset; 52 | 53 | [SerializeField] 54 | [HideInInspector] 55 | [Tooltip("Location of frame number value in byte array.")] 56 | int m_FrameNumberOffset; 57 | 58 | [SerializeField] 59 | [HideInInspector] 60 | [Tooltip("Location of frame time value in byte array.")] 61 | int m_FrameTimeOffset; 62 | 63 | [SerializeField] 64 | [HideInInspector] 65 | [Tooltip("Total size of buffer of byte array for single same of data.")] 66 | int m_BufferSize; 67 | 68 | [SerializeField] 69 | [Tooltip("String names of the blend shapes in the stream with their index in the array being their relative location.")] 70 | string[] m_Locations = {}; 71 | 72 | [SerializeField] 73 | [Tooltip("Rename mapping values to apply blend shape locations to a blend shape controller.")] 74 | Mapping[] m_Mappings = {}; 75 | 76 | public byte ErrorCheck { get { return m_ErrorCheck; } } 77 | public int BlendShapeSize { get { return m_BlendShapeSize; } } 78 | public int FrameNumberSize { get { return m_FrameNumberSize; } } 79 | public int FrameTimeSize { get { return m_FrameTimeSize; } } 80 | public int HeadPoseOffset { get { return m_HeadPoseOffset; } } 81 | public int CameraPoseOffset { get { return m_CameraPoseOffset; } } 82 | public int FrameNumberOffset { get { return m_FrameNumberOffset; } } 83 | public int FrameTimeOffset { get { return m_FrameTimeOffset; } } 84 | public int bufferSize { get { return m_BufferSize; } } 85 | public Mapping[] mappings { get { return m_Mappings; } } 86 | public string[] locations { get { return m_Locations; } } 87 | 88 | public string name 89 | { 90 | get { return m_Name; } 91 | set { m_Name = value; } 92 | } 93 | 94 | public byte[] recordStream 95 | { 96 | get { return m_RecordStream; } 97 | set { m_RecordStream = value; } 98 | } 99 | 100 | PlaybackBuffer() {} 101 | 102 | public PlaybackBuffer(IStreamSettings streamSettings) 103 | { 104 | m_BufferSize = streamSettings.bufferSize; 105 | m_ErrorCheck = streamSettings.ErrorCheck; 106 | m_BlendShapeSize = streamSettings.BlendShapeSize; 107 | m_HeadPoseOffset = streamSettings.HeadPoseOffset; 108 | m_CameraPoseOffset = streamSettings.CameraPoseOffset; 109 | m_FrameNumberOffset = streamSettings.FrameNumberOffset; 110 | m_FrameTimeOffset = streamSettings.FrameTimeOffset; 111 | 112 | m_FrameNumberSize = streamSettings.FrameNumberSize; 113 | m_FrameTimeSize = streamSettings.FrameTimeSize; 114 | 115 | m_Locations = streamSettings.locations; 116 | m_Mappings = streamSettings.mappings; 117 | } 118 | 119 | public void UseDefaultLocations() 120 | { 121 | var locs = new List(); 122 | foreach (var location in BlendShapeUtils.Locations) 123 | { 124 | locs.Add(location); 125 | } 126 | 127 | locs.Sort(); 128 | m_Locations = locs.ToArray(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Runtime/PlaybackBuffer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c605cf8abce42dc8d49f1055cd23b3d 3 | timeCreated: 1527902600 -------------------------------------------------------------------------------- /Runtime/PlaybackData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | namespace Unity.Labs.FacialRemote 8 | { 9 | /// 10 | /// Asset for storing recorded sessions. 11 | /// 12 | [Serializable] 13 | [CreateAssetMenu(fileName = "PlaybackData", menuName = "Facial Remote/Playback Data")] 14 | public class PlaybackData : ScriptableObject 15 | { 16 | const int k_MinBufferAmount = 32; 17 | const int k_BufferCreateAmount = 6; 18 | 19 | [SerializeField] 20 | [Tooltip("Individual recorded playback buffers from a streaming source.")] 21 | PlaybackBuffer[] m_PlaybackBuffers; 22 | 23 | readonly Queue m_BufferQueue = new Queue(); 24 | readonly List m_RecordedBuffers = new List(); 25 | 26 | PlaybackBuffer m_ActivePlaybackBuffer; 27 | int m_CurrentBufferSize = -1; 28 | 29 | public PlaybackBuffer[] playbackBuffers { get { return m_PlaybackBuffers; } } 30 | 31 | void OnEnable() 32 | { 33 | #if UNITY_EDITOR 34 | EditorApplication.playModeStateChanged += PlayModeStateChanged; 35 | #endif 36 | } 37 | 38 | void OnDisable() 39 | { 40 | #if UNITY_EDITOR 41 | EditorApplication.playModeStateChanged -= PlayModeStateChanged; 42 | #endif 43 | } 44 | 45 | #if UNITY_EDITOR 46 | void PlayModeStateChanged(PlayModeStateChange state) 47 | { 48 | FinishRecording(); 49 | } 50 | #endif 51 | 52 | public void StartRecording(IStreamSettings streamSettings, int take) 53 | { 54 | var playbackBuffer = new PlaybackBuffer(streamSettings) 55 | { 56 | name = string.Format("{0:yyyy_MM_dd_HH_mm}-Take{1:00}", DateTime.Now, take) 57 | }; 58 | 59 | Debug.Log(string.Format("Starting take: {0}", playbackBuffer.name)); 60 | 61 | m_ActivePlaybackBuffer = playbackBuffer; 62 | 63 | var bufferSize = streamSettings.bufferSize; 64 | if (bufferSize != m_CurrentBufferSize) 65 | m_BufferQueue.Clear(); 66 | 67 | m_CurrentBufferSize = bufferSize; 68 | new Thread(() => 69 | { 70 | while (m_ActivePlaybackBuffer != null) 71 | { 72 | if (m_BufferQueue.Count < k_MinBufferAmount) 73 | { 74 | for (var i = 0; i < k_BufferCreateAmount; i++) 75 | { 76 | m_BufferQueue.Enqueue(new byte[m_CurrentBufferSize]); 77 | } 78 | } 79 | 80 | Thread.Sleep(1); 81 | } 82 | }).Start(); 83 | } 84 | 85 | public void AddDataToRecording(byte[] buffer, int offset = 0) 86 | { 87 | byte[] copyBuffer; 88 | if (m_BufferQueue.Count < 1) 89 | { 90 | Debug.LogWarning("Buffer Queue Empty"); 91 | copyBuffer = new byte[m_CurrentBufferSize]; 92 | } 93 | else 94 | { 95 | copyBuffer = m_BufferQueue.Dequeue(); 96 | } 97 | 98 | Buffer.BlockCopy(buffer, offset, copyBuffer, 0, m_CurrentBufferSize); 99 | 100 | m_RecordedBuffers.Add(copyBuffer); 101 | } 102 | 103 | public void FinishRecording() 104 | { 105 | if (m_ActivePlaybackBuffer == null) 106 | { 107 | RecycleRecordedBuffers(); 108 | return; 109 | } 110 | 111 | var bufferCount = m_RecordedBuffers.Count; 112 | if (string.IsNullOrEmpty(m_ActivePlaybackBuffer.name) || bufferCount == 0) 113 | { 114 | RecycleRecordedBuffers(); 115 | m_ActivePlaybackBuffer = null; 116 | return; 117 | } 118 | 119 | var recordStream = new byte[bufferCount * m_CurrentBufferSize]; 120 | m_ActivePlaybackBuffer.recordStream = recordStream; 121 | for (var i = 0; i < bufferCount; i++) 122 | { 123 | var buffer = m_RecordedBuffers[i]; 124 | Buffer.BlockCopy(buffer, 0, recordStream, i * m_CurrentBufferSize, m_CurrentBufferSize); 125 | m_BufferQueue.Enqueue(buffer); 126 | } 127 | 128 | var length = m_PlaybackBuffers.Length; 129 | var buffers = new PlaybackBuffer[length + 1]; 130 | for (var i = 0; i < length; i++) 131 | { 132 | buffers[i] = m_PlaybackBuffers[i]; 133 | } 134 | 135 | buffers[length] = m_ActivePlaybackBuffer; 136 | m_PlaybackBuffers = buffers; 137 | 138 | m_ActivePlaybackBuffer = null; 139 | 140 | #if UNITY_EDITOR 141 | EditorUtility.SetDirty(this); 142 | #endif 143 | } 144 | 145 | void RecycleRecordedBuffers() 146 | { 147 | if (m_RecordedBuffers.Count > 0) 148 | { 149 | foreach (var bytes in m_RecordedBuffers) 150 | { 151 | m_BufferQueue.Enqueue(bytes); 152 | } 153 | } 154 | } 155 | 156 | void OnValidate() 157 | { 158 | foreach (var playbackBuffer in m_PlaybackBuffers) 159 | { 160 | if (playbackBuffer.locations.Length == 0) 161 | { 162 | playbackBuffer.UseDefaultLocations(); 163 | } 164 | } 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Runtime/PlaybackData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21649ccc570324b479f22201a38e086a 3 | timeCreated: 1527193226 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/PlaybackStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Unity.Labs.FacialRemote 5 | { 6 | /// 7 | /// 8 | /// Reads tracking data from a PlaybackData asset and updates a Stream Reader. 9 | /// 10 | public class PlaybackStream : MonoBehaviour, IStreamSource, IStreamRecorder 11 | { 12 | #pragma warning disable 649 13 | [SerializeField] 14 | [Tooltip("Contains the individual streams recorded from a capture session.")] 15 | PlaybackData m_PlaybackData; 16 | #pragma warning restore 649 17 | 18 | float m_PlaybackStartTime = float.PositiveInfinity; 19 | 20 | int m_BufferPosition; 21 | 22 | byte[] m_CurrentFrameBuffer; 23 | readonly float[] m_FrameTime = new float[1]; 24 | float m_FirstFrameTime; 25 | float m_NextFrameTime; 26 | 27 | [NonSerialized] 28 | PlaybackBuffer m_ActivePlaybackBuffer; 29 | 30 | public IStreamReader streamReader { private get; set; } 31 | public bool active { get; private set; } 32 | public PlaybackBuffer activePlaybackBuffer { get { return m_ActivePlaybackBuffer; } } 33 | public IStreamSettings streamSettings { get { return activePlaybackBuffer; } } 34 | public PlaybackData playbackData { get { return m_PlaybackData; } } 35 | 36 | void Start() 37 | { 38 | if (!m_PlaybackData) 39 | Debug.LogWarningFormat("No Playback Data set on {0}. You will be unable to record, playback or bake any stream data.", 40 | gameObject.name); 41 | } 42 | 43 | public void StreamSourceUpdate() 44 | { 45 | var source = streamReader.streamSource; 46 | if (source != null && !source.Equals(this) && active) 47 | active = false; 48 | 49 | if (!active) 50 | return; 51 | 52 | if (Time.time - m_PlaybackStartTime < m_NextFrameTime - m_FirstFrameTime) 53 | return; 54 | 55 | if (!PlayBackLoop()) 56 | StopPlayback(); 57 | 58 | UpdateCurrentFrameBuffer(); 59 | } 60 | 61 | public void SetPlaybackBuffer(PlaybackBuffer buffer) 62 | { 63 | if (active) 64 | StopPlayback(); 65 | 66 | m_ActivePlaybackBuffer = buffer; 67 | } 68 | 69 | public void StartPlayback() 70 | { 71 | if (activePlaybackBuffer == null) 72 | { 73 | Debug.Log("No Playback Buffer Set."); 74 | SetPlaybackBuffer(playbackData.playbackBuffers[0]); 75 | } 76 | 77 | var settings = activePlaybackBuffer; 78 | m_CurrentFrameBuffer = new byte[settings.bufferSize]; 79 | for (var i = 0; i < settings.bufferSize; i++) 80 | { 81 | m_CurrentFrameBuffer[i] = 0; 82 | } 83 | 84 | Buffer.BlockCopy(activePlaybackBuffer.recordStream, 0, m_CurrentFrameBuffer, 0, streamSettings.bufferSize); 85 | Buffer.BlockCopy(m_CurrentFrameBuffer, streamSettings.FrameTimeOffset, m_FrameTime, 0, streamSettings.FrameTimeSize); 86 | 87 | m_PlaybackStartTime = Time.time; 88 | m_FirstFrameTime = m_FrameTime[0]; 89 | m_NextFrameTime = m_FirstFrameTime; 90 | m_BufferPosition = 0; 91 | 92 | active = true; 93 | } 94 | 95 | public void StopPlayback() 96 | { 97 | m_PlaybackStartTime = float.PositiveInfinity; 98 | active = false; 99 | } 100 | 101 | public bool PlayBackLoop() 102 | { 103 | if (m_BufferPosition + streamSettings.bufferSize > activePlaybackBuffer.recordStream.Length) 104 | return false; 105 | 106 | Buffer.BlockCopy(activePlaybackBuffer.recordStream, m_BufferPosition, 107 | m_CurrentFrameBuffer, 0, streamSettings.bufferSize); 108 | Buffer.BlockCopy(m_CurrentFrameBuffer, streamSettings.FrameTimeOffset, m_FrameTime, 109 | 0, streamSettings.FrameTimeSize); 110 | 111 | m_BufferPosition += streamSettings.bufferSize; 112 | m_NextFrameTime = m_FrameTime[0]; 113 | 114 | return true; 115 | } 116 | 117 | public void UpdateCurrentFrameBuffer(bool force = false) 118 | { 119 | if (force || streamReader.streamSource.Equals(this) && active) 120 | streamReader.UpdateStreamData(m_CurrentFrameBuffer); 121 | } 122 | 123 | public void StartRecording(IStreamSettings settings, int take) 124 | { 125 | playbackData.StartRecording(settings, take); 126 | } 127 | 128 | public void AddDataToRecording(byte[] buffer, int offset = 0) 129 | { 130 | playbackData.AddDataToRecording(buffer, offset); 131 | } 132 | 133 | public void FinishRecording() 134 | { 135 | playbackData.FinishRecording(); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Runtime/PlaybackStream.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44fb5c15f36a0ad43959c7c074f64b09 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_PlaybackData: {fileID: 11400000, guid: 6471208d98b8f5843bc5839ee125a490, type: 2} 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Runtime/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 169dc51c3b555ba4c86e369f5fb03086 3 | folderAsset: yes 4 | timeCreated: 1526000266 5 | licenseType: Pro 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Runtime/Prefabs/AR Face.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &4288144275462805626 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 5920237153773060622} 12 | - component: {fileID: 3996966741752958094} 13 | - component: {fileID: 3477713542785335550} 14 | - component: {fileID: 7738952074342772278} 15 | - component: {fileID: 432603542824043631} 16 | - component: {fileID: 835999181108086536} 17 | m_Layer: 0 18 | m_Name: AR Face 19 | m_TagString: Untagged 20 | m_Icon: {fileID: 0} 21 | m_NavMeshLayer: 0 22 | m_StaticEditorFlags: 0 23 | m_IsActive: 1 24 | --- !u!4 &5920237153773060622 25 | Transform: 26 | m_ObjectHideFlags: 0 27 | m_CorrespondingSourceObject: {fileID: 0} 28 | m_PrefabInstance: {fileID: 0} 29 | m_PrefabAsset: {fileID: 0} 30 | m_GameObject: {fileID: 4288144275462805626} 31 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 32 | m_LocalPosition: {x: 0, y: 0, z: 0} 33 | m_LocalScale: {x: 1, y: 1, z: 1} 34 | m_Children: [] 35 | m_Father: {fileID: 0} 36 | m_RootOrder: 0 37 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 38 | --- !u!114 &3996966741752958094 39 | MonoBehaviour: 40 | m_ObjectHideFlags: 0 41 | m_CorrespondingSourceObject: {fileID: 0} 42 | m_PrefabInstance: {fileID: 0} 43 | m_PrefabAsset: {fileID: 0} 44 | m_GameObject: {fileID: 4288144275462805626} 45 | m_Enabled: 1 46 | m_EditorHideFlags: 0 47 | m_Script: {fileID: 11500000, guid: 5d87bd45cfc214ce48ce8b882225dd11, type: 3} 48 | m_Name: 49 | m_EditorClassIdentifier: 50 | m_DestroyOnRemoval: 1 51 | --- !u!114 &3477713542785335550 52 | MonoBehaviour: 53 | m_ObjectHideFlags: 0 54 | m_CorrespondingSourceObject: {fileID: 0} 55 | m_PrefabInstance: {fileID: 0} 56 | m_PrefabAsset: {fileID: 0} 57 | m_GameObject: {fileID: 4288144275462805626} 58 | m_Enabled: 1 59 | m_EditorHideFlags: 0 60 | m_Script: {fileID: 11500000, guid: f4aab259b5c35443f9b1d0c15e2ad434, type: 3} 61 | m_Name: 62 | m_EditorClassIdentifier: 63 | --- !u!64 &7738952074342772278 64 | MeshCollider: 65 | m_ObjectHideFlags: 0 66 | m_CorrespondingSourceObject: {fileID: 0} 67 | m_PrefabInstance: {fileID: 0} 68 | m_PrefabAsset: {fileID: 0} 69 | m_GameObject: {fileID: 4288144275462805626} 70 | m_Material: {fileID: 0} 71 | m_IsTrigger: 0 72 | m_Enabled: 1 73 | serializedVersion: 3 74 | m_Convex: 0 75 | m_CookingOptions: 30 76 | m_Mesh: {fileID: 0} 77 | --- !u!33 &432603542824043631 78 | MeshFilter: 79 | m_ObjectHideFlags: 0 80 | m_CorrespondingSourceObject: {fileID: 0} 81 | m_PrefabInstance: {fileID: 0} 82 | m_PrefabAsset: {fileID: 0} 83 | m_GameObject: {fileID: 4288144275462805626} 84 | m_Mesh: {fileID: 0} 85 | --- !u!23 &835999181108086536 86 | MeshRenderer: 87 | m_ObjectHideFlags: 0 88 | m_CorrespondingSourceObject: {fileID: 0} 89 | m_PrefabInstance: {fileID: 0} 90 | m_PrefabAsset: {fileID: 0} 91 | m_GameObject: {fileID: 4288144275462805626} 92 | m_Enabled: 1 93 | m_CastShadows: 0 94 | m_ReceiveShadows: 0 95 | m_DynamicOccludee: 1 96 | m_MotionVectors: 1 97 | m_LightProbeUsage: 1 98 | m_ReflectionProbeUsage: 1 99 | m_RayTracingMode: 2 100 | m_RenderingLayerMask: 1 101 | m_RendererPriority: 0 102 | m_Materials: 103 | - {fileID: 2100000, guid: e8c90c443ee56462d8280d76f63d2922, type: 2} 104 | m_StaticBatchInfo: 105 | firstSubMesh: 0 106 | subMeshCount: 0 107 | m_StaticBatchRoot: {fileID: 0} 108 | m_ProbeAnchor: {fileID: 0} 109 | m_LightProbeVolumeOverride: {fileID: 0} 110 | m_ScaleInLightmap: 1 111 | m_ReceiveGI: 1 112 | m_PreserveUVs: 0 113 | m_IgnoreNormalsForChartDetection: 0 114 | m_ImportantGI: 0 115 | m_StitchLightmapSeams: 1 116 | m_SelectedEditorRenderState: 3 117 | m_MinimumChartSize: 4 118 | m_AutoUVMaxDistance: 0.5 119 | m_AutoUVMaxAngle: 89 120 | m_LightmapParameters: {fileID: 0} 121 | m_SortingLayerID: 0 122 | m_SortingLayer: 0 123 | m_SortingOrder: 0 124 | -------------------------------------------------------------------------------- /Runtime/Prefabs/AR Face.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ea755b7e141e5416e9855bf89cecf09f 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Prefabs/Client.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f94950507ce7740dfaa5e4deb18906c8 3 | timeCreated: 1524725931 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | externalObjects: {} 7 | mainObjectFileID: 100100000 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Runtime/Prefabs/FaceLostOverlay.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: FaceLostOverlay 10 | m_Shader: {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _ColorMask: 15 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _Stencil: 0 74 | - _StencilComp: 8 75 | - _StencilOp: 0 76 | - _StencilReadMask: 255 77 | - _StencilWriteMask: 255 78 | - _UVSec: 0 79 | - _UseUIAlphaClip: 0 80 | - _ZWrite: 1 81 | m_Colors: 82 | - _Color: {r: 1, g: 1, b: 1, a: 1} 83 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 84 | -------------------------------------------------------------------------------- /Runtime/Prefabs/FaceLostOverlay.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9972e2b7803bcf64fa2ba17b95983299 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Prefabs/StreamReader.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &1301902957927422 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 4795781088406236} 12 | - component: {fileID: 114853668929166538} 13 | - component: {fileID: 114180405116318928} 14 | - component: {fileID: 114641533554280668} 15 | m_Layer: 0 16 | m_Name: StreamReader 17 | m_TagString: Untagged 18 | m_Icon: {fileID: 0} 19 | m_NavMeshLayer: 0 20 | m_StaticEditorFlags: 0 21 | m_IsActive: 1 22 | --- !u!4 &4795781088406236 23 | Transform: 24 | m_ObjectHideFlags: 0 25 | m_CorrespondingSourceObject: {fileID: 0} 26 | m_PrefabInstance: {fileID: 0} 27 | m_PrefabAsset: {fileID: 0} 28 | m_GameObject: {fileID: 1301902957927422} 29 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 30 | m_LocalPosition: {x: 0, y: 0, z: 0} 31 | m_LocalScale: {x: 1, y: 1, z: 1} 32 | m_Children: [] 33 | m_Father: {fileID: 0} 34 | m_RootOrder: 0 35 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 36 | --- !u!114 &114853668929166538 37 | MonoBehaviour: 38 | m_ObjectHideFlags: 0 39 | m_CorrespondingSourceObject: {fileID: 0} 40 | m_PrefabInstance: {fileID: 0} 41 | m_PrefabAsset: {fileID: 0} 42 | m_GameObject: {fileID: 1301902957927422} 43 | m_Enabled: 1 44 | m_EditorHideFlags: 0 45 | m_Script: {fileID: 11500000, guid: 8172ccacadb6046a58bb68b5e91ff386, type: 3} 46 | m_Name: 47 | m_EditorClassIdentifier: 48 | m_StreamSettings: {fileID: 0} 49 | m_Port: 9000 50 | m_CatchUpThreshold: 16 51 | m_CatchUpSize: 3 52 | m_StreamRecorderOverride: {fileID: 0} 53 | --- !u!114 &114180405116318928 54 | MonoBehaviour: 55 | m_ObjectHideFlags: 0 56 | m_CorrespondingSourceObject: {fileID: 0} 57 | m_PrefabInstance: {fileID: 0} 58 | m_PrefabAsset: {fileID: 0} 59 | m_GameObject: {fileID: 1301902957927422} 60 | m_Enabled: 1 61 | m_EditorHideFlags: 0 62 | m_Script: {fileID: 11500000, guid: 44fb5c15f36a0ad43959c7c074f64b09, type: 3} 63 | m_Name: 64 | m_EditorClassIdentifier: 65 | m_PlaybackData: {fileID: 0} 66 | --- !u!114 &114641533554280668 67 | MonoBehaviour: 68 | m_ObjectHideFlags: 0 69 | m_CorrespondingSourceObject: {fileID: 0} 70 | m_PrefabInstance: {fileID: 0} 71 | m_PrefabAsset: {fileID: 0} 72 | m_GameObject: {fileID: 1301902957927422} 73 | m_Enabled: 1 74 | m_EditorHideFlags: 0 75 | m_Script: {fileID: 11500000, guid: 6d4971bbbce29c747ad31c2747bcbc57, type: 3} 76 | m_Name: 77 | m_EditorClassIdentifier: 78 | m_Character: {fileID: 0} 79 | m_VerboseLogging: 0 80 | m_TrackingLossPadding: 64 81 | m_BlendShapesControllerOverride: {fileID: 0} 82 | m_CharacterRigControllerOverride: {fileID: 0} 83 | m_HeadBoneOverride: {fileID: 0} 84 | m_CameraOverride: {fileID: 0} 85 | m_StreamSourceOverrides: [] 86 | -------------------------------------------------------------------------------- /Runtime/Prefabs/StreamReader.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 98f44cca61f34da4dbb00fe3ae4ca938 3 | timeCreated: 1524859873 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | externalObjects: {} 7 | mainObjectFileID: 100100000 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Runtime/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4bcd042a1a02baa4e8ef83f3d885c344 3 | folderAsset: yes 4 | timeCreated: 1526000254 5 | licenseType: Pro 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Runtime/Scenes/Client.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 930b9145849e94b95a973074b8dc0c1b 3 | timeCreated: 1510188488 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Scenes/Server.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_TemporalCoherenceThreshold: 1 54 | m_EnvironmentLightingMode: 0 55 | m_EnableBakedLightmaps: 1 56 | m_EnableRealtimeLightmaps: 1 57 | m_LightmapEditorSettings: 58 | serializedVersion: 10 59 | m_Resolution: 2 60 | m_BakeResolution: 40 61 | m_AtlasSize: 1024 62 | m_AO: 0 63 | m_AOMaxDistance: 1 64 | m_CompAOExponent: 1 65 | m_CompAOExponentDirect: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 0 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVRFilterTypeDirect: 0 81 | m_PVRFilterTypeIndirect: 0 82 | m_PVRFilterTypeAO: 0 83 | m_PVRFilteringMode: 1 84 | m_PVRCulling: 1 85 | m_PVRFilteringGaussRadiusDirect: 1 86 | m_PVRFilteringGaussRadiusIndirect: 5 87 | m_PVRFilteringGaussRadiusAO: 2 88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 90 | m_PVRFilteringAtrousPositionSigmaAO: 1 91 | m_ShowResolutionOverlay: 1 92 | m_LightingDataAsset: {fileID: 0} 93 | m_UseShadowmask: 1 94 | --- !u!196 &4 95 | NavMeshSettings: 96 | serializedVersion: 2 97 | m_ObjectHideFlags: 0 98 | m_BuildSettings: 99 | serializedVersion: 2 100 | agentTypeID: 0 101 | agentRadius: 0.5 102 | agentHeight: 2 103 | agentSlope: 45 104 | agentClimb: 0.4 105 | ledgeDropHeight: 0 106 | maxJumpAcrossDistance: 0 107 | minRegionArea: 2 108 | manualCellSize: 0 109 | cellSize: 0.16666667 110 | manualTileSize: 0 111 | tileSize: 256 112 | accuratePlacement: 0 113 | debug: 114 | m_Flags: 0 115 | m_NavMeshData: {fileID: 0} 116 | --- !u!1 &347698976 117 | GameObject: 118 | m_ObjectHideFlags: 0 119 | m_PrefabParentObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 0} 121 | serializedVersion: 5 122 | m_Component: 123 | - component: {fileID: 347698980} 124 | - component: {fileID: 347698979} 125 | - component: {fileID: 347698978} 126 | - component: {fileID: 347698977} 127 | m_Layer: 0 128 | m_Name: Main Camera 129 | m_TagString: MainCamera 130 | m_Icon: {fileID: 0} 131 | m_NavMeshLayer: 0 132 | m_StaticEditorFlags: 0 133 | m_IsActive: 1 134 | --- !u!81 &347698977 135 | AudioListener: 136 | m_ObjectHideFlags: 0 137 | m_PrefabParentObject: {fileID: 0} 138 | m_PrefabInternal: {fileID: 0} 139 | m_GameObject: {fileID: 347698976} 140 | m_Enabled: 1 141 | --- !u!124 &347698978 142 | Behaviour: 143 | m_ObjectHideFlags: 0 144 | m_PrefabParentObject: {fileID: 0} 145 | m_PrefabInternal: {fileID: 0} 146 | m_GameObject: {fileID: 347698976} 147 | m_Enabled: 1 148 | --- !u!20 &347698979 149 | Camera: 150 | m_ObjectHideFlags: 0 151 | m_PrefabParentObject: {fileID: 0} 152 | m_PrefabInternal: {fileID: 0} 153 | m_GameObject: {fileID: 347698976} 154 | m_Enabled: 1 155 | serializedVersion: 2 156 | m_ClearFlags: 1 157 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 158 | m_NormalizedViewPortRect: 159 | serializedVersion: 2 160 | x: 0 161 | y: 0 162 | width: 1 163 | height: 1 164 | near clip plane: 0.1 165 | far clip plane: 30 166 | field of view: 60 167 | orthographic: 0 168 | orthographic size: 5 169 | m_Depth: -1 170 | m_CullingMask: 171 | serializedVersion: 2 172 | m_Bits: 4294967295 173 | m_RenderingPath: -1 174 | m_TargetTexture: {fileID: 0} 175 | m_TargetDisplay: 0 176 | m_TargetEye: 3 177 | m_HDR: 1 178 | m_AllowMSAA: 1 179 | m_AllowDynamicResolution: 0 180 | m_ForceIntoRT: 0 181 | m_OcclusionCulling: 1 182 | m_StereoConvergence: 10 183 | m_StereoSeparation: 0.022 184 | --- !u!4 &347698980 185 | Transform: 186 | m_ObjectHideFlags: 0 187 | m_PrefabParentObject: {fileID: 0} 188 | m_PrefabInternal: {fileID: 0} 189 | m_GameObject: {fileID: 347698976} 190 | m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} 191 | m_LocalPosition: {x: -0.25, y: 0.25, z: 0} 192 | m_LocalScale: {x: 1, y: 1, z: 1} 193 | m_Children: [] 194 | m_Father: {fileID: 0} 195 | m_RootOrder: 0 196 | m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} 197 | --- !u!1001 &763425897 198 | Prefab: 199 | m_ObjectHideFlags: 0 200 | serializedVersion: 2 201 | m_Modification: 202 | m_TransformParent: {fileID: 0} 203 | m_Modifications: 204 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 205 | propertyPath: m_LocalPosition.x 206 | value: 0 207 | objectReference: {fileID: 0} 208 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 209 | propertyPath: m_LocalPosition.y 210 | value: 0 211 | objectReference: {fileID: 0} 212 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 213 | propertyPath: m_LocalPosition.z 214 | value: 0 215 | objectReference: {fileID: 0} 216 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 217 | propertyPath: m_LocalRotation.x 218 | value: 0 219 | objectReference: {fileID: 0} 220 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 221 | propertyPath: m_LocalRotation.y 222 | value: 0 223 | objectReference: {fileID: 0} 224 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 225 | propertyPath: m_LocalRotation.z 226 | value: 0 227 | objectReference: {fileID: 0} 228 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 229 | propertyPath: m_LocalRotation.w 230 | value: 1 231 | objectReference: {fileID: 0} 232 | - target: {fileID: 4795781088406236, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 233 | propertyPath: m_RootOrder 234 | value: 2 235 | objectReference: {fileID: 0} 236 | m_RemovedComponents: [] 237 | m_ParentPrefab: {fileID: 100100000, guid: 98f44cca61f34da4dbb00fe3ae4ca938, type: 2} 238 | m_IsPrefabParent: 0 239 | --- !u!1 &1845804764 240 | GameObject: 241 | m_ObjectHideFlags: 0 242 | m_PrefabParentObject: {fileID: 0} 243 | m_PrefabInternal: {fileID: 0} 244 | serializedVersion: 5 245 | m_Component: 246 | - component: {fileID: 1845804766} 247 | - component: {fileID: 1845804765} 248 | m_Layer: 0 249 | m_Name: Directional Light 250 | m_TagString: Untagged 251 | m_Icon: {fileID: 0} 252 | m_NavMeshLayer: 0 253 | m_StaticEditorFlags: 0 254 | m_IsActive: 1 255 | --- !u!108 &1845804765 256 | Light: 257 | m_ObjectHideFlags: 0 258 | m_PrefabParentObject: {fileID: 0} 259 | m_PrefabInternal: {fileID: 0} 260 | m_GameObject: {fileID: 1845804764} 261 | m_Enabled: 1 262 | serializedVersion: 8 263 | m_Type: 1 264 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 265 | m_Intensity: 0.57 266 | m_Range: 10 267 | m_SpotAngle: 30 268 | m_CookieSize: 10 269 | m_Shadows: 270 | m_Type: 2 271 | m_Resolution: -1 272 | m_CustomResolution: -1 273 | m_Strength: 1 274 | m_Bias: 0.05 275 | m_NormalBias: 0.4 276 | m_NearPlane: 0.2 277 | m_Cookie: {fileID: 0} 278 | m_DrawHalo: 0 279 | m_Flare: {fileID: 0} 280 | m_RenderMode: 0 281 | m_CullingMask: 282 | serializedVersion: 2 283 | m_Bits: 4294967295 284 | m_Lightmapping: 4 285 | m_AreaSize: {x: 1, y: 1} 286 | m_BounceIntensity: 1 287 | m_ColorTemperature: 6570 288 | m_UseColorTemperature: 0 289 | m_ShadowRadius: 0 290 | m_ShadowAngle: 0 291 | --- !u!4 &1845804766 292 | Transform: 293 | m_ObjectHideFlags: 0 294 | m_PrefabParentObject: {fileID: 0} 295 | m_PrefabInternal: {fileID: 0} 296 | m_GameObject: {fileID: 1845804764} 297 | m_LocalRotation: {x: 0.4594426, y: 0.020470567, z: 0.42118073, w: 0.7817289} 298 | m_LocalPosition: {x: 0, y: 0.28, z: 0} 299 | m_LocalScale: {x: 1, y: 1, z: 1} 300 | m_Children: [] 301 | m_Father: {fileID: 0} 302 | m_RootOrder: 1 303 | m_LocalEulerAnglesHint: {x: 44.513, y: 35.988003, z: 71.773} 304 | -------------------------------------------------------------------------------- /Runtime/Scenes/Server.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4301ff739d6994e25b61e5698b6b5843 3 | timeCreated: 1524723185 4 | licenseType: Pro 5 | DefaultImporter: 6 | externalObjects: {} 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Runtime/Settings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b34fc886acfa74020be27dd8f9f78f09 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Settings/Default Stream Settings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: e9873bf0085043ad8a2f13636d3b7fe5, type: 3} 13 | m_Name: Default Stream Settings 14 | m_EditorClassIdentifier: 15 | m_ErrorCheck: 42 16 | m_BlendShapeSize: 208 17 | m_FrameNumberSize: 4 18 | m_FrameTimeSize: 4 19 | m_HeadPoseOffset: 209 20 | m_CameraPoseOffset: 237 21 | m_FrameNumberOffset: 265 22 | m_FrameTimeOffset: 269 23 | m_BufferSize: 274 24 | m_Locations: 25 | - BrowDownLeft 26 | - BrowDownRight 27 | - BrowInnerUp 28 | - BrowOuterUpLeft 29 | - BrowOuterUpRight 30 | - CheekPuff 31 | - CheekSquintLeft 32 | - CheekSquintRight 33 | - EyeBlinkLeft 34 | - EyeBlinkRight 35 | - EyeLookDownLeft 36 | - EyeLookDownRight 37 | - EyeLookInLeft 38 | - EyeLookInRight 39 | - EyeLookOutLeft 40 | - EyeLookOutRight 41 | - EyeLookUpLeft 42 | - EyeLookUpRight 43 | - EyeSquintLeft 44 | - EyeSquintRight 45 | - EyeWideLeft 46 | - EyeWideRight 47 | - JawForward 48 | - JawLeft 49 | - JawOpen 50 | - JawRight 51 | - MouthClose 52 | - MouthDimpleLeft 53 | - MouthDimpleRight 54 | - MouthFrownLeft 55 | - MouthFrownRight 56 | - MouthFunnel 57 | - MouthLeft 58 | - MouthLowerDownLeft 59 | - MouthLowerDownRight 60 | - MouthPressLeft 61 | - MouthPressRight 62 | - MouthPucker 63 | - MouthRight 64 | - MouthRollLower 65 | - MouthRollUpper 66 | - MouthShrugLower 67 | - MouthShrugUpper 68 | - MouthSmileLeft 69 | - MouthSmileRight 70 | - MouthStretchLeft 71 | - MouthStretchRight 72 | - MouthUpperUpLeft 73 | - MouthUpperUpRight 74 | - NoseSneerLeft 75 | - NoseSneerRight 76 | - TongueOut 77 | m_Mappings: [] 78 | -------------------------------------------------------------------------------- /Runtime/Settings/Default Stream Settings.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 664f63512dc824ff69313c1e0b49cc3e 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Settings/Legacy Stream Settings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: e9873bf0085043ad8a2f13636d3b7fe5, type: 3} 13 | m_Name: Legacy Stream Settings 14 | m_EditorClassIdentifier: 15 | m_ErrorCheck: 42 16 | m_BlendShapeCount: 51 17 | m_BlendShapeSize: 204 18 | m_FrameNumberSize: 4 19 | m_FrameTimeSize: 4 20 | m_HeadPoseOffset: 205 21 | m_CameraPoseOffset: 233 22 | m_FrameNumberOffset: 261 23 | m_FrameTimeOffset: 265 24 | m_BufferSize: 270 25 | m_Locations: 26 | - BrowDownLeft 27 | - BrowDownRight 28 | - BrowInnerUp 29 | - BrowOuterUpLeft 30 | - BrowOuterUpRight 31 | - CheekPuff 32 | - CheekSquintLeft 33 | - CheekSquintRight 34 | - EyeBlinkLeft 35 | - EyeBlinkRight 36 | - EyeLookDownLeft 37 | - EyeLookDownRight 38 | - EyeLookInLeft 39 | - EyeLookInRight 40 | - EyeLookOutLeft 41 | - EyeLookOutRight 42 | - EyeLookUpLeft 43 | - EyeLookUpRight 44 | - EyeSquintLeft 45 | - EyeSquintRight 46 | - EyeWideLeft 47 | - EyeWideRight 48 | - JawForward 49 | - JawLeft 50 | - JawOpen 51 | - JawRight 52 | - MouthClose 53 | - MouthDimpleLeft 54 | - MouthDimpleRight 55 | - MouthFrownLeft 56 | - MouthFrownRight 57 | - MouthFunnel 58 | - MouthLeft 59 | - MouthLowerDownLeft 60 | - MouthLowerDownRight 61 | - MouthPressLeft 62 | - MouthPressRight 63 | - MouthPucker 64 | - MouthRight 65 | - MouthRollLower 66 | - MouthRollUpper 67 | - MouthShrugLower 68 | - MouthShrugUpper 69 | - MouthSmileLeft 70 | - MouthSmileRight 71 | - MouthStretchLeft 72 | - MouthStretchRight 73 | - MouthUpperUpLeft 74 | - MouthUpperUpRight 75 | - NoseSneerLeft 76 | - NoseSneerRight 77 | - TongueOut 78 | m_Mappings: 79 | - m_From: BrowDownLeft 80 | m_To: browDown_L 81 | - m_From: BrowDownRight 82 | m_To: browDown_R 83 | - m_From: BrowInnerUp 84 | m_To: browInnerUp 85 | - m_From: BrowOuterUpLeft 86 | m_To: browOuterUp_L 87 | - m_From: BrowOuterUpRight 88 | m_To: browOuterUp_R 89 | - m_From: CheekPuff 90 | m_To: cheekPuff 91 | - m_From: CheekSquintLeft 92 | m_To: cheekSquint_L 93 | - m_From: CheekSquintRight 94 | m_To: cheekSquint_R 95 | - m_From: EyeBlinkLeft 96 | m_To: eyeBlink_L 97 | - m_From: EyeBlinkRight 98 | m_To: eyeBlink_R 99 | - m_From: EyeLookDownLeft 100 | m_To: eyeLookDown_L 101 | - m_From: EyeLookDownRight 102 | m_To: eyeLookDown_R 103 | - m_From: EyeLookInLeft 104 | m_To: eyeLookIn_L 105 | - m_From: EyeLookInRight 106 | m_To: eyeLookIn_R 107 | - m_From: EyeLookOutLeft 108 | m_To: eyeLookOut_L 109 | - m_From: EyeLookOutRight 110 | m_To: eyeLookOut_R 111 | - m_From: EyeLookUpLeft 112 | m_To: eyeLookUp_L 113 | - m_From: EyeLookUpRight 114 | m_To: eyeLookUp_R 115 | - m_From: EyeSquintLeft 116 | m_To: eyeSquint_L 117 | - m_From: EyeSquintRight 118 | m_To: eyeSquint_R 119 | - m_From: EyeWideLeft 120 | m_To: eyeWide_L 121 | - m_From: EyeWideRight 122 | m_To: eyeWide_R 123 | - m_From: JawForward 124 | m_To: jawForward 125 | - m_From: JawLeft 126 | m_To: jawLeft 127 | - m_From: JawOpen 128 | m_To: jawOpen 129 | - m_From: JawRight 130 | m_To: jawRight 131 | - m_From: MouthClose 132 | m_To: mouthClose 133 | - m_From: MouthDimpleLeft 134 | m_To: mouthDimple_L 135 | - m_From: MouthDimpleRight 136 | m_To: mouthDimple_R 137 | - m_From: MouthFrownLeft 138 | m_To: mouthFrown_L 139 | - m_From: MouthFrownRight 140 | m_To: mouthFrown_R 141 | - m_From: MouthFunnel 142 | m_To: mouthFunnel 143 | - m_From: MouthLeft 144 | m_To: mouthLeft 145 | - m_From: MouthLowerDownLeft 146 | m_To: mouthLowerDown_L 147 | - m_From: MouthLowerDownRight 148 | m_To: mouthLowerDown_R 149 | - m_From: MouthPressLeft 150 | m_To: mouthPress_L 151 | - m_From: MouthPressRight 152 | m_To: mouthPress_R 153 | - m_From: MouthPucker 154 | m_To: mouthPucker 155 | - m_From: MouthRight 156 | m_To: mouthRight 157 | - m_From: MouthRollLower 158 | m_To: mouthRollLower 159 | - m_From: MouthRollUpper 160 | m_To: mouthRollUpper 161 | - m_From: MouthShrugLower 162 | m_To: mouthShrugLower 163 | - m_From: MouthShrugUpper 164 | m_To: mouthShrugUpper 165 | - m_From: MouthSmileLeft 166 | m_To: mouthSmile_L 167 | - m_From: MouthSmileRight 168 | m_To: mouthSmile_R 169 | - m_From: MouthStretchLeft 170 | m_To: mouthStretch_L 171 | - m_From: MouthStretchRight 172 | m_To: mouthStretch_R 173 | - m_From: MouthUpperUpLeft 174 | m_To: mouthUpperUp_L 175 | - m_From: MouthUpperUpRight 176 | m_To: mouthUpperUp_R 177 | - m_From: NoseSneerLeft 178 | m_To: noseSneer_L 179 | - m_From: NoseSneerRight 180 | m_To: noseSneer_R 181 | - m_From: TongueOut 182 | m_To: tongueOut 183 | -------------------------------------------------------------------------------- /Runtime/Settings/Legacy Stream Settings.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8bc5c491c89cd42d4b2a092c66415d49 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f19828667a2f43daaca2e7a9061236d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Shaders/ARFaceShader.shader: -------------------------------------------------------------------------------- 1 | Shader "ARKit/AR Face" { 2 | Properties { 3 | _Color ("Color", Color) = (1,1,1,1) 4 | _MainTex ("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness ("Smoothness", Range(0,1)) = 0.5 6 | _Metallic ("Metallic", Range(0,1)) = 0.0 7 | _RimColor ("Rim Color", Color) = (0.26,0.19,0.16,0.0) 8 | _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0 9 | } 10 | SubShader { 11 | Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" } 12 | Blend OneMinusDstColor One 13 | LOD 200 14 | 15 | CGPROGRAM 16 | // Physically based Standard lighting model, and enable shadows on all light types 17 | #pragma surface surf Standard fullforwardshadows 18 | 19 | // Use shader model 3.0 target, to get nicer looking lighting 20 | #pragma target 3.0 21 | 22 | sampler2D _MainTex; 23 | 24 | struct Input { 25 | float2 uv_MainTex; 26 | float3 viewDir; 27 | }; 28 | 29 | half _Glossiness; 30 | half _Metallic; 31 | fixed4 _Color; 32 | float4 _RimColor; 33 | float _RimPower; 34 | 35 | // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. 36 | // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. 37 | // #pragma instancing_options assumeuniformscaling 38 | UNITY_INSTANCING_BUFFER_START(Props) 39 | // put more per-instance properties here 40 | UNITY_INSTANCING_BUFFER_END(Props) 41 | 42 | void surf (Input IN, inout SurfaceOutputStandard o) { 43 | // Albedo comes from a texture tinted by color 44 | fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 45 | half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal)); 46 | rim = pow(rim, _RimPower); 47 | o.Albedo = c.rgb * rim; 48 | // Metallic and smoothness come from slider variables 49 | o.Metallic = _Metallic; 50 | o.Smoothness = _Glossiness; 51 | o.Emission = rim * _RimColor.rgb; 52 | o.Alpha = c.a * rim; 53 | } 54 | ENDCG 55 | } 56 | FallBack "Diffuse" 57 | } 58 | -------------------------------------------------------------------------------- /Runtime/Shaders/ARFaceShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 811156b770cc047d896b5b19ebd9e9a2 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Runtime/StreamReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Unity.Labs.FacialRemote 6 | { 7 | /// 8 | /// 9 | /// This component acts as the hub for using the Facial AR Remote in editor. It is responsible for processing the 10 | /// stream data from the stream source(s) to be used by connected controllers. It allows you to control the device 11 | /// connection, and record and playback captured streams to a character. 12 | /// 13 | public class StreamReader : MonoBehaviour, IStreamReader 14 | { 15 | #pragma warning disable 649 16 | [SerializeField] 17 | [Tooltip("Root of character to be be driven.")] 18 | GameObject m_Character; 19 | 20 | [SerializeField] 21 | [Tooltip("Shows extra logging information in the console.")] 22 | bool m_VerboseLogging; 23 | 24 | [SerializeField] 25 | [Range(1, 512)] 26 | [Tooltip("Number of frames of same head tracking data before tracking is considered lost.")] 27 | int m_TrackingLossPadding = 64; 28 | 29 | [SerializeField] 30 | [Tooltip("(Optional) Manually override the blend shape controller found in the Character.")] 31 | BlendShapesController m_BlendShapesControllerOverride; 32 | 33 | [SerializeField] 34 | [Tooltip("(Optional) Manually override the character rig controller found in the Character.")] 35 | CharacterRigController m_CharacterRigControllerOverride; 36 | 37 | [SerializeField] 38 | [Tooltip("(Optional) Manually override the head bone set from the character rig controller. Used for determining the start pose of the character.")] 39 | Transform m_HeadBoneOverride; 40 | 41 | [SerializeField] 42 | [Tooltip("(Optional) Manually override the main camera found by the stream reader. Used for determining the starting pose of the camera.")] 43 | Camera m_CameraOverride; 44 | 45 | [SerializeField] 46 | [Tooltip("(Optional) Manually add stream sources which aren't on this GameObject or its children.")] 47 | GameObject[] m_StreamSourceOverrides = { }; 48 | #pragma warning restore 649 49 | 50 | IStreamSource m_ActiveStreamSource; 51 | 52 | int m_TrackingLossCount; 53 | 54 | bool m_FaceActive; 55 | Pose m_CameraPose; 56 | Pose m_HeadPose; 57 | Vector3 m_LastHeadPosition; 58 | 59 | float[] m_CameraPoseArray = new float[BlendShapeUtils.PoseFloatCount]; 60 | float[] m_HeadPoseArray = new float[BlendShapeUtils.PoseFloatCount]; 61 | int[] m_FrameNumArray = new int[1]; 62 | float[] m_FrameTimeArray = new float[1]; 63 | 64 | HashSet m_Sources = new HashSet(); 65 | 66 | public float[] blendShapesBuffer { get; private set; } 67 | public bool trackingActive { get; private set; } 68 | 69 | public Pose headPose { get { return m_HeadPose; } } 70 | public Pose cameraPose { get { return m_CameraPose; } } 71 | public bool verboseLogging { get { return m_VerboseLogging; } } 72 | public Transform headBone { get; private set; } 73 | public Transform cameraTransform { get; private set; } 74 | public HashSet sources { get { return m_Sources; } } 75 | public BlendShapesController blendShapesController { get; private set; } 76 | public CharacterRigController characterRigController { get; private set; } 77 | 78 | public IStreamSource streamSource 79 | { 80 | get { return m_ActiveStreamSource; } 81 | set 82 | { 83 | if (m_ActiveStreamSource == value) 84 | return; 85 | 86 | m_ActiveStreamSource = value; 87 | 88 | if (value == null) 89 | return; 90 | 91 | var blendShapeCount = value.streamSettings.locations.Length; 92 | if (blendShapesBuffer == null || blendShapesBuffer.Length != blendShapeCount) 93 | blendShapesBuffer = new float[blendShapeCount]; 94 | } 95 | } 96 | 97 | public void UpdateStreamData(byte[] buffer, int offset = 0) 98 | { 99 | var settings = streamSource.streamSettings; 100 | 101 | Buffer.BlockCopy(buffer, offset + 1, blendShapesBuffer, 0, settings.BlendShapeSize); 102 | m_FaceActive = buffer[offset + settings.bufferSize - 1] == 1; 103 | 104 | if (m_VerboseLogging) 105 | { 106 | Buffer.BlockCopy(buffer, offset + settings.FrameNumberOffset, m_FrameNumArray, 0, settings.FrameNumberSize); 107 | Buffer.BlockCopy(buffer, offset + settings.FrameTimeOffset, m_FrameTimeArray, 0, settings.FrameTimeSize); 108 | Debug.Log(string.Format("{0} : {1}", m_FrameNumArray[0], m_FrameTimeArray[0])); 109 | } 110 | 111 | if (m_FaceActive) 112 | { 113 | Buffer.BlockCopy(buffer, offset + settings.HeadPoseOffset, m_HeadPoseArray, 0, BlendShapeUtils.PoseSize); 114 | Buffer.BlockCopy(buffer, offset + settings.CameraPoseOffset, m_CameraPoseArray, 0, BlendShapeUtils.PoseSize); 115 | BlendShapeUtils.ArrayToPose(m_HeadPoseArray, ref m_HeadPose); 116 | BlendShapeUtils.ArrayToPose(m_CameraPoseArray, ref m_CameraPose); 117 | } 118 | } 119 | 120 | public void ConnectDependencies() 121 | { 122 | m_Sources.UnionWith(GetComponentsInChildren()); 123 | foreach (var go in m_StreamSourceOverrides) 124 | { 125 | m_Sources.UnionWith(go.GetComponentsInChildren()); 126 | } 127 | 128 | foreach (var source in m_Sources) 129 | { 130 | ConnectInterfaces(source); 131 | if (source is NetworkStream) 132 | streamSource = source; 133 | } 134 | 135 | if (m_Character != null) 136 | { 137 | blendShapesController = m_BlendShapesControllerOverride != null 138 | ? m_BlendShapesControllerOverride 139 | : m_Character.GetComponentInChildren(); 140 | 141 | characterRigController = m_CharacterRigControllerOverride != null 142 | ? m_CharacterRigControllerOverride 143 | : m_Character.GetComponentInChildren(); 144 | 145 | headBone = m_HeadBoneOverride != null 146 | ? m_HeadBoneOverride 147 | : characterRigController != null 148 | ? characterRigController.headBone 149 | : null; 150 | } 151 | else 152 | { 153 | blendShapesController = m_BlendShapesControllerOverride; 154 | characterRigController = m_CharacterRigControllerOverride; 155 | headBone = m_HeadBoneOverride; 156 | } 157 | 158 | cameraTransform = m_CameraOverride == null ? Camera.main.transform : m_CameraOverride.transform; 159 | 160 | if (blendShapesController != null) 161 | ConnectInterfaces(blendShapesController); 162 | 163 | if (characterRigController != null) 164 | ConnectInterfaces(characterRigController); 165 | } 166 | 167 | void Awake() 168 | { 169 | Application.targetFrameRate = 60; 170 | 171 | if (headBone == null) 172 | { 173 | m_HeadPose = new Pose(Vector3.zero, Quaternion.identity); 174 | Debug.LogWarning("No Character head bone set. Using default pose."); 175 | } 176 | else 177 | { 178 | m_HeadPose = new Pose(headBone.position, headBone.rotation); 179 | } 180 | 181 | if (cameraTransform == null) 182 | { 183 | m_CameraPose = new Pose(Vector3.zero, Quaternion.identity); 184 | Debug.LogWarning("No Camera set. Using default pose."); 185 | } 186 | else 187 | { 188 | m_CameraPose = new Pose(cameraTransform.position, cameraTransform.rotation); 189 | } 190 | 191 | ConnectDependencies(); 192 | } 193 | 194 | void Update() 195 | { 196 | var headPosition = m_HeadPose.position; 197 | if (headPosition == m_LastHeadPosition) 198 | { 199 | m_TrackingLossCount++; 200 | if (!m_FaceActive && m_TrackingLossCount > m_TrackingLossPadding) 201 | trackingActive = false; 202 | else 203 | trackingActive = true; 204 | } 205 | else 206 | { 207 | m_TrackingLossCount = 0; 208 | } 209 | 210 | m_LastHeadPosition = headPosition; 211 | 212 | foreach (var source in m_Sources) 213 | { 214 | source.StreamSourceUpdate(); 215 | } 216 | } 217 | 218 | void ConnectInterfaces(object obj) 219 | { 220 | var usesStreamReader = obj as IUsesStreamReader; 221 | if (usesStreamReader != null) 222 | usesStreamReader.streamReader = this; 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /Runtime/StreamReader.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d4971bbbce29c747ad31c2747bcbc57 3 | timeCreated: 1527697132 4 | licenseType: Pro 5 | MonoImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | defaultReferences: [] 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/StreamSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Unity.Labs.FacialRemote 6 | { 7 | /// 8 | /// 9 | /// Holds the data needed to process facial data to and from a byte stream. 10 | /// This data needs to match on the server and client side. 11 | /// 12 | [Serializable] 13 | [CreateAssetMenu(fileName = "Stream Settings", menuName = "Facial Remote/Stream Settings")] 14 | public class StreamSettings : ScriptableObject, IStreamSettings 15 | { 16 | [SerializeField] 17 | [Tooltip("Error check byte value.")] 18 | byte m_ErrorCheck = 42; 19 | 20 | [SerializeField] 21 | [Tooltip("Size of blend shapes in the byte array.")] 22 | int m_BlendShapeSize; 23 | 24 | [SerializeField] 25 | [Tooltip("Size of frame number value in byte array.")] 26 | int m_FrameNumberSize; 27 | 28 | [SerializeField] 29 | [Tooltip("Size of frame time value in byte array.")] 30 | int m_FrameTimeSize; 31 | 32 | [SerializeField] 33 | [Tooltip("Location of head pose in byte array.")] 34 | int m_HeadPoseOffset; 35 | 36 | [SerializeField] 37 | [Tooltip("Location of camera pose in byte array.")] 38 | int m_CameraPoseOffset; 39 | 40 | [SerializeField] 41 | [Tooltip("Location of frame number value in byte array.")] 42 | int m_FrameNumberOffset; 43 | 44 | [SerializeField] 45 | [Tooltip("Location of frame time value in byte array.")] 46 | int m_FrameTimeOffset; 47 | 48 | [SerializeField] 49 | [Tooltip("Total size of buffer of byte array for single same of data.")] 50 | int m_BufferSize; 51 | 52 | [SerializeField] 53 | [Tooltip("String names of the blend shapes in the stream with their index in the array being their relative location.")] 54 | string[] m_Locations = { }; 55 | 56 | [SerializeField] 57 | [Tooltip("Rename mapping values to apply blend shape locations to a blend shape controller.")] 58 | Mapping[] m_Mappings = { }; 59 | 60 | public byte ErrorCheck { get { return m_ErrorCheck; } } 61 | public int BlendShapeSize { get { return m_BlendShapeSize; } } 62 | public int FrameNumberSize { get { return m_FrameNumberSize; } } 63 | public int FrameTimeSize { get { return m_FrameTimeSize; } } 64 | public int HeadPoseOffset { get { return m_HeadPoseOffset; } } 65 | public int CameraPoseOffset { get { return m_CameraPoseOffset; } } 66 | public int FrameNumberOffset { get { return m_FrameNumberOffset; } } 67 | public int FrameTimeOffset { get { return m_FrameTimeOffset; } } 68 | 69 | // ARKit 1.5 buffer layout 70 | // 0 - Error check 71 | // 1-204 - Blend Shapes 72 | // 205-232 - Head Pose 73 | // 233-260 - Camera Pose 74 | // 261-264 - Frame Number 75 | // 265-268 - Frame Time 76 | // 269 - Active state 77 | 78 | // ARKit 2.0 buffer layout 79 | // 0 - Error check 80 | // 1-208 - Blend Shapes 81 | // 209-236 - Head Pose 82 | // 237-264 - Camera Pose 83 | // 265-268 - Frame Number 84 | // 269-273 - Frame Time 85 | // 274 - Active state 86 | public int bufferSize { get { return m_BufferSize; } } 87 | 88 | public Mapping[] mappings { get { return m_Mappings; } } 89 | 90 | public string[] locations { get { return m_Locations; } } 91 | 92 | void OnValidate() 93 | { 94 | UpdateOffsets(); 95 | } 96 | 97 | void UpdateOffsets() 98 | { 99 | const int poseSize = BlendShapeUtils.PoseSize; 100 | var blendShapeCount = m_Locations.Length; 101 | m_BlendShapeSize = sizeof(float) * blendShapeCount; 102 | m_FrameNumberSize = sizeof(int); 103 | m_FrameTimeSize = sizeof(float); 104 | m_HeadPoseOffset = BlendShapeSize + 1; 105 | m_CameraPoseOffset = HeadPoseOffset + poseSize; 106 | m_FrameNumberOffset = CameraPoseOffset + poseSize; 107 | m_FrameTimeOffset = FrameNumberOffset + FrameNumberSize; 108 | 109 | // Error check + Blend Shapes + HeadPose + CameraPose + FrameNumber + FrameTime + Active 110 | m_BufferSize = 1 + BlendShapeSize + poseSize * 2 + FrameNumberSize + FrameTimeSize + 1; 111 | } 112 | 113 | void Reset() 114 | { 115 | var locationStrings = new List(); 116 | foreach (var location in BlendShapeUtils.Locations) 117 | { 118 | locationStrings.Add(location); 119 | } 120 | 121 | locationStrings.Sort(); 122 | m_Locations = locationStrings.ToArray(); 123 | UpdateOffsets(); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Runtime/StreamSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9873bf0085043ad8a2f13636d3b7fe5 3 | timeCreated: 1527740083 -------------------------------------------------------------------------------- /Runtime/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f9ef4a7e9361425a96da3b5700f58d9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Textures/Button.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:482a50213cc4171deb79a8fe644dd5854c46a45a435cf92dbf1975918c39c8ee 3 | size 4676 4 | -------------------------------------------------------------------------------- /Runtime/Textures/Button.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 196e978facf634d028164b806e15a43a 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: 1 36 | wrapV: 1 37 | wrapW: -1 38 | nPOTScale: 0 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 1 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 32, y: 31, z: 31, w: 32} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 1 51 | spriteTessellationDetail: -1 52 | textureType: 8 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | - serializedVersion: 2 71 | buildTarget: Standalone 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | androidETC2FallbackOverride: 0 81 | - serializedVersion: 2 82 | buildTarget: iPhone 83 | maxTextureSize: 2048 84 | resizeAlgorithm: 0 85 | textureFormat: -1 86 | textureCompression: 1 87 | compressionQuality: 50 88 | crunchedCompression: 0 89 | allowsAlphaSplitting: 0 90 | overridden: 0 91 | androidETC2FallbackOverride: 0 92 | spriteSheet: 93 | serializedVersion: 2 94 | sprites: [] 95 | outline: [] 96 | physicsShape: [] 97 | bones: [] 98 | spriteID: 906b26838479945e98199adbccddc92c 99 | vertices: [] 100 | indices: 101 | edges: [] 102 | weights: [] 103 | spritePackingTag: 104 | userData: 105 | assetBundleName: 106 | assetBundleVariant: 107 | -------------------------------------------------------------------------------- /Runtime/Textures/Button@2x.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f32c76e777fcb43574a74be30fca90093931a19c36d0bb49fce35b40f8c0ade8 3 | size 9687 4 | -------------------------------------------------------------------------------- /Runtime/Textures/Button@2x.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0989cdcee66b048b9ab0b46b8328c4b9 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: 1 36 | wrapV: 1 37 | wrapW: -1 38 | nPOTScale: 0 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 1 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 1 45 | spritePivot: {x: 0, y: 1} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 66, y: 65, z: 65, w: 66} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 1 51 | spriteTessellationDetail: -1 52 | textureType: 8 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | - serializedVersion: 2 71 | buildTarget: Standalone 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | androidETC2FallbackOverride: 0 81 | - serializedVersion: 2 82 | buildTarget: iPhone 83 | maxTextureSize: 2048 84 | resizeAlgorithm: 0 85 | textureFormat: -1 86 | textureCompression: 1 87 | compressionQuality: 50 88 | crunchedCompression: 0 89 | allowsAlphaSplitting: 0 90 | overridden: 0 91 | androidETC2FallbackOverride: 0 92 | spriteSheet: 93 | serializedVersion: 2 94 | sprites: [] 95 | outline: [] 96 | physicsShape: [] 97 | bones: [] 98 | spriteID: 84e5709c7b8b748a3a28ef23ca5ce88c 99 | vertices: [] 100 | indices: 101 | edges: [] 102 | weights: [] 103 | spritePackingTag: 104 | userData: 105 | assetBundleName: 106 | assetBundleVariant: 107 | -------------------------------------------------------------------------------- /Runtime/Textures/View_Finder_Corner.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9f9313d7cbc5178b63c93bd3ea86fff19089d15f40d6aa0e88167d6d185921d9 3 | size 1102 4 | -------------------------------------------------------------------------------- /Runtime/Textures/View_Finder_Corner.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fbc711ef5d8334b8b9df8aee709b203f 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: 1 36 | wrapV: 1 37 | wrapW: -1 38 | nPOTScale: 0 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 1 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 1 51 | spriteTessellationDetail: -1 52 | textureType: 8 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | - serializedVersion: 2 71 | buildTarget: Standalone 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | androidETC2FallbackOverride: 0 81 | - serializedVersion: 2 82 | buildTarget: iPhone 83 | maxTextureSize: 2048 84 | resizeAlgorithm: 0 85 | textureFormat: -1 86 | textureCompression: 1 87 | compressionQuality: 50 88 | crunchedCompression: 0 89 | allowsAlphaSplitting: 0 90 | overridden: 0 91 | androidETC2FallbackOverride: 0 92 | spriteSheet: 93 | serializedVersion: 2 94 | sprites: [] 95 | outline: [] 96 | physicsShape: [] 97 | bones: [] 98 | spriteID: 0bf812540292940919ff317bbbf1fa35 99 | vertices: [] 100 | indices: 101 | edges: [] 102 | weights: [] 103 | spritePackingTag: 104 | userData: 105 | assetBundleName: 106 | assetBundleVariant: 107 | -------------------------------------------------------------------------------- /Runtime/Textures/View_Finder_Corner@2x.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bb47e4358c791a2384701b0539d255991477a4ec5aceee156e5de065953aa036 3 | size 2525 4 | -------------------------------------------------------------------------------- /Runtime/Textures/View_Finder_Corner@2x.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc39f4de214134dd5b6ee3d5aa3e15c6 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 1 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapU: 1 36 | wrapV: 1 37 | wrapW: -1 38 | nPOTScale: 0 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 1 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 1 50 | alphaIsTransparency: 1 51 | spriteTessellationDetail: -1 52 | textureType: 8 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | - serializedVersion: 2 71 | buildTarget: Standalone 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | androidETC2FallbackOverride: 0 81 | - serializedVersion: 2 82 | buildTarget: iPhone 83 | maxTextureSize: 2048 84 | resizeAlgorithm: 0 85 | textureFormat: -1 86 | textureCompression: 1 87 | compressionQuality: 50 88 | crunchedCompression: 0 89 | allowsAlphaSplitting: 0 90 | overridden: 0 91 | androidETC2FallbackOverride: 0 92 | spriteSheet: 93 | serializedVersion: 2 94 | sprites: [] 95 | outline: [] 96 | physicsShape: [] 97 | bones: [] 98 | spriteID: 9fb4fc630dd52430fa7afae0365291eb 99 | vertices: [] 100 | indices: 101 | edges: [] 102 | weights: [] 103 | spritePackingTag: 104 | userData: 105 | assetBundleName: 106 | assetBundleVariant: 107 | -------------------------------------------------------------------------------- /Runtime/Unity.FacialARRemote.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Unity.FacialARRemote", 3 | "references": [ 4 | "Unity.TextMeshPro", 5 | "Unity.XR.ARKit.FaceTracking", 6 | "Unity.XR.ARFoundation", 7 | "Unity.XR.ARSubsystems" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [ 17 | { 18 | "name": "com.unity.xr.arkit-face-tracking", 19 | "expression": "1.0.7", 20 | "define": "INCLUDE_ARKIT_FACE_PLUGIN" 21 | }, 22 | { 23 | "name": "com.unity.xr.arfoundation", 24 | "expression": "2.1.8", 25 | "define": "INCLUDE_AR_FOUNDATION" 26 | } 27 | ], 28 | "noEngineReferences": false 29 | } -------------------------------------------------------------------------------- /Runtime/Unity.FacialARRemote.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec15f1858d67b432bbdf97e143371752 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Sloth Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7fdfa29288ea64979be8d4b44a641a36 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName":"Sloth Example", 3 | "description": "A simple face rig of a sloth with the ARKit blendshapes.", 4 | "createSeparatePackage": false 5 | } 6 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b678f623aa14a4f7797a6cf0036abe8e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Materials/ARKitFaceMesh.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ARKitFaceMesh 10 | m_Shader: {fileID: 4800000, guid: 811156b770cc047d896b5b19ebd9e9a2, type: 3} 11 | m_ShaderKeywords: _ALPHAPREMULTIPLY_ON 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 10, y: 10} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 10, y: 10} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 10 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.494 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 3 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _RimPower: 1.21 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 0 75 | m_Colors: 76 | - _Color: {r: 0.23540407, g: 0.40872183, b: 0.4339623, a: 0.6156863} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | - _RimColor: {r: 0.07413671, g: 0.8783532, b: 0.9245283, a: 0} 79 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Materials/ARKitFaceMesh.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8c90c443ee56462d8280d76f63d2922 3 | timeCreated: 1517432121 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 077b8cffba6db074bb5ed3b60be95039 3 | folderAsset: yes 4 | timeCreated: 1529018279 5 | licenseType: Pro 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Scenes/SlothBlendShapes.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 647c057ead5854246be7955fbc3022c7 3 | timeCreated: 1529018313 4 | licenseType: Pro 5 | DefaultImporter: 6 | externalObjects: {} 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Settings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fbfef9a5c91f71f48940bd438c4893d1 3 | folderAsset: yes 4 | timeCreated: 1529018065 5 | licenseType: Pro 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Settings/PlaybackData.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 0} 8 | m_GameObject: {fileID: 0} 9 | m_Enabled: 1 10 | m_EditorHideFlags: 0 11 | m_Script: {fileID: 11500000, guid: 21649ccc570324b479f22201a38e086a, type: 3} 12 | m_Name: PlaybackData 13 | m_EditorClassIdentifier: 14 | m_PlaybackBuffers: [] 15 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/Settings/PlaybackData.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6471208d98b8f5843bc5839ee125a490 3 | timeCreated: 1529018504 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | externalObjects: {} 7 | mainObjectFileID: 11400000 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dbd656aa75a1c664d8c595f1733a98aa 3 | folderAsset: yes 4 | timeCreated: 1510601314 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d1b714ad3b96fe41b9bf1113c0bdab8 3 | folderAsset: yes 4 | timeCreated: 1511933011 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Materials/sloth_all_1001_AlbedoTransparency.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: sloth_all_1001_AlbedoTransparency 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _METALLICGLOSSMAP _NORMALMAP 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 2800000, guid: 3452a0f43479da747bf187eee7f1f4f4, type: 3} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: cc53223aded01054aa49b50ed964879d, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 2800000, guid: 5c0bf29cbf5a1f749b392f3820d121c0, type: 3} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 1, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Materials/sloth_all_1001_AlbedoTransparency.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 39d1e996955b4b8479301256a1d9e1b7 3 | timeCreated: 1511933011 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Meshs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 121725edeea914c4eaab70d3459995d9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Meshs/sloth_head_blendshapes.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3781211db628f7d3ebc1c44c61d19d5cefd6b56744e7c5f56e82312c16bd9939 3 | size 643696 4 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Meshs/sloth_head_blendshapes.fbx.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af968d843fbb7064799877e138be8e80 3 | timeCreated: 1511933011 4 | licenseType: Pro 5 | ModelImporter: 6 | serializedVersion: 19 7 | fileIDToRecycleName: 8 | 100000: blendshapes3 9 | 100002: Sloth_Head2 10 | 100004: //RootNode 11 | 400000: blendshapes3 12 | 400002: Sloth_Head2 13 | 400004: //RootNode 14 | 4300000: Sloth_Head2 15 | 9500000: //RootNode 16 | 13700000: Sloth_Head2 17 | materials: 18 | importMaterials: 1 19 | materialName: 0 20 | materialSearch: 1 21 | animations: 22 | legacyGenerateAnimations: 4 23 | bakeSimulation: 0 24 | resampleCurves: 1 25 | optimizeGameObjects: 0 26 | motionNodeName: 27 | rigImportErrors: 28 | rigImportWarnings: 29 | animationImportErrors: 30 | animationImportWarnings: 31 | animationRetargetingWarnings: 32 | animationDoRetargetingWarnings: 0 33 | animationCompression: 1 34 | animationRotationError: 0.5 35 | animationPositionError: 0.5 36 | animationScaleError: 0.5 37 | animationWrapMode: 0 38 | extraExposedTransformPaths: [] 39 | clipAnimations: [] 40 | isReadable: 1 41 | meshes: 42 | lODScreenPercentages: [] 43 | globalScale: 10 44 | meshCompression: 0 45 | addColliders: 0 46 | importBlendShapes: 1 47 | swapUVChannels: 0 48 | generateSecondaryUV: 0 49 | useFileUnits: 1 50 | optimizeMeshForGPU: 1 51 | keepQuads: 0 52 | weldVertices: 1 53 | secondaryUVAngleDistortion: 8 54 | secondaryUVAreaDistortion: 15.000001 55 | secondaryUVHardAngle: 88 56 | secondaryUVPackMargin: 4 57 | useFileScale: 1 58 | tangentSpace: 59 | normalSmoothAngle: 60 60 | normalImportMode: 0 61 | tangentImportMode: 3 62 | importAnimation: 1 63 | copyAvatar: 0 64 | humanDescription: 65 | serializedVersion: 2 66 | human: [] 67 | skeleton: [] 68 | armTwist: 0.5 69 | foreArmTwist: 0.5 70 | upperLegTwist: 0.5 71 | legTwist: 0.5 72 | armStretch: 0.05 73 | legStretch: 0.05 74 | feetSpacing: 0 75 | rootMotionBoneName: 76 | rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1} 77 | hasTranslationDoF: 0 78 | hasExtraRoot: 0 79 | skeletonHasParents: 1 80 | lastHumanDescriptionAvatarSource: {instanceID: 0} 81 | animationType: 2 82 | humanoidOversampling: 1 83 | additionalBone: 0 84 | userData: 85 | assetBundleName: 86 | assetBundleVariant: 87 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aca95e8dd6a7bf64a9bb6b21b42a6069 3 | folderAsset: yes 4 | timeCreated: 1510204871 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_AlbedoTransparency.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b1f8162d454db2c7d3a5f6dd86095a5b8f1042b84afd33e19e702d5cd67f944b 3 | size 3935660 4 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_AlbedoTransparency.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cc53223aded01054aa49b50ed964879d 3 | timeCreated: 1510333546 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 4096 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 4096 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_MetallicSmoothness.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff0bb3d9dff2f217f6009e4d8173df04be267cad7793f1c2c00d4c1b412ec39c 3 | size 1002125 4 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_MetallicSmoothness.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c0bf29cbf5a1f749b392f3820d121c0 3 | timeCreated: 1510333569 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 4096 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 4096 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_Normal.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ebd437437c3201c7b8b0ce41a11301563fced2da46775a9b4de6b2490439e550 3 | size 2950896 4 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/Textures/sloth_all_1001_Normal.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3452a0f43479da747bf187eee7f1f4f4 3 | timeCreated: 1510333583 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 0 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 1 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 4096 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 4096 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Samples~/Sloth Example/SlothCharacter/sloth_head_blendshapes.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f52b9039400198449907ac105acc8616 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 100100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.unity.facial-ar-remote", 3 | "displayName": "Facial AR Remote", 4 | "version": "0.1.0-preview", 5 | "unity": "2019.3", 6 | "unityRelease": "0f6", 7 | "description": "Facial AR Remote for remote iteration on ARKit blendshapes", 8 | "dependencies": { 9 | "com.unity.textmeshpro": "2.0.1", 10 | "com.unity.xr.arfoundation": "2.1.8" 11 | }, 12 | "samples": [ 13 | { 14 | "displayName": "Sloth Example", 15 | "description": "A simple face rig of a sloth with the ARKit blendshapes.", 16 | "path": "Samples~/Sloth Example" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d56d8e181e1a1444cbf3e8dda05203c1 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------