clean project

This commit is contained in:
Helar Jaadla
2022-03-07 17:52:41 +02:00
parent a174b45bd2
commit cbeb10ec35
5100 changed files with 837159 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
using System;
using UnityEngine;
using Oculus.Avatar;
public class GazeTarget : MonoBehaviour
{
public ovrAvatarGazeTargetType Type;
private static ovrAvatarGazeTargets RuntimeTargetList;
static GazeTarget()
{
// This size has to match the 'MarshalAs' attribute in the ovrAvatarGazeTargets declaration.
RuntimeTargetList.targets = new ovrAvatarGazeTarget[128];
RuntimeTargetList.targetCount = 1;
}
void Start()
{
UpdateGazeTarget();
transform.hasChanged = false;
}
void Update()
{
if (transform.hasChanged)
{
transform.hasChanged = false;
UpdateGazeTarget();
}
}
void OnDestroy()
{
UInt32[] targetIds = new UInt32[1];
targetIds[0] = (UInt32) transform.GetInstanceID();
CAPI.ovrAvatar_RemoveGazeTargets(1, targetIds);
}
private void UpdateGazeTarget()
{
ovrAvatarGazeTarget target = CreateOvrGazeTarget((UInt32) transform.GetInstanceID(), transform.position, Type);
RuntimeTargetList.targets[0] = target;
CAPI.ovrAvatar_UpdateGazeTargets(RuntimeTargetList);
}
private ovrAvatarGazeTarget CreateOvrGazeTarget(UInt32 targetId, Vector3 targetPosition, ovrAvatarGazeTargetType targetType)
{
return new ovrAvatarGazeTarget
{
id = targetId,
// Do coordinate system switch.
worldPosition = new Vector3(targetPosition.x, targetPosition.y, -targetPosition.z),
type = targetType
};
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bfcd054df64e334ba2f191666f3fe92
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 00f3402a2ea5bff4880c0313515240cd
timeCreated: 1464046614
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,5 @@
using System;
public class OvrAvatarAsset {
public UInt64 assetID;
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a7045bb39115f484a89ecaa778a2a60f
timeCreated: 1475521356
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,279 @@
using System;
using Oculus.Avatar;
using UnityEngine;
using System.Runtime.InteropServices;
public class OvrAvatarAssetMesh : OvrAvatarAsset
{
public Mesh mesh;
private ovrAvatarSkinnedMeshPose skinnedBindPose;
public string[] jointNames;
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]);
}
}
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 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);
}
}
}
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;
}
}
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;
}
}
public SkinnedMeshRenderer CreateSkinnedMeshRendererOnObject(GameObject target)
{
SkinnedMeshRenderer skinnedMeshRenderer = target.AddComponent<SkinnedMeshRenderer>();
skinnedMeshRenderer.sharedMesh = mesh;
mesh.name = "AvatarMesh_" + assetID;
UInt32 jointCount = skinnedBindPose.jointCount;
GameObject[] bones = new GameObject[jointCount];
Transform[] boneTransforms = new Transform[jointCount];
Matrix4x4[] bindPoses = new Matrix4x4[jointCount];
for (UInt32 i = 0; i < jointCount; i++)
{
bones[i] = new GameObject();
boneTransforms[i] = bones[i].transform;
bones[i].name = jointNames[i];
int parentIndex = skinnedBindPose.jointParents[i];
if (parentIndex == -1)
{
bones[i].transform.parent = skinnedMeshRenderer.transform;
skinnedMeshRenderer.rootBone = bones[i].transform;
}
else
{
bones[i].transform.parent = bones[parentIndex].transform;
}
// Set the position relative to the parent
Vector3 position = skinnedBindPose.jointTransform[i].position;
position.z = -position.z;
bones[i].transform.localPosition = position;
Quaternion orientation = skinnedBindPose.jointTransform[i].orientation;
orientation.x = -orientation.x;
orientation.y = -orientation.y;
bones[i].transform.localRotation = orientation;
bones[i].transform.localScale = skinnedBindPose.jointTransform[i].scale;
bindPoses[i] = bones[i].transform.worldToLocalMatrix * skinnedMeshRenderer.transform.localToWorldMatrix;
}
skinnedMeshRenderer.bones = boneTransforms;
mesh.bindposes = bindPoses;
return skinnedMeshRenderer;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 80be643e69fa4a4478a5cb27a190bbd2
timeCreated: 1475522461
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System;
using Oculus.Avatar;
using UnityEngine;
public class OvrAvatarAssetTexture : OvrAvatarAsset
{
public Texture2D texture;
private const int ASTCHeaderSize = 16;
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:
#if UNITY_2020_1_OR_NEWER
format = TextureFormat.ASTC_6x6;
#else
format = TextureFormat.ASTC_RGB_6x6;
#endif
textureData = new IntPtr(textureData.ToInt64() + ASTCHeaderSize);
textureDataSize -= ASTCHeaderSize;
break;
case ovrAvatarTextureFormat.ASTC_RGB_6x6_MIPMAPS:
#if UNITY_2020_1_OR_NEWER
format = TextureFormat.ASTC_6x6;
#else
format = TextureFormat.ASTC_RGB_6x6;
#endif
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);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8a3167eed50e56346be5b1cc65ad7226
timeCreated: 1475522480
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using Oculus.Avatar;
public class OvrAvatarBase : OvrAvatarComponent
{
ovrAvatarBaseComponent component = new ovrAvatarBaseComponent();
void Update()
{
if (owner == null)
{
return;
}
if (CAPI.ovrAvatarPose_GetBaseComponent(owner.sdkAvatar, ref component))
{
UpdateAvatar(component.renderComponent);
}
else
{
owner.Base = null;
Destroy(this);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a0e33623ec5372748b5703f61a4df82d
timeCreated: 1477606822
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Oculus.Avatar;
public class OvrAvatarBody : OvrAvatarComponent
{
public ovrAvatarBodyComponent component = new ovrAvatarBodyComponent();
public ovrAvatarComponent? GetNativeAvatarComponent()
{
if (owner == null)
{
return null;
}
if (CAPI.ovrAvatarPose_GetBodyComponent(owner.sdkAvatar, ref component))
{
CAPI.ovrAvatarComponent_Get(component.renderComponent, true, ref nativeAvatarComponent);
return nativeAvatarComponent;
}
return null;
}
void Update()
{
if (owner == null)
{
return;
}
if (CAPI.ovrAvatarPose_GetBodyComponent(owner.sdkAvatar, ref component))
{
UpdateAvatar(component.renderComponent);
}
else
{
owner.Body = null;
Destroy(this);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: eb7a6650b6cb46545967d3b380b7396c
timeCreated: 1466814542
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Oculus.Avatar;
using System.Threading;
public class OvrAvatarComponent : MonoBehaviour
{
public static readonly string[] LayerKeywords = new[] { "LAYERS_0", "LAYERS_1", "LAYERS_2", "LAYERS_3", "LAYERS_4", "LAYERS_5", "LAYERS_6", "LAYERS_7", "LAYERS_8", };
public static readonly string[] LayerSampleModeParameters = new[] { "_LayerSampleMode0", "_LayerSampleMode1", "_LayerSampleMode2", "_LayerSampleMode3", "_LayerSampleMode4", "_LayerSampleMode5", "_LayerSampleMode6", "_LayerSampleMode7", };
public static readonly string[] LayerBlendModeParameters = new[] { "_LayerBlendMode0", "_LayerBlendMode1", "_LayerBlendMode2", "_LayerBlendMode3", "_LayerBlendMode4", "_LayerBlendMode5", "_LayerBlendMode6", "_LayerBlendMode7", };
public static readonly string[] LayerMaskTypeParameters = new[] { "_LayerMaskType0", "_LayerMaskType1", "_LayerMaskType2", "_LayerMaskType3", "_LayerMaskType4", "_LayerMaskType5", "_LayerMaskType6", "_LayerMaskType7", };
public static readonly string[] LayerColorParameters = new[] { "_LayerColor0", "_LayerColor1", "_LayerColor2", "_LayerColor3", "_LayerColor4", "_LayerColor5", "_LayerColor6", "_LayerColor7", };
public static readonly string[] LayerSurfaceParameters = new[] { "_LayerSurface0", "_LayerSurface1", "_LayerSurface2", "_LayerSurface3", "_LayerSurface4", "_LayerSurface5", "_LayerSurface6", "_LayerSurface7", };
public static readonly string[] LayerSampleParametersParameters = new[] { "_LayerSampleParameters0", "_LayerSampleParameters1", "_LayerSampleParameters2", "_LayerSampleParameters3", "_LayerSampleParameters4", "_LayerSampleParameters5", "_LayerSampleParameters6", "_LayerSampleParameters7", };
public static readonly string[] LayerMaskParametersParameters = new[] { "_LayerMaskParameters0", "_LayerMaskParameters1", "_LayerMaskParameters2", "_LayerMaskParameters3", "_LayerMaskParameters4", "_LayerMaskParameters5", "_LayerMaskParameters6", "_LayerMaskParameters7", };
public static readonly string[] LayerMaskAxisParameters = new[] { "_LayerMaskAxis0", "_LayerMaskAxis1", "_LayerMaskAxis2", "_LayerMaskAxis3", "_LayerMaskAxis4", "_LayerMaskAxis5", "_LayerMaskAxis6", "_LayerMaskAxis7", };
private Dictionary<Material, ovrAvatarMaterialState> materialStates = new Dictionary<Material, ovrAvatarMaterialState>();
public List<OvrAvatarRenderComponent> RenderParts = new List<OvrAvatarRenderComponent>();
protected OvrAvatar owner = null;
protected ovrAvatarComponent nativeAvatarComponent = new ovrAvatarComponent();
public void SetOvrAvatarOwner(OvrAvatar ovrAvatarOwner)
{
owner = ovrAvatarOwner;
}
public void UpdateAvatar(IntPtr nativeComponent)
{
CAPI.ovrAvatarComponent_Get(nativeComponent, false, ref nativeAvatarComponent);
OvrAvatar.ConvertTransform(nativeAvatarComponent.transform, transform);
for (UInt32 renderPartIndex = 0; renderPartIndex < nativeAvatarComponent.renderPartCount; renderPartIndex++)
{
if (RenderParts.Count <= renderPartIndex)
{
break;
}
OvrAvatarRenderComponent renderComponent = RenderParts[(int)renderPartIndex];
IntPtr renderPart = OvrAvatar.GetRenderPart(nativeAvatarComponent, renderPartIndex);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRender:
((OvrAvatarSkinnedMeshRenderComponent)renderComponent).UpdateSkinnedMeshRender(this, owner, renderPart);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
((OvrAvatarSkinnedMeshRenderPBSComponent)renderComponent).UpdateSkinnedMeshRenderPBS(owner, renderPart, renderComponent.mesh.sharedMaterial);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
((OvrAvatarSkinnedMeshPBSV2RenderComponent)renderComponent).UpdateSkinnedMeshRender(this, owner, renderPart);
break;
default:
break;
}
}
}
protected void UpdateActive(OvrAvatar avatar, ovrAvatarVisibilityFlags mask)
{
bool active = avatar.ShowFirstPerson && (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0;
active |= avatar.ShowThirdPerson && (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0;
this.gameObject.SetActive(active);
}
public void UpdateAvatarMaterial(Material mat, ovrAvatarMaterialState matState)
{
mat.SetColor("_BaseColor", matState.baseColor);
mat.SetInt("_BaseMaskType", (int)matState.baseMaskType);
mat.SetVector("_BaseMaskParameters", matState.baseMaskParameters);
mat.SetVector("_BaseMaskAxis", matState.baseMaskAxis);
if (matState.alphaMaskTextureID != 0)
{
mat.SetTexture("_AlphaMask", GetLoadedTexture(matState.alphaMaskTextureID));
mat.SetTextureScale("_AlphaMask", new Vector2(matState.alphaMaskScaleOffset.x, matState.alphaMaskScaleOffset.y));
mat.SetTextureOffset("_AlphaMask", new Vector2(matState.alphaMaskScaleOffset.z, matState.alphaMaskScaleOffset.w));
}
if (matState.normalMapTextureID != 0)
{
mat.EnableKeyword("NORMAL_MAP_ON");
mat.SetTexture("_NormalMap", GetLoadedTexture(matState.normalMapTextureID));
mat.SetTextureScale("_NormalMap", new Vector2(matState.normalMapScaleOffset.x, matState.normalMapScaleOffset.y));
mat.SetTextureOffset("_NormalMap", new Vector2(matState.normalMapScaleOffset.z, matState.normalMapScaleOffset.w));
}
if (matState.parallaxMapTextureID != 0)
{
mat.SetTexture("_ParallaxMap", GetLoadedTexture(matState.parallaxMapTextureID));
mat.SetTextureScale("_ParallaxMap", new Vector2(matState.parallaxMapScaleOffset.x, matState.parallaxMapScaleOffset.y));
mat.SetTextureOffset("_ParallaxMap", new Vector2(matState.parallaxMapScaleOffset.z, matState.parallaxMapScaleOffset.w));
}
if (matState.roughnessMapTextureID != 0)
{
mat.EnableKeyword("ROUGHNESS_ON");
mat.SetTexture("_RoughnessMap", GetLoadedTexture(matState.roughnessMapTextureID));
mat.SetTextureScale("_RoughnessMap", new Vector2(matState.roughnessMapScaleOffset.x, matState.roughnessMapScaleOffset.y));
mat.SetTextureOffset("_RoughnessMap", new Vector2(matState.roughnessMapScaleOffset.z, matState.roughnessMapScaleOffset.w));
}
mat.EnableKeyword(LayerKeywords[matState.layerCount]);
for (ulong layerIndex = 0; layerIndex < matState.layerCount; layerIndex++)
{
ovrAvatarMaterialLayerState layer = matState.layers[layerIndex];
mat.SetInt(LayerSampleModeParameters[layerIndex], (int)layer.sampleMode);
mat.SetInt(LayerBlendModeParameters[layerIndex], (int)layer.blendMode);
mat.SetInt(LayerMaskTypeParameters[layerIndex], (int)layer.maskType);
mat.SetColor(LayerColorParameters[layerIndex], layer.layerColor);
if (layer.sampleMode != ovrAvatarMaterialLayerSampleMode.Color)
{
string surfaceProperty = LayerSurfaceParameters[layerIndex];
mat.SetTexture(surfaceProperty, GetLoadedTexture(layer.sampleTexture));
mat.SetTextureScale(surfaceProperty, new Vector2(layer.sampleScaleOffset.x, layer.sampleScaleOffset.y));
mat.SetTextureOffset(surfaceProperty, new Vector2(layer.sampleScaleOffset.z, layer.sampleScaleOffset.w));
}
if (layer.sampleMode == ovrAvatarMaterialLayerSampleMode.Parallax)
{
mat.EnableKeyword("PARALLAX_ON");
}
mat.SetColor(LayerSampleParametersParameters[layerIndex], layer.sampleParameters);
mat.SetColor(LayerMaskParametersParameters[layerIndex], layer.maskParameters);
mat.SetColor(LayerMaskAxisParameters[layerIndex], layer.maskAxis);
}
materialStates[mat] = matState;
}
public static Texture2D GetLoadedTexture(UInt64 assetId)
{
OvrAvatarAssetTexture tex = (OvrAvatarAssetTexture)OvrAvatarSDKManager.Instance.GetAsset(assetId);
if (tex == null)
{
return null;
}
return tex.texture;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4d8af585c6ed18849905454f83194043
timeCreated: 1479155378
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
using UnityEngine;
using System.Collections;
using System;
using Oculus.Avatar;
public abstract class OvrAvatarDriver : MonoBehaviour {
public enum PacketMode
{
SDK,
Unity
};
public PacketMode Mode;
protected PoseFrame CurrentPose;
public PoseFrame GetCurrentPose() { return CurrentPose; }
public abstract void UpdateTransforms(IntPtr sdkAvatar);
private ovrAvatarControllerType ControllerType = ovrAvatarControllerType.Quest;
public struct ControllerPose
{
public ovrAvatarButton buttons;
public ovrAvatarTouch touches;
public Vector2 joystickPosition;
public float indexTrigger;
public float handTrigger;
public bool isActive;
public static ControllerPose Interpolate(ControllerPose a, ControllerPose b, float t)
{
return new ControllerPose
{
buttons = t < 0.5f ? a.buttons : b.buttons,
touches = t < 0.5f ? a.touches : b.touches,
joystickPosition = Vector2.Lerp(a.joystickPosition, b.joystickPosition, t),
indexTrigger = Mathf.Lerp(a.indexTrigger, b.indexTrigger, t),
handTrigger = Mathf.Lerp(a.handTrigger, b.handTrigger, t),
isActive = t < 0.5f ? a.isActive : b.isActive,
};
}
}
public struct PoseFrame
{
public Vector3 headPosition;
public Quaternion headRotation;
public Vector3 handLeftPosition;
public Quaternion handLeftRotation;
public Vector3 handRightPosition;
public Quaternion handRightRotation;
public float voiceAmplitude;
public ControllerPose controllerLeftPose;
public ControllerPose controllerRightPose;
public static PoseFrame Interpolate(PoseFrame a, PoseFrame b, float t)
{
return new PoseFrame
{
headPosition = Vector3.Lerp(a.headPosition, b.headPosition, t),
headRotation = Quaternion.Slerp(a.headRotation, b.headRotation, t),
handLeftPosition = Vector3.Lerp(a.handLeftPosition, b.handLeftPosition, t),
handLeftRotation = Quaternion.Slerp(a.handLeftRotation, b.handLeftRotation, t),
handRightPosition = Vector3.Lerp(a.handRightPosition, b.handRightPosition, t),
handRightRotation = Quaternion.Slerp(a.handRightRotation, b.handRightRotation, t),
voiceAmplitude = Mathf.Lerp(a.voiceAmplitude, b.voiceAmplitude, t),
controllerLeftPose = ControllerPose.Interpolate(a.controllerLeftPose, b.controllerLeftPose, t),
controllerRightPose = ControllerPose.Interpolate(a.controllerRightPose, b.controllerRightPose, t),
};
}
};
void Start()
{
var headsetType = OVRPlugin.GetSystemHeadsetType();
switch (headsetType)
{
case OVRPlugin.SystemHeadset.Oculus_Quest:
case OVRPlugin.SystemHeadset.Rift_S:
ControllerType = ovrAvatarControllerType.Quest;
break;
case OVRPlugin.SystemHeadset.Rift_DK1:
case OVRPlugin.SystemHeadset.Rift_DK2:
case OVRPlugin.SystemHeadset.Rift_CV1:
default:
ControllerType = ovrAvatarControllerType.Touch;
break;
}
}
public void UpdateTransformsFromPose(IntPtr sdkAvatar)
{
if (sdkAvatar != IntPtr.Zero)
{
ovrAvatarTransform bodyTransform = OvrAvatar.CreateOvrAvatarTransform(CurrentPose.headPosition, CurrentPose.headRotation);
ovrAvatarHandInputState inputStateLeft = OvrAvatar.CreateInputState(OvrAvatar.CreateOvrAvatarTransform(CurrentPose.handLeftPosition, CurrentPose.handLeftRotation), CurrentPose.controllerLeftPose);
ovrAvatarHandInputState inputStateRight = OvrAvatar.CreateInputState(OvrAvatar.CreateOvrAvatarTransform(CurrentPose.handRightPosition, CurrentPose.handRightRotation), CurrentPose.controllerRightPose);
CAPI.ovrAvatarPose_UpdateBody(sdkAvatar, bodyTransform);
CAPI.ovrAvatarPose_UpdateHandsWithType(sdkAvatar, inputStateLeft, inputStateRight, ControllerType);
}
}
public static bool GetIsTrackedRemote()
{
return false;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b0bda905d6cc47640bc17f99e364a1b9
timeCreated: 1464049373
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Oculus.Avatar;
public class OvrAvatarHand : OvrAvatarComponent
{
public bool isLeftHand = true;
ovrAvatarHandComponent component = new ovrAvatarHandComponent();
void Update()
{
if (owner == null)
{
return;
}
bool hasComponent = false;
if (isLeftHand)
{
hasComponent = CAPI.ovrAvatarPose_GetLeftHandComponent(owner.sdkAvatar, ref component);
}
else
{
hasComponent = CAPI.ovrAvatarPose_GetRightHandComponent(owner.sdkAvatar, ref component);
}
if (hasComponent)
{
UpdateAvatar(component.renderComponent);
}
else
{
if (isLeftHand)
{
owner.HandLeft = null;
}
else
{
owner.HandRight = null;
}
Destroy(this);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e53b07ad62d980a4da9fffff0b05fd2e
timeCreated: 1464054646
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using Oculus.Avatar;
public class OvrAvatarLocalDriver : OvrAvatarDriver {
Vector3 centerEyePosition = Vector3.zero;
Quaternion centerEyeRotation = Quaternion.identity;
ControllerPose GetMalibuControllerPose(OVRInput.Controller controller)
{
ovrAvatarButton buttons = 0;
if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, controller)) buttons |= ovrAvatarButton.One;
return new ControllerPose
{
buttons = buttons,
touches = OVRInput.Get(OVRInput.Touch.PrimaryTouchpad) ? ovrAvatarTouch.One : 0,
joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, controller),
indexTrigger = 0f,
handTrigger = 0f,
isActive = (OVRInput.GetActiveController() & controller) != 0,
};
}
float voiceAmplitude = 0.0f;
ControllerPose GetControllerPose(OVRInput.Controller controller)
{
ovrAvatarButton buttons = 0;
if (OVRInput.Get(OVRInput.Button.One, controller)) buttons |= ovrAvatarButton.One;
if (OVRInput.Get(OVRInput.Button.Two, controller)) buttons |= ovrAvatarButton.Two;
if (OVRInput.Get(OVRInput.Button.Start, controller)) buttons |= ovrAvatarButton.Three;
if (OVRInput.Get(OVRInput.Button.PrimaryThumbstick, controller)) buttons |= ovrAvatarButton.Joystick;
ovrAvatarTouch touches = 0;
if (OVRInput.Get(OVRInput.Touch.One, controller)) touches |= ovrAvatarTouch.One;
if (OVRInput.Get(OVRInput.Touch.Two, controller)) touches |= ovrAvatarTouch.Two;
if (OVRInput.Get(OVRInput.Touch.PrimaryThumbstick, controller)) touches |= ovrAvatarTouch.Joystick;
if (OVRInput.Get(OVRInput.Touch.PrimaryThumbRest, controller)) touches |= ovrAvatarTouch.ThumbRest;
if (OVRInput.Get(OVRInput.Touch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Index;
if (!OVRInput.Get(OVRInput.NearTouch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Pointing;
if (!OVRInput.Get(OVRInput.NearTouch.PrimaryThumbButtons, controller)) touches |= ovrAvatarTouch.ThumbUp;
return new ControllerPose
{
buttons = buttons,
touches = touches,
joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick, controller),
indexTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryIndexTrigger, controller),
handTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger, controller),
isActive = (OVRInput.GetActiveController() & controller) != 0,
};
}
private void CalculateCurrentPose()
{
// Platform and device agnostic calls to return center eye pose, used to pass in head pose to sdk
OVRNodeStateProperties.GetNodeStatePropertyVector3(UnityEngine.XR.XRNode.CenterEye, NodeStatePropertyType.Position,
OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyePosition);
OVRNodeStateProperties.GetNodeStatePropertyQuaternion(UnityEngine.XR.XRNode.CenterEye, NodeStatePropertyType.Orientation,
OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyeRotation);
CurrentPose = new PoseFrame
{
voiceAmplitude = voiceAmplitude,
headPosition = centerEyePosition,
headRotation = centerEyeRotation,
handLeftPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch),
handLeftRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch),
handRightPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch),
handRightRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch),
controllerLeftPose = GetControllerPose(OVRInput.Controller.LTouch),
controllerRightPose = GetControllerPose(OVRInput.Controller.RTouch),
};
}
public override void UpdateTransforms(IntPtr sdkAvatar)
{
CalculateCurrentPose();
UpdateTransformsFromPose(sdkAvatar);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ac27124318cf8e84aa7350c2ac1cdb80
timeCreated: 1464049705
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using UnityEngine;
namespace Oculus.Avatar
{
public static class AvatarLogger
{
public const string LogAvatar = "[Avatars] - ";
public const string Tab = " ";
[System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"),
System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_BASIC")]
public static void Log(string logMsg)
{
Debug.Log(LogAvatar + logMsg);
}
[System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"),
System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_BASIC")]
public static void Log(string logMsg, Object context)
{
Debug.Log(LogAvatar + logMsg , context);
}
[System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"),
System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_WARNING")]
public static void LogWarning(string logMsg)
{
Debug.LogWarning(LogAvatar + logMsg);
}
[System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"),
System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_ERROR")]
public static void LogError(string logMsg)
{
Debug.LogError(LogAvatar + logMsg);
}
[System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"),
System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_ERROR")]
public static void LogError(string logMsg, Object context)
{
Debug.LogError(LogAvatar + logMsg, context);
}
};
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6d391500bc1e8da42a41ef796dd22ed0
timeCreated: 1519433181
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,430 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public class OvrAvatarMaterialManager : MonoBehaviour
{
private Renderer TargetRenderer;
private AvatarTextureArrayProperties[] TextureArrays;
public enum TextureType
{
DiffuseTextures = 0,
NormalMaps,
RoughnessMaps,
Count
}
// Material properties required to render a single component
public struct AvatarComponentMaterialProperties
{
public ovrAvatarBodyPartType TypeIndex;
public Color Color;
public Texture2D[] Textures;
public float DiffuseIntensity;
public float RimIntensity;
public float ReflectionIntensity;
}
// Texture arrays
public struct AvatarTextureArrayProperties
{
public Texture2D[] Textures;
public Texture2DArray TextureArray;
}
// Material property arrays that are pushed to the shader
public struct AvatarMaterialPropertyBlock
{
public Vector4[] Colors;
public float[] DiffuseIntensities;
public float[] RimIntensities;
public float[] ReflectionIntensities;
}
private readonly string[] TextureTypeToShaderProperties =
{
"_MainTex", // TextureType.DiffuseTextures = 0
"_NormalMap", // TextureType.NormalMaps
"_RoughnessMap" // TextureType.RoughnessMaps
};
// Container class for all the data relating to an avatar material description
[System.Serializable]
public class AvatarMaterialConfig
{
public AvatarComponentMaterialProperties[] ComponentMaterialProperties;
public AvatarMaterialPropertyBlock MaterialPropertyBlock;
}
// Local config that this manager instance will render
public AvatarMaterialConfig LocalAvatarConfig = new AvatarMaterialConfig();
public List<ReflectionProbeBlendInfo> ReflectionProbes = new List<ReflectionProbeBlendInfo>();
// Cache the previous shader when swapping in the loading shader.
private Shader CombinedShader;
// Shader properties
public static string AVATAR_SHADER_LOADER = "OvrAvatar/Avatar_Mobile_Loader";
public static string AVATAR_SHADER_MAINTEX = "_MainTex";
public static string AVATAR_SHADER_NORMALMAP = "_NormalMap";
public static string AVATAR_SHADER_ROUGHNESSMAP = "_RoughnessMap";
public static string AVATAR_SHADER_COLOR = "_BaseColor";
public static string AVATAR_SHADER_DIFFUSEINTENSITY = "_DiffuseIntensity";
public static string AVATAR_SHADER_RIMINTENSITY = "_RimIntensity";
public static string AVATAR_SHADER_REFLECTIONINTENSITY = "_ReflectionIntensity";
public static string AVATAR_SHADER_CUBEMAP = "_Cubemap";
public static string AVATAR_SHADER_ALPHA = "_Alpha";
public static string AVATAR_SHADER_LOADING_DIMMER = "_LoadingDimmer";
public static string AVATAR_SHADER_IRIS_COLOR = "_MaskColorIris";
public static string AVATAR_SHADER_LIP_COLOR = "_MaskColorLips";
public static string AVATAR_SHADER_BROW_COLOR = "_MaskColorBrows";
public static string AVATAR_SHADER_LASH_COLOR = "_MaskColorLashes";
public static string AVATAR_SHADER_SCLERA_COLOR = "_MaskColorSclera";
public static string AVATAR_SHADER_GUM_COLOR = "_MaskColorGums";
public static string AVATAR_SHADER_TEETH_COLOR = "_MaskColorTeeth";
public static string AVATAR_SHADER_LIP_SMOOTHNESS = "_LipSmoothness";
// Diffuse Intensity constants: body, clothes, eyewear, hair, beard
public static float[] DiffuseIntensities = new[] {0.3f, 0.1f, 0f, 0.15f, 0.15f};
// Rim Intensity constants: body, clothes, eyewear, hair, beard
public static float[] RimIntensities = new[] {5f, 2f, 2.84f, 4f, 4f};
// Reflection Intensity constants: body, clothes, eyewear, hair, beard
public static float[] ReflectionIntensities = new[] {0f, 0.3f, 0.4f, 0f, 0f};
// Loading animation
private const float LOADING_ANIMATION_AMPLITUDE = 0.5f;
private const float LOADING_ANIMATION_PERIOD = 0.35f;
private const float LOADING_ANIMATION_CURVE_SCALE = 0.25f;
private const float LOADING_ANIMATION_DIMMER_MIN = 0.3f;
public void CreateTextureArrays()
{
const int componentCount = (int)ovrAvatarBodyPartType.Count;
const int textureTypeCount = (int)TextureType.Count;
LocalAvatarConfig.ComponentMaterialProperties = new AvatarComponentMaterialProperties[componentCount];
LocalAvatarConfig.MaterialPropertyBlock.Colors = new Vector4[componentCount];
LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities = new float[componentCount];
LocalAvatarConfig.MaterialPropertyBlock.RimIntensities = new float[componentCount];
LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities = new float[componentCount];
for (int i = 0; i < LocalAvatarConfig.ComponentMaterialProperties.Length; ++i)
{
LocalAvatarConfig.ComponentMaterialProperties[i].Textures = new Texture2D[textureTypeCount];
}
TextureArrays = new AvatarTextureArrayProperties[textureTypeCount];
}
public void SetRenderer(Renderer renderer)
{
TargetRenderer = renderer;
TargetRenderer.GetClosestReflectionProbes(ReflectionProbes);
}
public void OnCombinedMeshReady()
{
InitTextureArrays();
SetMaterialPropertyBlock();
// Callback to delete texture set once the avatar is fully loaded
StartCoroutine(RunLoadingAnimation(DeleteTextureSet));
}
// Add a texture ID so that it's managed for deletion
public void AddTextureIDToTextureManager(ulong assetID, bool isSingleComponent)
{
OvrAvatarSDKManager.Instance.GetTextureCopyManager().AddTextureIDToTextureSet(
GetInstanceID(), assetID, isSingleComponent);
}
// Once avatar loading is completed trigger the texture set for deletion
private void DeleteTextureSet()
{
OvrAvatarSDKManager.Instance.GetTextureCopyManager().DeleteTextureSet(GetInstanceID());
}
// Prepare texture arrays and copy to GPU
public void InitTextureArrays()
{
var localProps = LocalAvatarConfig.ComponentMaterialProperties[0];
for (int i = 0; i < TextureArrays.Length && i < localProps.Textures.Length; i++)
{
TextureArrays[i].TextureArray = new Texture2DArray(
localProps.Textures[0].height, localProps.Textures[0].width,
LocalAvatarConfig.ComponentMaterialProperties.Length,
localProps.Textures[0].format,
true,
QualitySettings.activeColorSpace == ColorSpace.Gamma ? false : true
) { filterMode = FilterMode.Trilinear,
//Can probably get away with 4 for roughness maps as well, once we switch
//to BC7/ASTC4x4 texture compression.
anisoLevel = (TextureType)i == TextureType.RoughnessMaps ? 16 : 4 };
//So a name shows up in Renderdoc
TextureArrays[i].TextureArray.name = string.Format("Texture Array Type: {0}", (TextureType)i);
TextureArrays[i].Textures
= new Texture2D[LocalAvatarConfig.ComponentMaterialProperties.Length];
for (int j = 0; j < LocalAvatarConfig.ComponentMaterialProperties.Length; j++)
{
TextureArrays[i].Textures[j]
= LocalAvatarConfig.ComponentMaterialProperties[j].Textures[i];
//So a name shows up in Renderdoc
TextureArrays[i].Textures[j].name = string.Format("Texture Type: {0} Component: {1}", (TextureType)i, j);
}
ProcessTexturesWithMips(
TextureArrays[i].Textures,
localProps.Textures[i].height,
TextureArrays[i].TextureArray);
}
}
private void ProcessTexturesWithMips(
Texture2D[] textures,
int texArrayResolution,
Texture2DArray texArray)
{
for (int i = 0; i < textures.Length; i++)
{
int currentMipSize = texArrayResolution;
int correctNumberOfMips = textures[i].mipmapCount - 1;
// Add mips to copyTexture queue in low-high order from correctNumberOfMips..0
for (int mipLevel = correctNumberOfMips; mipLevel >= 0; mipLevel--)
{
int mipSize = texArrayResolution / currentMipSize;
OvrAvatarSDKManager.Instance.GetTextureCopyManager().CopyTexture(
textures[i],
texArray,
mipLevel,
mipSize,
i,
false);
currentMipSize /= 2;
}
}
}
private void SetMaterialPropertyBlock()
{
if (TargetRenderer != null)
{
for (int i = 0; i < LocalAvatarConfig.ComponentMaterialProperties.Length; i++)
{
LocalAvatarConfig.MaterialPropertyBlock.Colors[i]
= LocalAvatarConfig.ComponentMaterialProperties[i].Color;
LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities[i] = DiffuseIntensities[i];
LocalAvatarConfig.MaterialPropertyBlock.RimIntensities[i] = RimIntensities[i];
LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities[i] = ReflectionIntensities[i];
}
}
}
private void ApplyMaterialPropertyBlock()
{
MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
materialPropertyBlock.SetVectorArray(AVATAR_SHADER_COLOR,
LocalAvatarConfig.MaterialPropertyBlock.Colors);
materialPropertyBlock.SetFloatArray(AVATAR_SHADER_DIFFUSEINTENSITY,
LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities);
materialPropertyBlock.SetFloatArray(AVATAR_SHADER_RIMINTENSITY,
LocalAvatarConfig.MaterialPropertyBlock.RimIntensities);
materialPropertyBlock.SetFloatArray(AVATAR_SHADER_REFLECTIONINTENSITY,
LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities);
TargetRenderer.GetClosestReflectionProbes(ReflectionProbes);
if (ReflectionProbes != null && ReflectionProbes.Count > 0 && ReflectionProbes[0].probe.texture != null)
{
materialPropertyBlock.SetTexture(AVATAR_SHADER_CUBEMAP, ReflectionProbes[0].probe.texture);
}
for (int i = 0; i < TextureArrays.Length; i++)
{
materialPropertyBlock.SetTexture(TextureTypeToShaderProperties[i],
TextureArrays[(int)(TextureType)i].TextureArray);
}
TargetRenderer.SetPropertyBlock(materialPropertyBlock);
}
// Return a component type based on name
public static ovrAvatarBodyPartType GetComponentType(string objectName)
{
if (objectName.Contains("0"))
{
return ovrAvatarBodyPartType.Body;
}
else if (objectName.Contains("1"))
{
return ovrAvatarBodyPartType.Clothing;
}
else if (objectName.Contains("2"))
{
return ovrAvatarBodyPartType.Eyewear;
}
else if (objectName.Contains("3"))
{
return ovrAvatarBodyPartType.Hair;
}
else if (objectName.Contains("4"))
{
return ovrAvatarBodyPartType.Beard;
}
return ovrAvatarBodyPartType.Count;
}
UInt64 GetTextureIDForType(ovrAvatarPBSMaterialState materialState, TextureType type)
{
if (type == TextureType.DiffuseTextures)
{
return materialState.albedoTextureID;
}
else if (type == TextureType.NormalMaps)
{
return materialState.normalTextureID;
}
else if (type == TextureType.RoughnessMaps)
{
return materialState.metallicnessTextureID;
}
return 0;
}
public void ValidateTextures(ovrAvatarPBSMaterialState[] materialStates)
{
var props = LocalAvatarConfig.ComponentMaterialProperties;
int[] heights = new int[(int)TextureType.Count];
TextureFormat[] formats = new TextureFormat[(int)TextureType.Count];
for (var propIndex = 0; propIndex < props.Length; propIndex++)
{
for (var index = 0; index < props[propIndex].Textures.Length; index++)
{
if (props[propIndex].Textures[index] == null)
{
throw new System.Exception(
props[propIndex].TypeIndex.ToString()
+ "Invalid: "
+ ((TextureType)index).ToString());
}
heights[index] = props[propIndex].Textures[index].height;
formats[index] = props[propIndex].Textures[index].format;
}
}
for (int textureIndex = 0; textureIndex < (int)TextureType.Count; textureIndex++)
{
for (var propIndex = 1; propIndex < props.Length; propIndex++)
{
if (props[propIndex - 1].Textures[textureIndex].height
!= props[propIndex].Textures[textureIndex].height)
{
throw new System.Exception(
props[propIndex].TypeIndex.ToString()
+ " Mismatching Resolutions: "
+ ((TextureType)textureIndex).ToString()
+ " "
+ props[propIndex - 1].Textures[textureIndex].height
+ " (ID: "
+ GetTextureIDForType(materialStates[propIndex - 1], (TextureType)textureIndex)
+ ") vs "
+ props[propIndex].Textures[textureIndex].height
+ " (ID: "
+ GetTextureIDForType(materialStates[propIndex], (TextureType)textureIndex)
+ ") Ensure you are using ASTC texture compression on Android or turn off CombineMeshes");
}
if (props[propIndex - 1].Textures[textureIndex].format
!= props[propIndex].Textures[textureIndex].format)
{
throw new System.Exception(
props[propIndex].TypeIndex.ToString()
+ " Mismatching Formats: "
+ ((TextureType)textureIndex).ToString()
+ " "
+ props[propIndex - 1].Textures[textureIndex].format
+ " (ID: "
+ GetTextureIDForType(materialStates[propIndex - 1], (TextureType)textureIndex)
+ ") vs "
+ props[propIndex].Textures[textureIndex].format
+ " (ID: "
+ GetTextureIDForType(materialStates[propIndex], (TextureType)textureIndex)
+ ") Ensure you are using ASTC texture compression on Android or turn off CombineMeshes");
}
}
}
}
// Loading animation on the Dimmer properyt
// Smooth sine lerp every 0.3 seconds between 0.25 and 0.5
private IEnumerator RunLoadingAnimation(Action callBack)
{
// Set the material to single component while the avatar loads
CombinedShader = TargetRenderer.sharedMaterial.shader;
// Save shader properties
int srcBlend = TargetRenderer.sharedMaterial.GetInt("_SrcBlend");
int dstBlend = TargetRenderer.sharedMaterial.GetInt("_DstBlend");
string lightModeTag = TargetRenderer.sharedMaterial.GetTag("LightMode", false);
string renderTypeTag = TargetRenderer.sharedMaterial.GetTag("RenderType", false);
string renderQueueTag = TargetRenderer.sharedMaterial.GetTag("Queue", false);
string ignoreProjectorTag = TargetRenderer.sharedMaterial.GetTag("IgnoreProjector", false);
int renderQueue = TargetRenderer.sharedMaterial.renderQueue;
bool transparentQueue = TargetRenderer.sharedMaterial.IsKeywordEnabled("_ALPHATEST_ON");
// Swap in loading shader
TargetRenderer.sharedMaterial.shader = Shader.Find(AVATAR_SHADER_LOADER);
TargetRenderer.sharedMaterial.SetColor(AVATAR_SHADER_COLOR, Color.white);
while (OvrAvatarSDKManager.Instance.GetTextureCopyManager().GetTextureCount() > 0)
{
float distance = (LOADING_ANIMATION_AMPLITUDE * Mathf.Sin(Time.timeSinceLevelLoad / LOADING_ANIMATION_PERIOD) +
LOADING_ANIMATION_AMPLITUDE) * (LOADING_ANIMATION_CURVE_SCALE) + LOADING_ANIMATION_DIMMER_MIN;
TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, distance);
yield return null;
}
// Swap back main shader
TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, 1f);
TargetRenderer.sharedMaterial.shader = CombinedShader;
// Restore shader properties
TargetRenderer.sharedMaterial.SetInt("_SrcBlend", srcBlend);
TargetRenderer.sharedMaterial.SetInt("_DstBlend", dstBlend);
TargetRenderer.sharedMaterial.SetOverrideTag("LightMode", lightModeTag);
TargetRenderer.sharedMaterial.SetOverrideTag("RenderType", renderTypeTag);
TargetRenderer.sharedMaterial.SetOverrideTag("Queue", renderQueueTag);
TargetRenderer.sharedMaterial.SetOverrideTag("IgnoreProjector", ignoreProjectorTag);
if (transparentQueue)
{
TargetRenderer.sharedMaterial.EnableKeyword("_ALPHATEST_ON");
TargetRenderer.sharedMaterial.EnableKeyword("_ALPHABLEND_ON");
TargetRenderer.sharedMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON");
}
else
{
TargetRenderer.sharedMaterial.DisableKeyword("_ALPHATEST_ON");
TargetRenderer.sharedMaterial.DisableKeyword("_ALPHABLEND_ON");
TargetRenderer.sharedMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
}
TargetRenderer.sharedMaterial.renderQueue = renderQueue;
ApplyMaterialPropertyBlock();
if (callBack != null)
{
callBack();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a139d83bf6796734db220df8a5bfacbd
timeCreated: 1518209612
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,231 @@
using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;
public class OvrAvatarPacket
{
// Used with SDK driven packet flow
public IntPtr ovrNativePacket = IntPtr.Zero;
// ===============================================================
// All code below used for unity only pose blending option.
// ===============================================================
List<float> frameTimes = new List<float>();
List<OvrAvatarDriver.PoseFrame> frames = new List<OvrAvatarDriver.PoseFrame>();
List<byte[]> encodedAudioPackets = new List<byte[]>();
public float Duration { get { return frameTimes[frameTimes.Count - 1]; } }
public OvrAvatarDriver.PoseFrame FinalFrame { get { return frames[frames.Count - 1]; } }
public OvrAvatarPacket()
{
}
public OvrAvatarPacket(OvrAvatarDriver.PoseFrame initialPose)
{
frameTimes.Add(0.0f);
frames.Add(initialPose);
}
OvrAvatarPacket(List<float> frameTimes, List<OvrAvatarDriver.PoseFrame> frames, List<byte[]> audioPackets)
{
this.frameTimes = frameTimes;
this.frames = frames;
}
public void AddFrame(OvrAvatarDriver.PoseFrame frame, float deltaSeconds)
{
frameTimes.Add(Duration + deltaSeconds);
frames.Add(frame);
}
public OvrAvatarDriver.PoseFrame GetPoseFrame(float seconds)
{
if (frames.Count == 1)
{
return frames[0];
}
// This can be replaced with a more efficient binary search
int tailIndex = 1;
while (tailIndex < frameTimes.Count && frameTimes[tailIndex] < seconds)
{
++tailIndex;
}
OvrAvatarDriver.PoseFrame a = frames[tailIndex - 1];
OvrAvatarDriver.PoseFrame b = frames[tailIndex];
float aTime = frameTimes[tailIndex - 1];
float bTime = frameTimes[tailIndex];
float t = (seconds - aTime) / (bTime - aTime);
return OvrAvatarDriver.PoseFrame.Interpolate(a, b, t);
}
public static OvrAvatarPacket Read(Stream stream)
{
BinaryReader reader = new BinaryReader(stream);
// Todo: bounds check frame count
int frameCount = reader.ReadInt32();
List<float> frameTimes = new List<float>(frameCount);
for (int i = 0; i < frameCount; ++i)
{
frameTimes.Add(reader.ReadSingle());
}
List<OvrAvatarDriver.PoseFrame> frames = new List<OvrAvatarDriver.PoseFrame>(frameCount);
for (int i = 0; i < frameCount; ++i)
{
frames.Add(reader.ReadPoseFrame());
}
// Todo: bounds check audio packet count
int audioPacketCount = reader.ReadInt32();
List<byte[]> audioPackets = new List<byte[]>(audioPacketCount);
for (int i = 0; i < audioPacketCount; ++i)
{
int audioPacketSize = reader.ReadInt32();
byte[] audioPacket = reader.ReadBytes(audioPacketSize);
audioPackets.Add(audioPacket);
}
return new OvrAvatarPacket(frameTimes, frames, audioPackets);
}
public void Write(Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);
// Write all of the frames
int frameCount = frameTimes.Count;
writer.Write(frameCount);
for (int i = 0; i < frameCount; ++i)
{
writer.Write(frameTimes[i]);
}
for (int i = 0; i < frameCount; ++i)
{
OvrAvatarDriver.PoseFrame frame = frames[i];
writer.Write(frame);
}
// Write all of the encoded audio packets
int audioPacketCount = encodedAudioPackets.Count;
writer.Write(audioPacketCount);
for (int i = 0; i < audioPacketCount; ++i)
{
byte[] packet = encodedAudioPackets[i];
writer.Write(packet.Length);
writer.Write(packet);
}
}
}
static class BinaryWriterExtensions
{
public static void Write(this BinaryWriter writer, OvrAvatarDriver.PoseFrame frame)
{
writer.Write(frame.headPosition);
writer.Write(frame.headRotation);
writer.Write(frame.handLeftPosition);
writer.Write(frame.handLeftRotation);
writer.Write(frame.handRightPosition);
writer.Write(frame.handRightRotation);
writer.Write(frame.voiceAmplitude);
writer.Write(frame.controllerLeftPose);
writer.Write(frame.controllerRightPose);
}
public static void Write(this BinaryWriter writer, Vector3 vec3)
{
writer.Write(vec3.x);
writer.Write(vec3.y);
writer.Write(vec3.z);
}
public static void Write(this BinaryWriter writer, Vector2 vec2)
{
writer.Write(vec2.x);
writer.Write(vec2.y);
}
public static void Write(this BinaryWriter writer, Quaternion quat)
{
writer.Write(quat.x);
writer.Write(quat.y);
writer.Write(quat.z);
writer.Write(quat.w);
}
public static void Write(this BinaryWriter writer, OvrAvatarDriver.ControllerPose pose)
{
writer.Write((uint)pose.buttons);
writer.Write((uint)pose.touches);
writer.Write(pose.joystickPosition);
writer.Write(pose.indexTrigger);
writer.Write(pose.handTrigger);
writer.Write(pose.isActive);
}
}
static class BinaryReaderExtensions
{
public static OvrAvatarDriver.PoseFrame ReadPoseFrame(this BinaryReader reader)
{
return new OvrAvatarDriver.PoseFrame
{
headPosition = reader.ReadVector3(),
headRotation = reader.ReadQuaternion(),
handLeftPosition = reader.ReadVector3(),
handLeftRotation = reader.ReadQuaternion(),
handRightPosition = reader.ReadVector3(),
handRightRotation = reader.ReadQuaternion(),
voiceAmplitude = reader.ReadSingle(),
controllerLeftPose = reader.ReadControllerPose(),
controllerRightPose = reader.ReadControllerPose(),
};
}
public static Vector2 ReadVector2(this BinaryReader reader)
{
return new Vector2
{
x = reader.ReadSingle(),
y = reader.ReadSingle()
};
}
public static Vector3 ReadVector3(this BinaryReader reader)
{
return new Vector3
{
x = reader.ReadSingle(),
y = reader.ReadSingle(),
z = reader.ReadSingle()
};
}
public static Quaternion ReadQuaternion(this BinaryReader reader)
{
return new Quaternion
{
x = reader.ReadSingle(),
y = reader.ReadSingle(),
z = reader.ReadSingle(),
w = reader.ReadSingle(),
};
}
public static OvrAvatarDriver.ControllerPose ReadControllerPose(this BinaryReader reader)
{
return new OvrAvatarDriver.ControllerPose
{
buttons = (ovrAvatarButton)reader.ReadUInt32(),
touches = (ovrAvatarTouch)reader.ReadUInt32(),
joystickPosition = reader.ReadVector2(),
indexTrigger = reader.ReadSingle(),
handTrigger = reader.ReadSingle(),
isActive = reader.ReadBoolean(),
};
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3b7dd866fbed2654e838d772129dc70c
timeCreated: 1464197799
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using Oculus.Avatar;
public class OvrAvatarRemoteDriver : OvrAvatarDriver
{
Queue<OvrAvatarPacket> packetQueue = new Queue<OvrAvatarPacket>();
IntPtr CurrentSDKPacket = IntPtr.Zero;
float CurrentPacketTime = 0f;
const int MinPacketQueue = 1;
const int MaxPacketQueue = 4;
int CurrentSequence = -1;
// Used for legacy Unity only packet blending
bool isStreaming = false;
OvrAvatarPacket currentPacket = null;
public void QueuePacket(int sequence, OvrAvatarPacket packet)
{
if (sequence > CurrentSequence)
{
CurrentSequence = sequence;
packetQueue.Enqueue(packet);
}
}
public override void UpdateTransforms(IntPtr sdkAvatar)
{
switch(Mode)
{
case PacketMode.SDK:
UpdateFromSDKPacket(sdkAvatar);
break;
case PacketMode.Unity:
UpdateFromUnityPacket(sdkAvatar);
break;
default:
break;
}
}
private void UpdateFromSDKPacket(IntPtr sdkAvatar)
{
if (CurrentSDKPacket == IntPtr.Zero && packetQueue.Count >= MinPacketQueue)
{
CurrentSDKPacket = packetQueue.Dequeue().ovrNativePacket;
}
if (CurrentSDKPacket != IntPtr.Zero)
{
float PacketDuration = CAPI.ovrAvatarPacket_GetDurationSeconds(CurrentSDKPacket);
CAPI.ovrAvatar_UpdatePoseFromPacket(sdkAvatar, CurrentSDKPacket, Mathf.Min(PacketDuration, CurrentPacketTime));
CurrentPacketTime += Time.deltaTime;
if (CurrentPacketTime > PacketDuration)
{
CAPI.ovrAvatarPacket_Free(CurrentSDKPacket);
CurrentSDKPacket = IntPtr.Zero;
CurrentPacketTime = CurrentPacketTime - PacketDuration;
//Throw away packets deemed too old.
while (packetQueue.Count > MaxPacketQueue)
{
packetQueue.Dequeue();
}
}
}
}
private void UpdateFromUnityPacket(IntPtr sdkAvatar)
{
// If we're not currently streaming, check to see if we've buffered enough
if (!isStreaming && packetQueue.Count > MinPacketQueue)
{
currentPacket = packetQueue.Dequeue();
isStreaming = true;
}
// If we are streaming, update our pose
if (isStreaming)
{
CurrentPacketTime += Time.deltaTime;
// If we've elapsed past our current packet, advance
while (CurrentPacketTime > currentPacket.Duration)
{
// If we're out of packets, stop streaming and
// lock to the final frame
if (packetQueue.Count == 0)
{
CurrentPose = currentPacket.FinalFrame;
CurrentPacketTime = 0.0f;
currentPacket = null;
isStreaming = false;
return;
}
while (packetQueue.Count > MaxPacketQueue)
{
packetQueue.Dequeue();
}
// Otherwise, dequeue the next packet
CurrentPacketTime -= currentPacket.Duration;
currentPacket = packetQueue.Dequeue();
}
// Compute the pose based on our current time offset in the packet
CurrentPose = currentPacket.GetPoseFrame(CurrentPacketTime);
UpdateTransformsFromPose(sdkAvatar);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c198a42a3843ca04fa633b60f428ff51
timeCreated: 1464302604
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,135 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Oculus.Avatar;
public class OvrAvatarRenderComponent : MonoBehaviour {
private bool firstSkinnedUpdate = true;
public SkinnedMeshRenderer mesh;
public Transform[] bones;
bool isBodyComponent = false;
protected void UpdateActive(OvrAvatar avatar, ovrAvatarVisibilityFlags mask)
{
bool doActiveHack = isBodyComponent && avatar.EnableExpressive && avatar.ShowFirstPerson && !avatar.ShowThirdPerson;
if (doActiveHack)
{
bool showFirstPerson = (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0;
bool showThirdPerson = (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0;
gameObject.SetActive(showThirdPerson || showThirdPerson);
if (!showFirstPerson)
{
mesh.enabled = false;
}
}
else
{
bool active = avatar.ShowFirstPerson && (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0;
active |= avatar.ShowThirdPerson && (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0;
this.gameObject.SetActive(active);
mesh.enabled = active;
}
}
protected SkinnedMeshRenderer CreateSkinnedMesh(ulong assetID, ovrAvatarVisibilityFlags visibilityMask, int thirdPersonLayer, int firstPersonLayer)
{
isBodyComponent = name.Contains("body");
OvrAvatarAssetMesh meshAsset = (OvrAvatarAssetMesh)OvrAvatarSDKManager.Instance.GetAsset(assetID);
if (meshAsset == null)
{
throw new Exception("Couldn't find mesh for asset " + assetID);
}
if ((visibilityMask & ovrAvatarVisibilityFlags.ThirdPerson) != 0)
{
this.gameObject.layer = thirdPersonLayer;
}
else
{
this.gameObject.layer = firstPersonLayer;
}
SkinnedMeshRenderer renderer = meshAsset.CreateSkinnedMeshRendererOnObject(gameObject);
#if UNITY_ANDROID
renderer.quality = SkinQuality.Bone2;
#else
renderer.quality = SkinQuality.Bone4;
#endif
renderer.updateWhenOffscreen = true;
if ((visibilityMask & ovrAvatarVisibilityFlags.SelfOccluding) == 0)
{
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
}
gameObject.SetActive(false);
return renderer;
}
protected void UpdateSkinnedMesh(OvrAvatar avatar, Transform[] bones, ovrAvatarTransform localTransform, ovrAvatarVisibilityFlags visibilityMask, IntPtr renderPart)
{
UpdateActive(avatar, visibilityMask);
OvrAvatar.ConvertTransform(localTransform, this.transform);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
UInt64 dirtyJoints;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRender:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRender_GetDirtyJoints(renderPart);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetDirtyJoints(renderPart);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetDirtyJoints(renderPart);
break;
default:
throw new Exception("Unhandled render part type: " + type);
}
for (UInt32 i = 0; i < 64; i++)
{
UInt64 dirtyMask = (ulong)1 << (int)i;
// We need to make sure that we fully update the initial position of
// Skinned mesh renderers, then, thereafter, we can only update dirty joints
if ((firstSkinnedUpdate && i < bones.Length) ||
(dirtyMask & dirtyJoints) != 0)
{
//This joint is dirty and needs to be updated
Transform targetBone = bones[i];
ovrAvatarTransform transform;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRender:
transform = CAPI.ovrAvatarSkinnedMeshRender_GetJointTransform(renderPart, i);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
transform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetJointTransform(renderPart, i);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
transform = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetJointTransform(renderPart, i);
break;
default:
throw new Exception("Unhandled render part type: " + type);
}
OvrAvatar.ConvertTransform(transform, targetBone);
}
}
firstSkinnedUpdate = false;
}
protected Material CreateAvatarMaterial(string name, Shader shader)
{
if (shader == null)
{
throw new Exception("No shader provided for avatar material.");
}
Material mat = new Material(shader);
mat.name = name;
return mat;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6a9e8691abb99884880df5ecada5e4d8
timeCreated: 1479155394
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0348026b48363904bb332b53a21c35b2
timeCreated: 1474928508
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,375 @@
using UnityEngine;
using Oculus.Avatar;
using System;
using System.Collections.Generic;
public delegate void specificationCallback(IntPtr specification);
public delegate void assetLoadedCallback(OvrAvatarAsset asset);
public delegate void combinedMeshLoadedCallback(IntPtr asset);
public class OvrAvatarSDKManager : MonoBehaviour
{
private static OvrAvatarSDKManager _instance;
private bool initialized = false;
private Dictionary<ulong, HashSet<specificationCallback>> specificationCallbacks;
private Dictionary<ulong, HashSet<assetLoadedCallback>> assetLoadedCallbacks;
private Dictionary<IntPtr, combinedMeshLoadedCallback> combinedMeshLoadedCallbacks;
private Dictionary<UInt64, OvrAvatarAsset> assetCache;
private OvrAvatarTextureCopyManager textureCopyManager;
public ovrAvatarLogLevel LoggingLevel = ovrAvatarLogLevel.Info;
private Queue<AvatarSpecRequestParams> avatarSpecificationQueue;
private List<int> loadingAvatars;
private bool avatarSpecRequestAvailable = true;
private float lastDispatchedAvatarSpecRequestTime = 0f;
private const float AVATAR_SPEC_REQUEST_TIMEOUT = 5f;
#if AVATAR_DEBUG
private ovrAvatarDebugContext debugContext = ovrAvatarDebugContext.None;
#endif
public struct AvatarSpecRequestParams
{
public UInt64 _userId;
public specificationCallback _callback;
public bool _useCombinedMesh;
public ovrAvatarAssetLevelOfDetail _lod;
public bool _forceMobileTextureFormat;
public ovrAvatarLookAndFeelVersion _lookVersion;
public ovrAvatarLookAndFeelVersion _fallbackVersion;
public bool _enableExpressive;
public AvatarSpecRequestParams(
UInt64 userId,
specificationCallback callback,
bool useCombinedMesh,
ovrAvatarAssetLevelOfDetail lod,
bool forceMobileTextureFormat,
ovrAvatarLookAndFeelVersion lookVersion,
ovrAvatarLookAndFeelVersion fallbackVersion,
bool enableExpressive)
{
_userId = userId;
_callback = callback;
_useCombinedMesh = useCombinedMesh;
_lod = lod;
_forceMobileTextureFormat = forceMobileTextureFormat;
_lookVersion = lookVersion;
_fallbackVersion = fallbackVersion;
_enableExpressive = enableExpressive;
}
}
public static OvrAvatarSDKManager Instance
{
get
{
if (_instance == null)
{
_instance = GameObject.FindObjectOfType<OvrAvatarSDKManager>();
if (_instance == null)
{
GameObject manager = new GameObject("OvrAvatarSDKManager");
_instance = manager.AddComponent<OvrAvatarSDKManager>();
_instance.textureCopyManager = manager.AddComponent<OvrAvatarTextureCopyManager>();
_instance.initialized = _instance.Initialize();
}
}
return _instance.initialized ? _instance : null;
}
}
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";
}
#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;
}
void OnDestroy()
{
CAPI.Shutdown();
CAPI.ovrAvatar_RegisterLoggingCallback(null);
CAPI.ovrAvatar_Shutdown();
}
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 bool IsAvatarSpecWaiting()
{
return avatarSpecificationQueue.Count > 0;
}
public bool IsAvatarLoading()
{
return loadingAvatars.Count > 0;
}
// Add avatar gameobject ID to loading list to keep track of loading avatars
public void AddLoadingAvatar(int gameobjectID)
{
loadingAvatars.Add(gameobjectID);
}
// Remove avatar gameobject ID from loading list
public void RemoveLoadingAvatar(int gameobjectID)
{
loadingAvatars.Remove(gameobjectID);
}
// 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());
}
private void DispatchAvatarSpecificationRequest(AvatarSpecRequestParams avatarSpecRequest)
{
textureCopyManager.CheckFallbackTextureSet(avatarSpecRequest._lod);
CAPI.ovrAvatar_SetForceASTCTextures(avatarSpecRequest._forceMobileTextureFormat);
HashSet<specificationCallback> callbackSet;
if (!specificationCallbacks.TryGetValue(avatarSpecRequest._userId, out callbackSet))
{
callbackSet = new HashSet<specificationCallback>();
specificationCallbacks.Add(avatarSpecRequest._userId, callbackSet);
IntPtr specRequest = CAPI.ovrAvatarSpecificationRequest_Create(avatarSpecRequest._userId);
CAPI.ovrAvatarSpecificationRequest_SetLookAndFeelVersion(specRequest, avatarSpecRequest._lookVersion);
CAPI.ovrAvatarSpecificationRequest_SetFallbackLookAndFeelVersion(specRequest, avatarSpecRequest._fallbackVersion);
CAPI.ovrAvatarSpecificationRequest_SetLevelOfDetail(specRequest, avatarSpecRequest._lod);
CAPI.ovrAvatarSpecificationRequest_SetCombineMeshes(specRequest, avatarSpecRequest._useCombinedMesh);
CAPI.ovrAvatarSpecificationRequest_SetExpressiveFlag(specRequest, avatarSpecRequest._enableExpressive);
CAPI.ovrAvatar_RequestAvatarSpecificationFromSpecRequest(specRequest);
CAPI.ovrAvatarSpecificationRequest_Destroy(specRequest);
}
callbackSet.Add(avatarSpecRequest._callback);
}
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);
}
public void RegisterCombinedMeshCallback(
IntPtr sdkAvatar,
combinedMeshLoadedCallback callback)
{
combinedMeshLoadedCallback currentCallback;
if (!combinedMeshLoadedCallbacks.TryGetValue(sdkAvatar, out currentCallback))
{
combinedMeshLoadedCallbacks.Add(sdkAvatar, callback);
}
else
{
throw new Exception("Adding second combind mesh callback for same avatar");
}
}
public OvrAvatarAsset GetAsset(UInt64 assetId)
{
OvrAvatarAsset asset;
if (assetCache.TryGetValue(assetId, out asset))
{
return asset;
}
else
{
return null;
}
}
public void DeleteAssetFromCache(UInt64 assetId)
{
if (assetCache.ContainsKey(assetId))
{
assetCache.Remove(assetId);
}
}
public string GetAppId()
{
return UnityEngine.Application.platform == RuntimePlatform.Android ?
OvrAvatarSettings.MobileAppID : OvrAvatarSettings.AppID;
}
public OvrAvatarTextureCopyManager GetTextureCopyManager()
{
if (textureCopyManager != null)
{
return textureCopyManager;
}
else
{
return null;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2ba08ec2733a3a54fbc9490f0f4ab2f0
timeCreated: 1475011862
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using UnityEngine;
using System.Collections;
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
#endif
public sealed class OvrAvatarSettings : ScriptableObject {
public static string AppID
{
get { return Instance.ovrAppID; }
set { Instance.ovrAppID = value; }
}
public static string MobileAppID
{
get { return Instance.ovrGearAppID; }
set { Instance.ovrGearAppID = value; }
}
private static OvrAvatarSettings instance;
public static OvrAvatarSettings Instance
{
get
{
if (instance == null)
{
instance = Resources.Load<OvrAvatarSettings>("OvrAvatarSettings");
// This can happen if the developer never input their App Id into the Unity Editor
// Use a dummy object with defaults for the getters so we don't have a null pointer exception
if (instance == null)
{
instance = ScriptableObject.CreateInstance<OvrAvatarSettings>();
#if UNITY_EDITOR
// Only in the editor should we save it to disk
string properPath = System.IO.Path.Combine(UnityEngine.Application.dataPath, "Resources");
if (!System.IO.Directory.Exists(properPath))
{
UnityEditor.AssetDatabase.CreateFolder("Assets", "Resources");
}
string fullPath = System.IO.Path.Combine(
System.IO.Path.Combine("Assets", "Resources"),
"OvrAvatarSettings.asset"
);
UnityEditor.AssetDatabase.CreateAsset(instance, fullPath);
#endif
}
}
return instance;
}
set
{
instance = value;
}
}
[SerializeField]
private string ovrAppID = "";
[SerializeField]
private string ovrGearAppID = "";
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 70c2f484f132c044097f03d65cac3b24
timeCreated: 1478024706
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
#if UNITY_EDITOR
using UnityEngine;
using System.Collections;
using UnityEditor;
using Oculus.Avatar;
[CustomEditor(typeof(OvrAvatarSettings))]
[InitializeOnLoadAttribute]
public class OvrAvatarSettingsEditor : Editor {
GUIContent appIDLabel = new GUIContent("Oculus Rift App Id [?]",
"This AppID will be used for OvrAvatar registration.");
GUIContent mobileAppIDLabel = new GUIContent("Oculus Go/Quest or Gear VR [?]",
"This AppID will be used when building to the Android target");
[UnityEditor.MenuItem("Oculus/Avatars/Edit Settings")]
public static void Edit()
{
var settings = OvrAvatarSettings.Instance;
UnityEditor.Selection.activeObject = settings;
CAPI.SendEvent("edit_settings");
}
static OvrAvatarSettingsEditor()
{
#if UNITY_2017_2_OR_NEWER
EditorApplication.playModeStateChanged += HandlePlayModeState;
#else
EditorApplication.playmodeStateChanged += () =>
{
if (EditorApplication.isPlaying)
{
CAPI.SendEvent("load", CAPI.AvatarSDKVersion.ToString());
}
};
#endif
}
#if UNITY_2017_2_OR_NEWER
private static void HandlePlayModeState(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredPlayMode)
{
CAPI.SendEvent("load", CAPI.AvatarSDKVersion.ToString());
}
}
#endif
private static string MakeTextBox(GUIContent label, string variable) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(label);
GUI.changed = false;
var result = EditorGUILayout.TextField(variable);
if (GUI.changed)
{
EditorUtility.SetDirty(OvrAvatarSettings.Instance);
GUI.changed = false;
}
EditorGUILayout.EndHorizontal();
return result;
}
public override void OnInspectorGUI()
{
EditorGUILayout.BeginVertical();
OvrAvatarSettings.AppID =
OvrAvatarSettingsEditor.MakeTextBox(appIDLabel, OvrAvatarSettings.AppID);
OvrAvatarSettings.MobileAppID =
OvrAvatarSettingsEditor.MakeTextBox(mobileAppIDLabel, OvrAvatarSettings.MobileAppID);
EditorGUILayout.EndVertical();
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1511f2aaa4ab15e4b8a0ac1a805a402b
timeCreated: 1478024800
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using UnityEngine;
using System.Collections;
using System;
using Oculus.Avatar;
public class OvrAvatarSkinnedMeshRenderComponent : OvrAvatarRenderComponent
{
Shader surface;
Shader surfaceSelfOccluding;
bool previouslyActive = false;
internal void Initialize(ovrAvatarRenderPart_SkinnedMeshRender skinnedMeshRender, Shader surface, Shader surfaceSelfOccluding, int thirdPersonLayer, int firstPersonLayer)
{
this.surfaceSelfOccluding = surfaceSelfOccluding != null ? surfaceSelfOccluding : Shader.Find("OvrAvatar/AvatarSurfaceShaderSelfOccluding");
this.surface = surface != null ? surface : Shader.Find("OvrAvatar/AvatarSurfaceShader");
this.mesh = CreateSkinnedMesh(skinnedMeshRender.meshAssetID, skinnedMeshRender.visibilityMask, thirdPersonLayer, firstPersonLayer);
bones = mesh.bones;
UpdateMeshMaterial(skinnedMeshRender.visibilityMask, mesh);
}
public void UpdateSkinnedMeshRender(OvrAvatarComponent component, OvrAvatar avatar, IntPtr renderPart)
{
ovrAvatarVisibilityFlags visibilityMask = CAPI.ovrAvatarSkinnedMeshRender_GetVisibilityMask(renderPart);
ovrAvatarTransform localTransform = CAPI.ovrAvatarSkinnedMeshRender_GetTransform(renderPart);
UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart);
UpdateMeshMaterial(visibilityMask, mesh);
bool isActive = this.gameObject.activeSelf;
if( mesh != null )
{
bool changedMaterial = CAPI.ovrAvatarSkinnedMeshRender_MaterialStateChanged(renderPart);
if (changedMaterial || (!previouslyActive && isActive))
{
ovrAvatarMaterialState materialState = CAPI.ovrAvatarSkinnedMeshRender_GetMaterialState(renderPart);
component.UpdateAvatarMaterial(mesh.sharedMaterial, materialState);
}
}
previouslyActive = isActive;
}
private void UpdateMeshMaterial(ovrAvatarVisibilityFlags visibilityMask, SkinnedMeshRenderer rootMesh)
{
Shader shader = (visibilityMask & ovrAvatarVisibilityFlags.SelfOccluding) != 0 ? surfaceSelfOccluding : surface;
if (rootMesh.sharedMaterial == null || rootMesh.sharedMaterial.shader != shader)
{
rootMesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4efdf8bc42b8b8843aff4ca38233f362
timeCreated: 1479156282
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using UnityEngine;
using System.Collections;
using System;
using Oculus.Avatar;
public class OvrAvatarSkinnedMeshRenderPBSComponent : OvrAvatarRenderComponent {
bool isMaterialInitilized = false;
internal void Initialize(ovrAvatarRenderPart_SkinnedMeshRenderPBS skinnedMeshRenderPBS, Shader shader, int thirdPersonLayer, int firstPersonLayer)
{
if (shader == null)
{
shader = Shader.Find("OvrAvatar/AvatarSurfaceShaderPBS");
}
mesh = CreateSkinnedMesh(skinnedMeshRenderPBS.meshAssetID, skinnedMeshRenderPBS.visibilityMask, thirdPersonLayer, firstPersonLayer);
mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader);
bones = mesh.bones;
}
internal void UpdateSkinnedMeshRenderPBS(OvrAvatar avatar, IntPtr renderPart, Material mat)
{
if (!isMaterialInitilized)
{
isMaterialInitilized = true;
UInt64 albedoTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetAlbedoTextureAssetID(renderPart);
UInt64 surfaceTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetSurfaceTextureAssetID(renderPart);
mat.SetTexture("_Albedo", OvrAvatarComponent.GetLoadedTexture(albedoTextureID));
mat.SetTexture("_Surface", OvrAvatarComponent.GetLoadedTexture(surfaceTextureID));
}
ovrAvatarVisibilityFlags visibilityMask = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetVisibilityMask(renderPart);
ovrAvatarTransform localTransform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetTransform(renderPart);
UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 69cc01a6441317c4c8a6e24d979cc1b0
timeCreated: 1479158964
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,347 @@
using UnityEngine;
using System.Collections.Generic;
using System;
using Oculus.Avatar;
public class OvrAvatarSkinnedMeshPBSV2RenderComponent : OvrAvatarRenderComponent
{
private OvrAvatarMaterialManager avatarMaterialManager;
private bool previouslyActive = false;
private bool isCombinedMaterial = false;
private ovrAvatarExpressiveParameters ExpressiveParameters;
private bool EnableExpressive = false;
private int blendShapeCount = 0;
private ovrAvatarBlendShapeParams blendShapeParams;
private const string MAIN_MATERIAL_NAME = "main_material";
private const string EYE_MATERIAL_NAME = "eye_material";
private const string DEFAULT_MATERIAL_NAME = "_material";
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 void UpdateSkinnedMeshRender(
OvrAvatarComponent component,
OvrAvatar avatar,
IntPtr renderPart)
{
ovrAvatarVisibilityFlags visibilityMask
= CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetVisibilityMask(renderPart);
ovrAvatarTransform localTransform
= CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetTransform(renderPart);
UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart);
bool isActive = gameObject.activeSelf;
if (mesh != null && !previouslyActive && isActive)
{
if (!isCombinedMaterial)
{
InitializeSingleComponentMaterial(renderPart, (int)avatar.LevelOfDetail - 1);
}
}
if (blendShapeCount > 0)
{
const float BLEND_MULTIPLIER = 100.0f;
CAPI.ovrAvatarSkinnedMeshRender_GetBlendShapeParams(renderPart, ref blendShapeParams);
for (uint i = 0; i < blendShapeParams.blendShapeParamCount && i < blendShapeCount; i++)
{
float value = blendShapeParams.blendShapeParams[i];
mesh.SetBlendShapeWeight((int)i, value * BLEND_MULTIPLIER);
}
}
previouslyActive = isActive;
}
private void InitializeSingleComponentMaterial(IntPtr renderPart, int lodIndex)
{
ovrAvatarPBSMaterialState materialState =
CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetPBSMaterialState(renderPart);
int componentType = (int)OvrAvatarMaterialManager.GetComponentType(gameObject.name);
Texture2D diffuseTexture = OvrAvatarComponent.GetLoadedTexture(materialState.albedoTextureID);
Texture2D normalTexture = OvrAvatarComponent.GetLoadedTexture(materialState.normalTextureID);
Texture2D metallicTexture = OvrAvatarComponent.GetLoadedTexture(materialState.metallicnessTextureID);
if (diffuseTexture != null)
{
avatarMaterialManager.AddTextureIDToTextureManager(materialState.albedoTextureID, true);
}
else
{
diffuseTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness;
}
diffuseTexture.anisoLevel = 4;
if (normalTexture != null)
{
avatarMaterialManager.AddTextureIDToTextureManager(materialState.normalTextureID, true);
}
else
{
normalTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].Normal;
}
normalTexture.anisoLevel = 4;
if (metallicTexture != null)
{
avatarMaterialManager.AddTextureIDToTextureManager(materialState.metallicnessTextureID, true);
}
else
{
metallicTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness;
}
metallicTexture.anisoLevel = 16;
mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_MAINTEX, diffuseTexture);
mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_NORMALMAP, normalTexture);
mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_ROUGHNESSMAP, metallicTexture);
mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_COLOR, materialState.albedoMultiplier);
mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_DIFFUSEINTENSITY,
OvrAvatarMaterialManager.DiffuseIntensities[componentType]);
mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_RIMINTENSITY,
OvrAvatarMaterialManager.RimIntensities[componentType]);
mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_REFLECTIONINTENSITY,
OvrAvatarMaterialManager.ReflectionIntensities[componentType]);
mesh.GetClosestReflectionProbes(avatarMaterialManager.ReflectionProbes);
if (avatarMaterialManager.ReflectionProbes != null &&
avatarMaterialManager.ReflectionProbes.Count > 0)
{
mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_CUBEMAP,
avatarMaterialManager.ReflectionProbes[0].probe.texture);
}
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);
}
}
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(materialStates);
}
}
private void SetMaterialTransparent(Material mat)
{
// Initialize shader to use transparent render queue with alpha blending
mat.SetOverrideTag("Queue", "Transparent");
mat.SetOverrideTag("RenderType", "Transparent");
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
mat.EnableKeyword("_ALPHATEST_ON");
mat.EnableKeyword("_ALPHABLEND_ON");
mat.EnableKeyword("_ALPHAPREMULTIPLY_ON");
mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
}
private void SetMaterialOpaque(Material mat)
{
// Initialize shader to use geometry render queue with no blending
mat.SetOverrideTag("Queue", "Geometry");
mat.SetOverrideTag("RenderType", "Opaque");
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
mat.DisableKeyword("_ALPHATEST_ON");
mat.DisableKeyword("_ALPHABLEND_ON");
mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c45906825d398024fbe09e47cc72de24
timeCreated: 1511398456
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,284 @@
using System.Collections;
using System.Collections.Generic;
using Oculus.Avatar;
using UnityEngine;
public class OvrAvatarTextureCopyManager : MonoBehaviour
{
[System.Serializable]
public struct FallbackTextureSet
{
public bool Initialized;
public Texture2D DiffuseRoughness;
public Texture2D Normal;
}
// Fallback texture sets are indexed with ovrAvatarAssetLevelOfDetail.
// We currently only use 1, 3 (mobile default), 5 (PC default).
public FallbackTextureSet[] FallbackTextureSets = new FallbackTextureSet[(int)ovrAvatarAssetLevelOfDetail.Highest + 1];
struct CopyTextureParams
{
public Texture Src;
public Texture Dst;
public int Mip;
public int SrcSize;
public int DstElement;
public CopyTextureParams(
Texture src,
Texture dst,
int mip,
int srcSize,
int dstElement)
{
Src = src;
Dst = dst;
Mip = mip;
SrcSize = srcSize;
DstElement = dstElement;
}
}
private Queue<CopyTextureParams> texturesToCopy;
public struct TextureSet
{
// Contains all texture asset IDs that are part of an avatar spec.
// Used by DeleteTextureSet().
// Textures that are part of combined mesh avatars can be safely deleted once they have been
// uploaded to the texture arrays.
// Textures that are part of single component meshes will remain in memory.
public Dictionary<ulong, bool> TextureIDSingleMeshPair;
public bool IsProcessed;
public TextureSet(
Dictionary<ulong, bool> textureIDSingleMeshPair,
bool isProcessed)
{
TextureIDSingleMeshPair = textureIDSingleMeshPair;
IsProcessed = isProcessed;
}
}
private Dictionary<int, TextureSet> textureSets;
private const int TEXTURES_TO_COPY_QUEUE_CAPACITY = 256;
private const int COPIES_PER_FRAME = 8;
// Fallback texture paths are indexed with ovrAvatarAssetLevelOfDetail
// We currently only use 1, 3 (mobile default), 5 (PC default)
private readonly string[] FALLBACK_TEXTURE_PATHS_DIFFUSE_ROUGHNESS = new string[]
{
"null",
PATH_LOWEST_DIFFUSE_ROUGHNESS,
"null",
PATH_MEDIUM_DIFFUSE_ROUGHNESS,
"null",
PATH_HIGHEST_DIFFUSE_ROUGHNESS,
};
private readonly string[] FALLBACK_TEXTURE_PATHS_NORMAL = new string[]
{
"null",
PATH_LOWEST_NORMAL,
"null",
PATH_MEDIUM_NORMAL,
"null",
PATH_HIGHEST_NORMAL,
};
private const string PATH_HIGHEST_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_2048";
private const string PATH_MEDIUM_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_1024";
private const string PATH_LOWEST_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_256";
private const string PATH_HIGHEST_NORMAL = "FallbackTextures/fallback_normal_2048";
private const string PATH_MEDIUM_NORMAL = "FallbackTextures/fallback_normal_1024";
private const string PATH_LOWEST_NORMAL = "FallbackTextures/fallback_normal_256";
private const int GPU_TEXTURE_COPY_WAIT_TIME = 10;
public OvrAvatarTextureCopyManager()
{
texturesToCopy = new Queue<CopyTextureParams>(TEXTURES_TO_COPY_QUEUE_CAPACITY);
textureSets = new Dictionary<int, TextureSet>();
}
public void Update()
{
if (texturesToCopy.Count == 0)
{
return;
}
lock (texturesToCopy)
{
for (int i = 0; i < Mathf.Min(COPIES_PER_FRAME, texturesToCopy.Count); ++i)
{
CopyTexture(texturesToCopy.Dequeue());
}
}
}
public int GetTextureCount()
{
return texturesToCopy.Count;
}
public void CopyTexture(
Texture src,
Texture dst,
int mipLevel,
int mipSize,
int dstElement,
bool useQueue = true)
{
var copyTextureParams = new CopyTextureParams(src, dst, mipLevel, mipSize, dstElement);
if (useQueue)
{
lock (texturesToCopy)
{
if (texturesToCopy.Count < TEXTURES_TO_COPY_QUEUE_CAPACITY)
{
texturesToCopy.Enqueue(copyTextureParams);
}
else
{
// Queue is full so copy texture immediately
CopyTexture(copyTextureParams);
}
}
}
else
{
CopyTexture(copyTextureParams);
}
}
private void CopyTexture(CopyTextureParams copyTextureParams)
{
Graphics.CopyTexture(
copyTextureParams.Src,
0,
copyTextureParams.Mip,
copyTextureParams.Dst,
copyTextureParams.DstElement,
copyTextureParams.Mip);
}
public void AddTextureIDToTextureSet(int gameobjectID, ulong textureID, bool isSingleMesh)
{
if (!textureSets.ContainsKey(gameobjectID))
{
TextureSet newTextureSet = new TextureSet(new Dictionary<ulong, bool>(), false);
newTextureSet.TextureIDSingleMeshPair.Add(textureID, isSingleMesh);
textureSets.Add(gameobjectID, newTextureSet);
}
else
{
bool TexIDSingleMesh;
if (textureSets[gameobjectID].TextureIDSingleMeshPair.TryGetValue(textureID, out TexIDSingleMesh))
{
if (!TexIDSingleMesh && isSingleMesh)
{
textureSets[gameobjectID].TextureIDSingleMeshPair[textureID] = true;
}
}
else
{
textureSets[gameobjectID].TextureIDSingleMeshPair.Add(textureID, isSingleMesh);
}
}
}
// This is called by a fully loaded avatar using combined mesh to safely delete unused textures.
public void DeleteTextureSet(int gameobjectID)
{
TextureSet textureSetToDelete;
if (!textureSets.TryGetValue(gameobjectID, out textureSetToDelete))
{
return;
};
if (textureSetToDelete.IsProcessed)
{
return;
}
StartCoroutine(DeleteTextureSetCoroutine(textureSetToDelete, gameobjectID));
}
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 void CheckFallbackTextureSet(ovrAvatarAssetLevelOfDetail lod)
{
if (FallbackTextureSets[(int)lod].Initialized)
{
return;
}
InitFallbackTextureSet(lod);
}
private void InitFallbackTextureSet(ovrAvatarAssetLevelOfDetail lod)
{
FallbackTextureSets[(int)lod].DiffuseRoughness = FallbackTextureSets[(int)lod].DiffuseRoughness =
Resources.Load<Texture2D>(FALLBACK_TEXTURE_PATHS_DIFFUSE_ROUGHNESS[(int)lod]);
FallbackTextureSets[(int)lod].Normal = FallbackTextureSets[(int)lod].Normal =
Resources.Load<Texture2D>(FALLBACK_TEXTURE_PATHS_NORMAL[(int)lod]);
FallbackTextureSets[(int)lod].Initialized = true;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bb5b00817cd46d645ac8b607693c37ce
timeCreated: 1519680044
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using Oculus.Avatar;
public class OvrAvatarTouchController : OvrAvatarComponent
{
public bool isLeftHand = true;
ovrAvatarControllerComponent component = new ovrAvatarControllerComponent();
void Update()
{
if (owner == null)
{
return;
}
bool hasComponent = false;
if (isLeftHand)
{
hasComponent = CAPI.ovrAvatarPose_GetLeftControllerComponent(owner.sdkAvatar, ref component);
}
else
{
hasComponent = CAPI.ovrAvatarPose_GetRightControllerComponent(owner.sdkAvatar, ref component);
}
if (hasComponent)
{
UpdateAvatar(component.renderComponent);
}
else
{
if (isLeftHand)
{
owner.ControllerLeft = null;
}
else
{
owner.ControllerRight = null;
}
Destroy(this);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 77e19ec58d4a9e844970103e5bd8946a
timeCreated: 1464050556
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: