private void GetVertexAndIndexData( IntPtr asset, ovrAvatarAssetType meshType, out long vertexCount, out IntPtr vertexBuffer, out uint indexCount, out IntPtr indexBuffer) { vertexCount = 0; vertexBuffer = IntPtr.Zero; indexCount = 0; indexBuffer = IntPtr.Zero; switch (meshType) { case ovrAvatarAssetType.Mesh: vertexCount = CAPI.ovrAvatarAsset_GetMeshData(asset).vertexCount; vertexBuffer = CAPI.ovrAvatarAsset_GetMeshData(asset).vertexBuffer; indexCount = CAPI.ovrAvatarAsset_GetMeshData(asset).indexCount; indexBuffer = CAPI.ovrAvatarAsset_GetMeshData(asset).indexBuffer; break; case ovrAvatarAssetType.CombinedMesh: vertexCount = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).vertexCount; vertexBuffer = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).vertexBuffer; indexCount = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).indexCount; indexBuffer = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).indexBuffer; break; default: break; } }
private void SetSkinnedBindPose(IntPtr asset, ovrAvatarAssetType meshType) { switch (meshType) { case ovrAvatarAssetType.Mesh: skinnedBindPose = CAPI.ovrAvatarAsset_GetMeshData(asset).skinnedBindPose; break; case ovrAvatarAssetType.CombinedMesh: skinnedBindPose = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).skinnedBindPose; break; default: break; } }
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"); } }
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); }
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; switch (assetType) { case ovrAvatarAssetType.Mesh: assetData = new OvrAvatarAssetMesh(assetID, asset); break; case ovrAvatarAssetType.Texture: assetData = new OvrAvatarAssetTexture(assetID, asset); break; case ovrAvatarAssetType.Material: assetData = new OvrAvatarAssetMaterial(assetID, asset); break; default: throw new NotImplementedException(string.Format("Unsupported asset type format {0}", assetType.ToString())); } HashSet <assetLoadedCallback> callbackSet; if (assetLoadedCallbacks.TryGetValue(assetMessage.assetID, out callbackSet)) { assetCache.Add(assetID, assetData); foreach (var callback in callbackSet) { callback(assetData); } assetLoadedCallbacks.Remove(assetMessage.assetID); } else { Debug.LogWarning("Loaded an asset with no owner: " + 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 { Debug.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); }