private void Initialize() { #if UNITY_ANDROID && !UNITY_EDITOR string appId = OvrAvatarSettings.GearAppID; if (appId == "") { AvatarLogger.Log("No Gear VR App ID has been provided. Go to Oculus Avatar > Edit Configuration to supply one", OvrAvatarSettings.Instance); appId = "0"; } CAPI.ovrAvatar_InitializeAndroidUnity(appId); #else string appId = OvrAvatarSettings.AppID; if (appId == "") { AvatarLogger.Log("No Oculus Rift App ID has been provided. Go to Oculus Avatar > Edit Configuration to supply one", OvrAvatarSettings.Instance); appId = "0"; } CAPI.ovrAvatar_Initialize(appId); #endif specificationCallbacks = new Dictionary <UInt64, HashSet <specificationCallback> >(); assetLoadedCallbacks = new Dictionary <UInt64, HashSet <assetLoadedCallback> >(); combinedMeshLoadedCallbacks = new Dictionary <IntPtr, combinedMeshLoadedCallback>(); assetCache = new Dictionary <ulong, OvrAvatarAsset>(); }
private void LoadSubmeshes(IntPtr asset, IntPtr indexBufferPtr, ulong indexCount) { UInt32 subMeshCount = CAPI.ovrAvatarAsset_GetSubmeshCount(asset); AvatarLogger.Log("LoadSubmeshes: " + subMeshCount); Int16[] indices = new Int16[indexCount]; Marshal.Copy(indexBufferPtr, indices, 0, (int)indexCount); mesh.subMeshCount = (int)subMeshCount; uint accumedOffset = 0; for (UInt32 index = 0; index < subMeshCount; index++) { var submeshIndexCount = CAPI.ovrAvatarAsset_GetSubmeshLastIndex(asset, index); var currSpan = submeshIndexCount - accumedOffset; Int32[] triangles = new Int32[currSpan]; int triangleOffset = 0; for (ulong i = accumedOffset; i < submeshIndexCount; i += 3) { // NOTE: We are changing the order of each triangle to match unity expectations vs pipeline. triangles[triangleOffset + 2] = (Int32)indices[i]; triangles[triangleOffset + 1] = (Int32)indices[i + 1]; triangles[triangleOffset] = (Int32)indices[i + 2]; triangleOffset += 3; } accumedOffset += currSpan; mesh.SetIndices(triangles, MeshTopology.Triangles, (int)index); } }
private void InitializeCombinedMaterial(IntPtr renderPart, int lodIndex) { ovrAvatarPBSMaterialState[] materialStates = CAPI.ovrAvatar_GetBodyPBSMaterialStates(renderPart); if (materialStates.Length == (int)ovrAvatarBodyPartType.Count) { AvatarMaterialManager.CreateTextureArrays(); AvatarMaterialManager.LocalAvatarConfig = AvatarMaterialManager.DefaultAvatarConfig; var localProperties = AvatarMaterialManager.LocalAvatarConfig.ComponentMaterialProperties; AvatarLogger.Log("InitializeCombinedMaterial - Loading Material States"); for (int i = 0; i < materialStates.Length; i++) { localProperties[i].TypeIndex = (ovrAvatarBodyPartType)i; localProperties[i].Color = materialStates[i].albedoMultiplier; var diffuse = OvrAvatarComponent.GetLoadedTexture(materialStates[i].albedoTextureID); var normal = OvrAvatarComponent.GetLoadedTexture(materialStates[i].normalTextureID); var roughness = OvrAvatarComponent.GetLoadedTexture(materialStates[i].metallicnessTextureID); localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = diffuse == null ? AvatarMaterialManager.DiffuseFallbacks[lodIndex] : diffuse; localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = normal == null ? AvatarMaterialManager.NormalFallbacks[lodIndex] : normal; localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = roughness == null ? AvatarMaterialManager.DiffuseFallbacks[lodIndex] : roughness; AvatarLogger.Log(localProperties[i].TypeIndex.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Diffuse: " + materialStates[i].albedoTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Normal: " + materialStates[i].normalTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Metallic: " + materialStates[i].metallicnessTextureID); } if (EnableExpressive) { mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_IRIS_COLOR, ExpressiveParameters.irisColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_COLOR, ExpressiveParameters.lipColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_BROW_COLOR, ExpressiveParameters.browColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LASH_COLOR, ExpressiveParameters.lashColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_SCLERA_COLOR, ExpressiveParameters.scleraColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_GUM_COLOR, ExpressiveParameters.gumColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_TEETH_COLOR, ExpressiveParameters.teethColor); mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_SMOOTHNESS, ExpressiveParameters.lipSmoothness); } AvatarMaterialManager.ValidateTextures(); } }
private IEnumerator DeleteTextureSetCoroutine(TextureSet textureSetToDelete, int gameobjectID) { // Wait a conservative amount of time for gpu upload to finish. Unity 2017 doesn't support async GPU calls, // so this 10 second time is a very conservative delay for this process to occur, which should be <1 sec. yield return(new WaitForSeconds(GPU_TEXTURE_COPY_WAIT_TIME)); // Spin if an avatar is loading while (OvrAvatarSDKManager.Instance.IsAvatarLoading()) { yield return(null); } // The avatar's texture set is compared against all other loaded or loading avatar texture sets. foreach (var textureIdAndSingleMeshFlag in textureSetToDelete.TextureIDSingleMeshPair) { bool triggerDelete = !textureIdAndSingleMeshFlag.Value; if (triggerDelete) { foreach (KeyValuePair <int, TextureSet> textureSet in textureSets) { if (textureSet.Key == gameobjectID) { continue; } foreach (var comparisonTextureIDSingleMeshPair in textureSet.Value.TextureIDSingleMeshPair) { // Mark the texture as not deletable if it's present in another set and that set hasn't been processed // or that texture ID is marked as part of a single mesh component. if (comparisonTextureIDSingleMeshPair.Key == textureIdAndSingleMeshFlag.Key && (!textureSet.Value.IsProcessed || comparisonTextureIDSingleMeshPair.Value)) { triggerDelete = false; break; } } if (!triggerDelete) { break; } } } if (triggerDelete) { Texture2D textureToDelete = OvrAvatarComponent.GetLoadedTexture(textureIdAndSingleMeshFlag.Key); if (textureToDelete != null) { AvatarLogger.Log("Deleting texture " + textureIdAndSingleMeshFlag.Key); OvrAvatarSDKManager.Instance.DeleteAssetFromCache(textureIdAndSingleMeshFlag.Key); Destroy(textureToDelete); } } } textureSetToDelete.IsProcessed = true; textureSets.Remove(gameobjectID); }
public OvrAvatarAssetTexture(UInt64 _assetId, IntPtr asset) { assetID = _assetId; ovrAvatarTextureAssetData textureAssetData = CAPI.ovrAvatarAsset_GetTextureData(asset); TextureFormat format; IntPtr textureData = textureAssetData.textureData; int textureDataSize = (int)textureAssetData.textureDataSize; AvatarLogger.Log( "OvrAvatarAssetTexture - " + _assetId + ": " + textureAssetData.format.ToString() + " " + textureAssetData.sizeX + "x" + textureAssetData.sizeY); switch (textureAssetData.format) { case ovrAvatarTextureFormat.RGB24: format = TextureFormat.RGB24; break; case ovrAvatarTextureFormat.DXT1: format = TextureFormat.DXT1; break; case ovrAvatarTextureFormat.DXT5: format = TextureFormat.DXT5; break; case ovrAvatarTextureFormat.ASTC_RGB_6x6: format = TextureFormat.ASTC_6x6; textureData = new IntPtr(textureData.ToInt64() + ASTCHeaderSize); textureDataSize -= ASTCHeaderSize; break; case ovrAvatarTextureFormat.ASTC_RGB_6x6_MIPMAPS: format = TextureFormat.ASTC_6x6; break; default: throw new NotImplementedException( string.Format("Unsupported texture format {0}", textureAssetData.format.ToString())); } texture = new Texture2D( (int)textureAssetData.sizeX, (int)textureAssetData.sizeY, format, textureAssetData.mipCount > 1, QualitySettings.activeColorSpace == ColorSpace.Gamma ? false : true) { filterMode = FilterMode.Trilinear, anisoLevel = 4, }; texture.LoadRawTextureData(textureData, textureDataSize); texture.Apply(true, false); }
void Start() { #if !UNITY_ANDROID if (CombineMeshes) { CombineMeshes = false; AvatarLogger.Log("Combine Meshes Currently Only Supported On Android"); } #endif #if !UNITY_5_5_OR_NEWER if (CombineMeshes) { CombineMeshes = false; AvatarLogger.LogWarning("Unity Version too old to use Combined Mesh Shader, required 5.5.0+"); } #endif try { oculusUserIDInternal = UInt64.Parse(oculusUserID); } catch (Exception) { oculusUserIDInternal = 0; AvatarLogger.LogWarning("Invalid Oculus User ID Format"); } AvatarLogger.Log("Starting OvrAvatar " + gameObject.name); AvatarLogger.Log(AvatarLogger.Tab + "LOD: " + LevelOfDetail.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Combine Meshes: " + CombineMeshes); AvatarLogger.Log(AvatarLogger.Tab + "Force Mobile Textures: " + ForceMobileTextureFormat); AvatarLogger.Log(AvatarLogger.Tab + "Oculus User ID: " + oculusUserIDInternal); ShowLeftController(StartWithControllers); ShowRightController(StartWithControllers); OvrAvatarSDKManager.Instance.RequestAvatarSpecification( oculusUserIDInternal, this.AvatarSpecificationCallback, CombineMeshes, LevelOfDetail, ForceMobileTextureFormat, LookAndFeelVersion, FallbackLookAndFeelVersion); WaitingForCombinedMesh = CombineMeshes; Driver.Mode = UseSDKPackets ? OvrAvatarDriver.PacketMode.SDK : OvrAvatarDriver.PacketMode.Unity; }
public void BeginLoadingAsset( UInt64 assetId, ovrAvatarAssetLevelOfDetail lod, assetLoadedCallback callback) { HashSet<assetLoadedCallback> callbackSet; if (!assetLoadedCallbacks.TryGetValue(assetId, out callbackSet)) { callbackSet = new HashSet<assetLoadedCallback>(); assetLoadedCallbacks.Add(assetId, callbackSet); } AvatarLogger.Log("Loading Asset ID: " + assetId); CAPI.ovrAvatarAsset_BeginLoadingLOD(assetId, lod); callbackSet.Add(callback); }
private void ConfigureHelpers() { Transform head = transform.Find("body/body_renderPart_0/root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT/head_JNT"); if (head == null) { AvatarLogger.LogError("Avatar helper config failed. Cannot find head transform. All helpers spawning on root avatar transform"); head = transform; } if (MouthAnchor == null) { MouthAnchor = CreateHelperObject(head, MOUTH_HEAD_OFFSET, MOUTH_HELPER_NAME); } if (GetComponent <OvrAvatarRemoteDriver>() != null) { GazeTarget headTarget = head.gameObject.AddComponent <GazeTarget>(); headTarget.Type = ovrAvatarGazeTargetType.AvatarHead; AvatarLogger.Log("Added head as gaze target"); Transform hand = transform.Find("hand_left"); if (hand == null) { AvatarLogger.LogWarning("Gaze target helper config failed: Cannot find left hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added left hand as gaze target"); } hand = transform.Find("hand_right"); if (hand == null) { AvatarLogger.Log("Gaze target helper config failed: Cannot find right hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added right hand as gaze target"); } } }
internal void Initialize( IntPtr renderPart, ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRender, OvrAvatarMaterialManager materialManager, int thirdPersonLayer, int firstPersonLayer, int sortOrder, bool isCombinedMaterial, ovrAvatarAssetLevelOfDetail lod) { AvatarMaterialManager = materialManager; IsCombinedMaterial = isCombinedMaterial; mesh = CreateSkinnedMesh( skinnedMeshRender.meshAssetID, skinnedMeshRender.visibilityMask, thirdPersonLayer, firstPersonLayer, sortOrder); #if UNITY_ANDROID var singleComponentShader = "OvrAvatar/Avatar_Mobile_SingleComponent"; #else var singleComponentShader = "OvrAvatar/Avatar_PC_SingleComponent"; #endif var shader = IsCombinedMaterial ? Shader.Find("OvrAvatar/Avatar_Mobile_CombinedMesh") : Shader.Find(singleComponentShader); AvatarLogger.Log("Shader is: " + shader.name); mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader); mesh.sharedMaterial.renderQueue = OvrAvatarMaterialManager.RENDER_QUEUE; bones = mesh.bones; if (IsCombinedMaterial) { AvatarMaterialManager.SetRenderer(mesh); InitializeCombinedMaterial(renderPart, (int)lod - 1); AvatarMaterialManager.OnCombinedMeshReady(); } }
private void InitializeCombinedMaterial(IntPtr renderPart, int lodIndex) { ovrAvatarPBSMaterialState[] materialStates = CAPI.ovrAvatar_GetBodyPBSMaterialStates(renderPart); if (materialStates.Length == (int)ovrAvatarBodyPartType.Count) { AvatarMaterialManager.CreateTextureArrays(); AvatarMaterialManager.LocalAvatarConfig = AvatarMaterialManager.DefaultAvatarConfig; var localProperties = AvatarMaterialManager.LocalAvatarConfig.ComponentMaterialProperties; AvatarLogger.Log("InitializeCombinedMaterial - Loading Material States"); for (int i = 0; i < materialStates.Length; i++) { localProperties[i].TypeIndex = (ovrAvatarBodyPartType)i; localProperties[i].Color = materialStates[i].albedoMultiplier; var diffuse = OvrAvatarComponent.GetLoadedTexture(materialStates[i].albedoTextureID); var normal = OvrAvatarComponent.GetLoadedTexture(materialStates[i].normalTextureID); var roughness = OvrAvatarComponent.GetLoadedTexture(materialStates[i].metallicnessTextureID); localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = diffuse == null ? AvatarMaterialManager.DiffuseFallbacks[lodIndex] : diffuse; localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = normal == null ? AvatarMaterialManager.NormalFallbacks[lodIndex] : normal; localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = roughness == null ? AvatarMaterialManager.DiffuseFallbacks[lodIndex] : roughness; AvatarLogger.Log(localProperties[i].TypeIndex.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Diffuse: " + materialStates[i].albedoTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Normal: " + materialStates[i].normalTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Metallic: " + materialStates[i].metallicnessTextureID); } AvatarMaterialManager.ValidateTextures(); } #if UNITY_EDITOR mesh.sharedMaterial.EnableKeyword("FIX_NORMAL_ON"); #endif }
private void Initialize() { string appId = GetAppId(); if (appId == "") { AvatarLogger.Log("No Oculus App ID has been provided for target platform. " + "Go to Oculus Avatar > Edit Configuration to supply one", OvrAvatarSettings.Instance); appId = "0"; } #if UNITY_ANDROID && !UNITY_EDITOR CAPI.ovrAvatar_InitializeAndroidUnity(appId); #else CAPI.ovrAvatar_Initialize(appId); CAPI.SendEvent("initialize", appId); #endif specificationCallbacks = new Dictionary <UInt64, HashSet <specificationCallback> >(); assetLoadedCallbacks = new Dictionary <UInt64, HashSet <assetLoadedCallback> >(); combinedMeshLoadedCallbacks = new Dictionary <IntPtr, combinedMeshLoadedCallback>(); assetCache = new Dictionary <ulong, OvrAvatarAsset>(); }
private bool Initialize() { CAPI.Initialize(); string appId = GetAppId(); if (appId == "") { AvatarLogger.LogError("No Oculus App ID has been provided for target platform. " + "Go to Oculus Avatar > Edit Configuration to supply one", OvrAvatarSettings.Instance); appId = "0"; return(false); } #if UNITY_ANDROID && !UNITY_EDITOR #if AVATAR_XPLAT CAPI.ovrAvatar_Initialize(appId); #else CAPI.ovrAvatar_InitializeAndroidUnity(appId); #endif #else CAPI.ovrAvatar_Initialize(appId); CAPI.SendEvent("initialize", appId); #endif specificationCallbacks = new Dictionary <UInt64, HashSet <specificationCallback> >(); assetLoadedCallbacks = new Dictionary <UInt64, HashSet <assetLoadedCallback> >(); combinedMeshLoadedCallbacks = new Dictionary <IntPtr, combinedMeshLoadedCallback>(); assetCache = new Dictionary <ulong, OvrAvatarAsset>(); avatarSpecificationQueue = new Queue <AvatarSpecRequestParams>(); loadingAvatars = new List <int>(); CAPI.ovrAvatar_SetLoggingLevel(LoggingLevel); CAPI.ovrAvatar_RegisterLoggingCallback(CAPI.LoggingCallback); #if AVATAR_DEBUG CAPI.ovrAvatar_SetDebugDrawContext((uint)debugContext); #endif return(true); }
private void LoadBlendShapes(IntPtr asset, long vertexCount) { UInt32 blendShapeCount = CAPI.ovrAvatarAsset_GetMeshBlendShapeCount(asset); IntPtr blendShapeVerts = CAPI.ovrAvatarAsset_GetMeshBlendShapeVertices(asset); AvatarLogger.Log("LoadBlendShapes: " + blendShapeCount); if (blendShapeVerts != IntPtr.Zero) { long offset = 0; long blendVertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarBlendVertex)); long blendVertexBufferStart = blendShapeVerts.ToInt64(); for (UInt32 blendIndex = 0; blendIndex < blendShapeCount; blendIndex++) { Vector3[] blendVerts = new Vector3[vertexCount]; Vector3[] blendNormals = new Vector3[vertexCount]; Vector3[] blendTangents = new Vector3[vertexCount]; for (long i = 0; i < vertexCount; i++) { ovrAvatarBlendVertex vertex = (ovrAvatarBlendVertex)Marshal.PtrToStructure(new IntPtr(blendVertexBufferStart + offset), typeof(ovrAvatarBlendVertex)); blendVerts[i] = new Vector3(vertex.x, vertex.y, -vertex.z); blendNormals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); blendTangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz); offset += blendVertexSize; } IntPtr namePtr = CAPI.ovrAvatarAsset_GetMeshBlendShapeName(asset, blendIndex); string name = Marshal.PtrToStringAnsi(namePtr); const float frameWeight = 100f; mesh.AddBlendShapeFrame(name, frameWeight, blendVerts, blendNormals, blendTangents); } } }
// Request an avatar specification to be loaded by adding to the queue. // Requests are dispatched in Update(). public void RequestAvatarSpecification(AvatarSpecRequestParams avatarSpecRequest) { avatarSpecificationQueue.Enqueue(avatarSpecRequest); AvatarLogger.Log("Avatar spec request queued: " + avatarSpecRequest._userId.ToString()); }
void Update() { if (Instance == null) { return; } #if AVATAR_DEBUG // Call before ovrAvatarMessage_Pop which flushes the state CAPI.ovrAvatar_DrawDebugLines(); #endif // Dispatch waiting avatar spec request if (avatarSpecificationQueue.Count > 0 && (avatarSpecRequestAvailable || Time.time - lastDispatchedAvatarSpecRequestTime >= AVATAR_SPEC_REQUEST_TIMEOUT)) { avatarSpecRequestAvailable = false; AvatarSpecRequestParams avatarSpec = avatarSpecificationQueue.Dequeue(); DispatchAvatarSpecificationRequest(avatarSpec); lastDispatchedAvatarSpecRequestTime = Time.time; AvatarLogger.Log("Avatar spec request dispatched: " + avatarSpec._userId); } IntPtr message = CAPI.ovrAvatarMessage_Pop(); if (message == IntPtr.Zero) { return; } ovrAvatarMessageType messageType = CAPI.ovrAvatarMessage_GetType(message); switch (messageType) { case ovrAvatarMessageType.AssetLoaded: { ovrAvatarMessage_AssetLoaded assetMessage = CAPI.ovrAvatarMessage_GetAssetLoaded(message); IntPtr asset = assetMessage.asset; UInt64 assetID = assetMessage.assetID; ovrAvatarAssetType assetType = CAPI.ovrAvatarAsset_GetType(asset); OvrAvatarAsset assetData = null; IntPtr avatarOwner = IntPtr.Zero; switch (assetType) { case ovrAvatarAssetType.Mesh: assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.Mesh); break; case ovrAvatarAssetType.Texture: assetData = new OvrAvatarAssetTexture(assetID, asset); break; case ovrAvatarAssetType.Material: assetData = new OvrAvatarAssetMaterial(assetID, asset); break; case ovrAvatarAssetType.CombinedMesh: avatarOwner = CAPI.ovrAvatarAsset_GetAvatar(asset); assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.CombinedMesh); break; case ovrAvatarAssetType.FailedLoad: AvatarLogger.LogWarning("Asset failed to load from SDK " + assetID); break; default: throw new NotImplementedException(string.Format("Unsupported asset type format {0}", assetType.ToString())); } HashSet <assetLoadedCallback> callbackSet; if (assetType == ovrAvatarAssetType.CombinedMesh) { if (!assetCache.ContainsKey(assetID)) { assetCache.Add(assetID, assetData); } combinedMeshLoadedCallback callback; if (combinedMeshLoadedCallbacks.TryGetValue(avatarOwner, out callback)) { callback(asset); combinedMeshLoadedCallbacks.Remove(avatarOwner); } else { AvatarLogger.LogWarning("Loaded a combined mesh with no owner: " + assetMessage.assetID); } } else { if (assetData != null && assetLoadedCallbacks.TryGetValue(assetMessage.assetID, out callbackSet)) { assetCache.Add(assetID, assetData); foreach (var callback in callbackSet) { callback(assetData); } assetLoadedCallbacks.Remove(assetMessage.assetID); } } break; } case ovrAvatarMessageType.AvatarSpecification: { avatarSpecRequestAvailable = true; ovrAvatarMessage_AvatarSpecification spec = CAPI.ovrAvatarMessage_GetAvatarSpecification(message); HashSet <specificationCallback> callbackSet; if (specificationCallbacks.TryGetValue(spec.oculusUserID, out callbackSet)) { foreach (var callback in callbackSet) { callback(spec.avatarSpec); } specificationCallbacks.Remove(spec.oculusUserID); } else { AvatarLogger.LogWarning("Error, got an avatar specification callback from a user id we don't have a record for: " + spec.oculusUserID); } break; } default: throw new NotImplementedException("Unhandled ovrAvatarMessageType: " + messageType); } CAPI.ovrAvatarMessage_Free(message); }
private void InitializeCombinedMaterial(IntPtr renderPart, int lodIndex) { ovrAvatarPBSMaterialState[] materialStates = CAPI.ovrAvatar_GetBodyPBSMaterialStates(renderPart); if (materialStates.Length == (int)ovrAvatarBodyPartType.Count) { avatarMaterialManager.CreateTextureArrays(); var localProperties = avatarMaterialManager.LocalAvatarConfig.ComponentMaterialProperties; AvatarLogger.Log("InitializeCombinedMaterial - Loading Material States"); for (int i = 0; i < materialStates.Length; i++) { localProperties[i].TypeIndex = (ovrAvatarBodyPartType)i; localProperties[i].Color = materialStates[i].albedoMultiplier; localProperties[i].DiffuseIntensity = OvrAvatarMaterialManager.DiffuseIntensities[i]; localProperties[i].RimIntensity = OvrAvatarMaterialManager.RimIntensities[i]; localProperties[i].ReflectionIntensity = OvrAvatarMaterialManager.ReflectionIntensities[i]; var diffuse = OvrAvatarComponent.GetLoadedTexture(materialStates[i].albedoTextureID); var normal = OvrAvatarComponent.GetLoadedTexture(materialStates[i].normalTextureID); var roughness = OvrAvatarComponent.GetLoadedTexture(materialStates[i].metallicnessTextureID); if (diffuse != null) { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = diffuse; avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].albedoTextureID, false); } else { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; } localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures].anisoLevel = 4; if (normal != null) { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = normal; avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].normalTextureID, false); } else { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].Normal; } localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps].anisoLevel = 4; if (roughness != null) { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = roughness; avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].metallicnessTextureID, false); } else { localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; } localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps].anisoLevel = 16; AvatarLogger.Log(localProperties[i].TypeIndex.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Diffuse: " + materialStates[i].albedoTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Normal: " + materialStates[i].normalTextureID); AvatarLogger.Log(AvatarLogger.Tab + "Metallic: " + materialStates[i].metallicnessTextureID); } if (EnableExpressive) { mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_IRIS_COLOR, ExpressiveParameters.irisColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_COLOR, ExpressiveParameters.lipColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_BROW_COLOR, ExpressiveParameters.browColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LASH_COLOR, ExpressiveParameters.lashColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_SCLERA_COLOR, ExpressiveParameters.scleraColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_GUM_COLOR, ExpressiveParameters.gumColor); mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_TEETH_COLOR, ExpressiveParameters.teethColor); mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_SMOOTHNESS, ExpressiveParameters.lipSmoothness); } avatarMaterialManager.ValidateTextures(); } }
internal void Initialize( IntPtr renderPart, ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRender, OvrAvatarMaterialManager materialManager, int thirdPersonLayer, int firstPersonLayer, bool combinedMesh, ovrAvatarAssetLevelOfDetail lod, bool assignExpressiveParams, OvrAvatar avatar, bool isControllerModel) { avatarMaterialManager = materialManager; isCombinedMaterial = combinedMesh; mesh = CreateSkinnedMesh( skinnedMeshRender.meshAssetID, skinnedMeshRender.visibilityMask, thirdPersonLayer, firstPersonLayer); EnableExpressive = assignExpressiveParams; #if UNITY_ANDROID var singleComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_VertFrag_SingleComponent : avatar.Skinshaded_VertFrag_SingleComponent; #else var singleComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_SurfaceShader_SingleComponent : avatar.Skinshaded_SurfaceShader_SingleComponent; #endif var combinedComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_VertFrag_CombinedMesh : avatar.Skinshaded_VertFrag_CombinedMesh; var mainShader = isCombinedMaterial ? combinedComponentShader : singleComponentShader; if (isControllerModel) { mainShader = avatar.ControllerShader; } AvatarLogger.Log("OvrAvatarSkinnedMeshPBSV2RenderComponent Shader is: " + mainShader != null ? mainShader.name : "null"); if (EnableExpressive) { ExpressiveParameters = CAPI.ovrAvatar_GetExpressiveParameters(avatar.sdkAvatar); var eyeShader = avatar.EyeLens; Material[] matArray = new Material[2]; matArray[0] = CreateAvatarMaterial(gameObject.name + MAIN_MATERIAL_NAME, mainShader); matArray[1] = CreateAvatarMaterial(gameObject.name + EYE_MATERIAL_NAME, eyeShader); if (avatar.UseTransparentRenderQueue) { SetMaterialTransparent(matArray[0]); } else { SetMaterialOpaque(matArray[0]); } // Eye lens shader queue is transparent and set from shader matArray[1].renderQueue = -1; mesh.materials = matArray; } else { mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + DEFAULT_MATERIAL_NAME, mainShader); if (avatar.UseTransparentRenderQueue && !isControllerModel) { SetMaterialTransparent(mesh.sharedMaterial); } else { SetMaterialOpaque(mesh.sharedMaterial); } } bones = mesh.bones; if (isCombinedMaterial) { avatarMaterialManager.SetRenderer(mesh); InitializeCombinedMaterial(renderPart, (int)lod); avatarMaterialManager.OnCombinedMeshReady(); } blendShapeParams = new ovrAvatarBlendShapeParams(); blendShapeParams.blendShapeParamCount = 0; blendShapeParams.blendShapeParams = new float[64]; blendShapeCount = mesh.sharedMesh.blendShapeCount; }
public OvrAvatarAssetMesh(UInt64 _assetId, IntPtr asset, ovrAvatarAssetType meshType) { assetID = _assetId; mesh = new Mesh(); mesh.name = "Procedural Geometry for asset " + _assetId; SetSkinnedBindPose(asset, meshType); long vertexCount = 0; IntPtr vertexBuffer = IntPtr.Zero; uint indexCount = 0; IntPtr indexBuffer = IntPtr.Zero; GetVertexAndIndexData(asset, meshType, out vertexCount, out vertexBuffer, out indexCount, out indexBuffer); AvatarLogger.Log("OvrAvatarAssetMesh: " + _assetId + " " + meshType.ToString() + " VertexCount:" + vertexCount); Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; Vector2[] uv = new Vector2[vertexCount]; Color[] colors = new Color[vertexCount]; BoneWeight[] boneWeights = new BoneWeight[vertexCount]; long vertexBufferStart = vertexBuffer.ToInt64(); // We have different underlying vertex types to unpack, so switch on mesh type. switch (meshType) { case ovrAvatarAssetType.Mesh: { long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertex)); for (long i = 0; i < vertexCount; i++) { long offset = vertexSize * i; ovrAvatarMeshVertex vertex = (ovrAvatarMeshVertex)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertex)); vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); uv[i] = new Vector2(vertex.u, vertex.v); colors[i] = new Color(0, 0, 0, 1); boneWeights[i].boneIndex0 = vertex.blendIndices[0]; boneWeights[i].boneIndex1 = vertex.blendIndices[1]; boneWeights[i].boneIndex2 = vertex.blendIndices[2]; boneWeights[i].boneIndex3 = vertex.blendIndices[3]; boneWeights[i].weight0 = vertex.blendWeights[0]; boneWeights[i].weight1 = vertex.blendWeights[1]; boneWeights[i].weight2 = vertex.blendWeights[2]; boneWeights[i].weight3 = vertex.blendWeights[3]; } } break; case ovrAvatarAssetType.CombinedMesh: { long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertexV2)); for (long i = 0; i < vertexCount; i++) { long offset = vertexSize * i; ovrAvatarMeshVertexV2 vertex = (ovrAvatarMeshVertexV2)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertexV2)); vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); uv[i] = new Vector2(vertex.u, vertex.v); colors[i] = new Color(vertex.r, vertex.g, vertex.b, vertex.a); boneWeights[i].boneIndex0 = vertex.blendIndices[0]; boneWeights[i].boneIndex1 = vertex.blendIndices[1]; boneWeights[i].boneIndex2 = vertex.blendIndices[2]; boneWeights[i].boneIndex3 = vertex.blendIndices[3]; boneWeights[i].weight0 = vertex.blendWeights[0]; boneWeights[i].weight1 = vertex.blendWeights[1]; boneWeights[i].weight2 = vertex.blendWeights[2]; boneWeights[i].weight3 = vertex.blendWeights[3]; } } break; default: throw new Exception("Bad Mesh Asset Type"); } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.tangents = tangents; mesh.boneWeights = boneWeights; mesh.colors = colors; LoadBlendShapes(asset, vertexCount); LoadSubmeshes(asset, indexBuffer, indexCount); UInt32 jointCount = skinnedBindPose.jointCount; jointNames = new string[jointCount]; for (UInt32 i = 0; i < jointCount; i++) { jointNames[i] = Marshal.PtrToStringAnsi(skinnedBindPose.jointNames[i]); } }
// Update is called once per frame void Update() { IntPtr message = CAPI.ovrAvatarMessage_Pop(); if (message == IntPtr.Zero) { return; } ovrAvatarMessageType messageType = CAPI.ovrAvatarMessage_GetType(message); switch (messageType) { case ovrAvatarMessageType.AssetLoaded: { ovrAvatarMessage_AssetLoaded assetMessage = CAPI.ovrAvatarMessage_GetAssetLoaded(message); IntPtr asset = assetMessage.asset; UInt64 assetID = assetMessage.assetID; ovrAvatarAssetType assetType = CAPI.ovrAvatarAsset_GetType(asset); OvrAvatarAsset assetData; IntPtr avatarOwner = IntPtr.Zero; switch (assetType) { case ovrAvatarAssetType.Mesh: assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.Mesh); break; case ovrAvatarAssetType.Texture: assetData = new OvrAvatarAssetTexture(assetID, asset); break; case ovrAvatarAssetType.Material: assetData = new OvrAvatarAssetMaterial(assetID, asset); break; case ovrAvatarAssetType.CombinedMesh: avatarOwner = CAPI.ovrAvatarAsset_GetAvatar(asset); assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.CombinedMesh); break; default: throw new NotImplementedException(string.Format("Unsupported asset type format {0}", assetType.ToString())); } HashSet <assetLoadedCallback> callbackSet; if (assetType == ovrAvatarAssetType.CombinedMesh) { if (!assetCache.ContainsKey(assetID)) { assetCache.Add(assetID, assetData); } combinedMeshLoadedCallback callback; if (combinedMeshLoadedCallbacks.TryGetValue(avatarOwner, out callback)) { callback(asset); combinedMeshLoadedCallbacks.Remove(avatarOwner); } else { AvatarLogger.LogWarning("Loaded a combined mesh with no owner: " + assetMessage.assetID); } } else { if (assetLoadedCallbacks.TryGetValue(assetMessage.assetID, out callbackSet)) { assetCache.Add(assetID, assetData); foreach (var callback in callbackSet) { callback(assetData); } assetLoadedCallbacks.Remove(assetMessage.assetID); } } break; } case ovrAvatarMessageType.AvatarSpecification: { ovrAvatarMessage_AvatarSpecification spec = CAPI.ovrAvatarMessage_GetAvatarSpecification(message); HashSet <specificationCallback> callbackSet; if (specificationCallbacks.TryGetValue(spec.oculusUserID, out callbackSet)) { foreach (var callback in callbackSet) { callback(spec.avatarSpec); } specificationCallbacks.Remove(spec.oculusUserID); } else { AvatarLogger.LogWarning("Error, got an avatar specification callback from a user id we don't have a record for: " + spec.oculusUserID); } break; } default: throw new NotImplementedException("Unhandled ovrAvatarMessageType: " + messageType); } CAPI.ovrAvatarMessage_Free(message); }
internal void Initialize( IntPtr renderPart, ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRender, OvrAvatarMaterialManager materialManager, int thirdPersonLayer, int firstPersonLayer, int sortOrder, bool isCombinedMaterial, ovrAvatarAssetLevelOfDetail lod, bool assignExpressiveParams, OvrAvatar avatar, bool isControllerModel) { AvatarMaterialManager = materialManager; IsCombinedMaterial = isCombinedMaterial; mesh = CreateSkinnedMesh( skinnedMeshRender.meshAssetID, skinnedMeshRender.visibilityMask, thirdPersonLayer, firstPersonLayer, sortOrder); EnableExpressive = assignExpressiveParams; #if UNITY_ANDROID var singleComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_VertFrag_SingleComponent : avatar.Skinshaded_VertFrag_SingleComponent; #else var singleComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_SurfaceShader_SingleComponent : avatar.Skinshaded_SurfaceShader_SingleComponent; #endif var combinedComponentShader = EnableExpressive ? avatar.Skinshaded_Expressive_VertFrag_CombinedMesh : avatar.Skinshaded_VertFrag_CombinedMesh; var mainShader = IsCombinedMaterial ? combinedComponentShader : singleComponentShader; if (isControllerModel) { mainShader = Shader.Find("OvrAvatar/AvatarPBRV2Simple"); } AvatarLogger.Log("OvrAvatarSkinnedMeshPBSV2RenderComponent Shader is: " + mainShader != null ? mainShader.name : "null"); if (EnableExpressive) { ExpressiveParameters = CAPI.ovrAvatar_GetExpressiveParameters(avatar.sdkAvatar); var eyeShader = avatar.EyeLens; Material[] matArray = new Material[2]; matArray[0] = CreateAvatarMaterial(gameObject.name + MAIN_MATERIAL_NAME, mainShader); matArray[1] = CreateAvatarMaterial(gameObject.name + EYE_MATERIAL_NAME, eyeShader); if (avatar.UseTransparentRenderQueue) { // Initialize shader to use transparent render queue with alpha blending matArray[0].SetOverrideTag("RenderType", "Transparent"); matArray[0].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); matArray[0].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); matArray[0].EnableKeyword("_ALPHATEST_ON"); matArray[0].EnableKeyword("_ALPHABLEND_ON"); matArray[0].EnableKeyword("_ALPHAPREMULTIPLY_ON"); matArray[0].renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; } else { // Initialize shader to use geometry render queue with no blending matArray[0].SetOverrideTag("RenderType", "Opaque"); matArray[0].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); matArray[0].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); matArray[0].DisableKeyword("_ALPHATEST_ON"); matArray[0].DisableKeyword("_ALPHABLEND_ON"); matArray[0].DisableKeyword("_ALPHAPREMULTIPLY_ON"); matArray[0].renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; } // Eye lens shader queue is transparent and set from shader matArray[1].renderQueue = -1; mesh.materials = matArray; } else { mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + DEFAULT_MATERIAL_NAME, mainShader); if (avatar.UseTransparentRenderQueue && !isControllerModel) { // Initialize shader to use transparent render queue with alpha blending mesh.sharedMaterial.SetOverrideTag("RenderType", "Transparent"); mesh.sharedMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); mesh.sharedMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); mesh.sharedMaterial.EnableKeyword("_ALPHATEST_ON"); mesh.sharedMaterial.EnableKeyword("_ALPHABLEND_ON"); mesh.sharedMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON"); mesh.sharedMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; } else { // Initialize shader to use geometry render queue with no blending mesh.sharedMaterial.SetOverrideTag("RenderType", "Opaque"); mesh.sharedMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); mesh.sharedMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); mesh.sharedMaterial.DisableKeyword("_ALPHATEST_ON"); mesh.sharedMaterial.DisableKeyword("_ALPHABLEND_ON"); mesh.sharedMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mesh.sharedMaterial.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; } } bones = mesh.bones; if (IsCombinedMaterial) { AvatarMaterialManager.SetRenderer(mesh); InitializeCombinedMaterial(renderPart, (int)lod - 1); AvatarMaterialManager.OnCombinedMeshReady(); } }
void Start() { if (OvrAvatarSDKManager.Instance == null) { return; } #if !UNITY_ANDROID if (CombineMeshes) { CombineMeshes = false; AvatarLogger.Log("Combined Meshes currently only supported on mobile"); } #endif #if !UNITY_5_5_OR_NEWER if (CombineMeshes) { CombineMeshes = false; AvatarLogger.LogWarning("Combined Meshes requires Unity 5.5.0+"); } #endif materialManager = gameObject.AddComponent <OvrAvatarMaterialManager>(); try { oculusUserIDInternal = UInt64.Parse(oculusUserID); } catch (Exception) { oculusUserIDInternal = 0; AvatarLogger.LogWarning("Invalid Oculus User ID Format"); } // If no oculus ID is supplied then turn off combine meshes to prevent the texture arrays // being populated by invalid textures. if (oculusUserIDInternal == 0) { AvatarLogger.LogWarning("Oculus User ID set to 0. Provide actual user ID: " + gameObject.name); CombineMeshes = false; } AvatarLogger.Log("Starting OvrAvatar " + gameObject.name); AvatarLogger.Log(AvatarLogger.Tab + "LOD: " + LevelOfDetail.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Combine Meshes: " + CombineMeshes); AvatarLogger.Log(AvatarLogger.Tab + "Force Mobile Textures: " + USE_MOBILE_TEXTURE_FORMAT); AvatarLogger.Log(AvatarLogger.Tab + "Oculus User ID: " + oculusUserIDInternal); Capabilities = 0; bool is3Dof = false; var headsetType = OVRPlugin.GetSystemHeadsetType(); switch (headsetType) { case OVRPlugin.SystemHeadset.GearVR_R320: case OVRPlugin.SystemHeadset.GearVR_R321: case OVRPlugin.SystemHeadset.GearVR_R322: case OVRPlugin.SystemHeadset.GearVR_R323: case OVRPlugin.SystemHeadset.GearVR_R324: case OVRPlugin.SystemHeadset.GearVR_R325: case OVRPlugin.SystemHeadset.Oculus_Go: is3Dof = true; break; case OVRPlugin.SystemHeadset.Oculus_Quest: case OVRPlugin.SystemHeadset.Rift_S: case OVRPlugin.SystemHeadset.Rift_DK1: case OVRPlugin.SystemHeadset.Rift_DK2: case OVRPlugin.SystemHeadset.Rift_CV1: default: break; } // The SDK 3 DOF Arm Model requires the body skeleton to pose itself. It will crash without it // The likely use case here is trying to have an invisible body. // T45010595 if (is3Dof && !EnableBody) { AvatarLogger.Log("Forcing the Body component for 3Dof hand tracking, and setting the visibility to 1st person"); EnableBody = true; ShowFirstPerson = true; ShowThirdPerson = false; } if (EnableBody) { Capabilities |= ovrAvatarCapabilities.Body; } if (EnableHands) { Capabilities |= ovrAvatarCapabilities.Hands; } if (EnableBase && EnableBody) { Capabilities |= ovrAvatarCapabilities.Base; } if (EnableExpressive) { Capabilities |= ovrAvatarCapabilities.Expressive; } // Enable body tilt on 6dof devices if (OVRPlugin.positionSupported) { Capabilities |= ovrAvatarCapabilities.BodyTilt; } ShowLeftController(StartWithControllers); ShowRightController(StartWithControllers); OvrAvatarSDKManager.AvatarSpecRequestParams avatarSpecRequest = new OvrAvatarSDKManager.AvatarSpecRequestParams( oculusUserIDInternal, this.AvatarSpecificationCallback, CombineMeshes, LevelOfDetail, USE_MOBILE_TEXTURE_FORMAT, LookAndFeelVersion, FallbackLookAndFeelVersion, EnableExpressive); OvrAvatarSDKManager.Instance.RequestAvatarSpecification(avatarSpecRequest); OvrAvatarSDKManager.Instance.AddLoadingAvatar(GetInstanceID()); waitingForCombinedMesh = CombineMeshes; if (Driver != null) { Driver.Mode = UseSDKPackets ? OvrAvatarDriver.PacketMode.SDK : OvrAvatarDriver.PacketMode.Unity; } }
private void ConfigureHelpers() { Transform head = transform.Find("body/body_renderPart_0/root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT/head_JNT"); if (head == null) { AvatarLogger.LogError("Avatar helper config failed. Cannot find head transform. All helpers spawning on root avatar transform"); head = transform; } if (MouthAnchor == null) { MouthAnchor = CreateHelperObject(head, MOUTH_HEAD_OFFSET, MOUTH_HELPER_NAME); } if (GetComponent <OvrAvatarLocalDriver>() != null) { if (audioSource == null) { audioSource = MouthAnchor.gameObject.AddComponent <AudioSource>(); } spatializedSource = MouthAnchor.GetComponent <ONSPAudioSource>(); if (spatializedSource == null) { spatializedSource = MouthAnchor.gameObject.AddComponent <ONSPAudioSource>(); } spatializedSource.UseInvSqr = true; spatializedSource.EnableRfl = false; spatializedSource.EnableSpatialization = true; spatializedSource.Far = 100f; spatializedSource.Near = 0.1f; // Add phoneme context to the mouth anchor lipsyncContext = MouthAnchor.GetComponent <OVRLipSyncContext>(); if (lipsyncContext == null) { lipsyncContext = MouthAnchor.gameObject.AddComponent <OVRLipSyncContext>(); } lipsyncContext.provider = EnableLaughter ? OVRLipSync.ContextProviders.Enhanced_with_Laughter : OVRLipSync.ContextProviders.Enhanced; // Ignore audio callback if microphone is owned by VoIP lipsyncContext.skipAudioSource = !CanOwnMicrophone; StartCoroutine(WaitForMouthAudioSource()); } if (GetComponent <OvrAvatarRemoteDriver>() != null) { GazeTarget headTarget = head.gameObject.AddComponent <GazeTarget>(); headTarget.Type = ovrAvatarGazeTargetType.AvatarHead; AvatarLogger.Log("Added head as gaze target"); Transform hand = transform.Find("hand_left"); if (hand == null) { AvatarLogger.LogWarning("Gaze target helper config failed: Cannot find left hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added left hand as gaze target"); } hand = transform.Find("hand_right"); if (hand == null) { AvatarLogger.Log("Gaze target helper config failed: Cannot find right hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added right hand as gaze target"); } } }
void Start() { if (OvrAvatarSDKManager.Instance == null) { return; } #if !UNITY_ANDROID if (CombineMeshes) { CombineMeshes = false; AvatarLogger.Log("Combined Meshes currently only supported on mobile"); } #endif #if !UNITY_5_5_OR_NEWER if (CombineMeshes) { CombineMeshes = false; AvatarLogger.LogWarning("Combined Meshes requires Unity 5.5.0+"); } #endif materialManager = gameObject.AddComponent <OvrAvatarMaterialManager>(); try { oculusUserIDInternal = UInt64.Parse(oculusUserID); } catch (Exception) { oculusUserIDInternal = 0; AvatarLogger.LogWarning("Invalid Oculus User ID Format"); } // If no oculus ID is supplied then turn off combine meshes to prevent the texture arrays // being populated by invalid textures. if (oculusUserIDInternal == 0) { AvatarLogger.LogWarning("Oculus User ID set to 0. Provide actual user ID: " + gameObject.name); CombineMeshes = false; } AvatarLogger.Log("Starting OvrAvatar " + gameObject.name); AvatarLogger.Log(AvatarLogger.Tab + "LOD: " + LevelOfDetail.ToString()); AvatarLogger.Log(AvatarLogger.Tab + "Combine Meshes: " + CombineMeshes); AvatarLogger.Log(AvatarLogger.Tab + "Force Mobile Textures: " + USE_MOBILE_TEXTURE_FORMAT); AvatarLogger.Log(AvatarLogger.Tab + "Oculus User ID: " + oculusUserIDInternal); Capabilities = 0; if (EnableBody) { Capabilities |= ovrAvatarCapabilities.Body; } if (EnableHands) { Capabilities |= ovrAvatarCapabilities.Hands; } if (EnableBase && EnableBody) { Capabilities |= ovrAvatarCapabilities.Base; } if (EnableExpressive) { Capabilities |= ovrAvatarCapabilities.Expressive; } // Enable body tilt on 6dof devices if (OVRPlugin.positionSupported) { Capabilities |= ovrAvatarCapabilities.BodyTilt; } ShowLeftController(StartWithControllers); ShowRightController(StartWithControllers); OvrAvatarSDKManager.AvatarSpecRequestParams avatarSpecRequest = new OvrAvatarSDKManager.AvatarSpecRequestParams( oculusUserIDInternal, this.AvatarSpecificationCallback, CombineMeshes, LevelOfDetail, USE_MOBILE_TEXTURE_FORMAT, LookAndFeelVersion, FallbackLookAndFeelVersion, EnableExpressive); OvrAvatarSDKManager.Instance.RequestAvatarSpecification(avatarSpecRequest); OvrAvatarSDKManager.Instance.AddLoadingAvatar(GetInstanceID()); waitingForCombinedMesh = CombineMeshes; if (Driver != null) { Driver.Mode = UseSDKPackets ? OvrAvatarDriver.PacketMode.SDK : OvrAvatarDriver.PacketMode.Unity; } }
public OvrAvatarAssetMesh(UInt64 _assetId, IntPtr asset, ovrAvatarAssetType meshType) { assetID = _assetId; mesh = new Mesh(); mesh.name = "Procedural Geometry for asset " + _assetId; switch (meshType) { case ovrAvatarAssetType.Mesh: { ovrAvatarMeshAssetData meshAssetData = CAPI.ovrAvatarAsset_GetMeshData(asset); AvatarLogger.Log( "OvrAvatarAssetMesh: " + _assetId + " " + meshType.ToString() + " VertexCount:" + meshAssetData.vertexCount); long vertexCount = (long)meshAssetData.vertexCount; Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; Vector2[] uv = new Vector2[vertexCount]; Color[] colors = new Color[vertexCount]; BoneWeight[] boneWeights = new BoneWeight[vertexCount]; long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertex)); long vertexBufferStart = meshAssetData.vertexBuffer.ToInt64(); for (long i = 0; i < vertexCount; i++) { long offset = vertexSize * i; ovrAvatarMeshVertex vertex = (ovrAvatarMeshVertex)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertex)); vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); uv[i] = new Vector2(vertex.u, vertex.v); colors[i] = new Color(0, 0, 0, 1); boneWeights[i].boneIndex0 = vertex.blendIndices[0]; boneWeights[i].boneIndex1 = vertex.blendIndices[1]; boneWeights[i].boneIndex2 = vertex.blendIndices[2]; boneWeights[i].boneIndex3 = vertex.blendIndices[3]; boneWeights[i].weight0 = vertex.blendWeights[0]; boneWeights[i].weight1 = vertex.blendWeights[1]; boneWeights[i].weight2 = vertex.blendWeights[2]; boneWeights[i].weight3 = vertex.blendWeights[3]; } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.tangents = tangents; mesh.boneWeights = boneWeights; mesh.colors = colors; skinnedBindPose = meshAssetData.skinnedBindPose; ulong indexCount = meshAssetData.indexCount; Int16[] indices = new Int16[indexCount]; IntPtr indexBufferPtr = meshAssetData.indexBuffer; Marshal.Copy(indexBufferPtr, indices, 0, (int)indexCount); Int32[] triangles = new Int32[indexCount]; for (ulong i = 0; i < indexCount; i += 3) { triangles[i + 2] = (Int32)indices[i]; triangles[i + 1] = (Int32)indices[i + 1]; triangles[i] = (Int32)indices[i + 2]; } mesh.triangles = triangles; UInt32 jointCount = skinnedBindPose.jointCount; jointNames = new string[jointCount]; for (UInt32 i = 0; i < jointCount; i++) { jointNames[i] = Marshal.PtrToStringAnsi(skinnedBindPose.jointNames[i]); } } break; case ovrAvatarAssetType.CombinedMesh: { ovrAvatarMeshAssetDataV2 meshAssetData = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset); AvatarLogger.Log( "OvrAvatarAssetMesh: " + _assetId + " " + meshType.ToString() + " VertexCount:" + meshAssetData.vertexCount); long vertexCount = (long)meshAssetData.vertexCount; Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; Vector2[] uv = new Vector2[vertexCount]; Color[] colors = new Color[vertexCount]; BoneWeight[] boneWeights = new BoneWeight[vertexCount]; long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertexV2)); long vertexBufferStart = meshAssetData.vertexBuffer.ToInt64(); for (long i = 0; i < vertexCount; i++) { long offset = vertexSize * i; ovrAvatarMeshVertexV2 vertex = (ovrAvatarMeshVertexV2)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertexV2)); vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); uv[i] = new Vector2(vertex.u, vertex.v); colors[i] = new Color(vertex.r, vertex.g, vertex.b, vertex.a); boneWeights[i].boneIndex0 = vertex.blendIndices[0]; boneWeights[i].boneIndex1 = vertex.blendIndices[1]; boneWeights[i].boneIndex2 = vertex.blendIndices[2]; boneWeights[i].boneIndex3 = vertex.blendIndices[3]; boneWeights[i].weight0 = vertex.blendWeights[0]; boneWeights[i].weight1 = vertex.blendWeights[1]; boneWeights[i].weight2 = vertex.blendWeights[2]; boneWeights[i].weight3 = vertex.blendWeights[3]; } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.tangents = tangents; mesh.boneWeights = boneWeights; mesh.colors = colors; skinnedBindPose = meshAssetData.skinnedBindPose; ulong indexCount = meshAssetData.indexCount; Int16[] indices = new Int16[indexCount]; IntPtr indexBufferPtr = meshAssetData.indexBuffer; Marshal.Copy(indexBufferPtr, indices, 0, (int)indexCount); Int32[] triangles = new Int32[indexCount]; for (ulong i = 0; i < indexCount; i += 3) { triangles[i + 2] = (Int32)indices[i]; triangles[i + 1] = (Int32)indices[i + 1]; triangles[i] = (Int32)indices[i + 2]; } mesh.triangles = triangles; UInt32 jointCount = skinnedBindPose.jointCount; jointNames = new string[jointCount]; for (UInt32 i = 0; i < jointCount; i++) { jointNames[i] = Marshal.PtrToStringAnsi(skinnedBindPose.jointNames[i]); } } break; default: throw new Exception("Bad Mesh Asset Type"); } }
private void ConfigureHelpers() { Transform head = transform.Find("body/body_renderPart_0/root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT/head_JNT"); if (head == null) { AvatarLogger.LogError("Avatar helper config failed. Cannot find head transform. All helpers spawning on root avatar transform"); head = transform; } if (MouthAnchor == null) { MouthAnchor = CreateHelperObject(head, MOUTH_HEAD_OFFSET, MOUTH_HELPER_NAME); } if (GetComponent <OvrAvatarLocalDriver>() != null) { if (audioSource == null) { audioSource = MouthAnchor.gameObject.AddComponent <AudioSource>(); } spatializedSource = MouthAnchor.GetComponent <ONSPAudioSource>(); if (spatializedSource == null) { spatializedSource = MouthAnchor.gameObject.AddComponent <ONSPAudioSource>(); } spatializedSource.UseInvSqr = true; spatializedSource.EnableRfl = false; spatializedSource.EnableSpatialization = true; spatializedSource.Far = 100f; spatializedSource.Near = 0.1f; StartCoroutine(WaitForMouthAudioSource()); } if (GetComponent <OvrAvatarRemoteDriver>() != null) { GazeTarget headTarget = head.gameObject.AddComponent <GazeTarget>(); headTarget.Type = ovrAvatarGazeTargetType.AvatarHead; AvatarLogger.Log("Added head as gaze target"); Transform hand = transform.Find("hand_left"); if (hand == null) { AvatarLogger.LogWarning("Gaze target helper config failed: Cannot find left hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added left hand as gaze target"); } hand = transform.Find("hand_right"); if (hand == null) { AvatarLogger.Log("Gaze target helper config failed: Cannot find right hand transform"); } else { GazeTarget handTarget = hand.gameObject.AddComponent <GazeTarget>(); handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; AvatarLogger.Log("Added right hand as gaze target"); } } }