clean project
This commit is contained in:
56
Assets/Oculus/Avatar/Scripts/GazeTarget.cs
Normal file
56
Assets/Oculus/Avatar/Scripts/GazeTarget.cs
Normal 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
|
||||
};
|
||||
}
|
||||
}
|
||||
11
Assets/Oculus/Avatar/Scripts/GazeTarget.cs.meta
Normal file
11
Assets/Oculus/Avatar/Scripts/GazeTarget.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bfcd054df64e334ba2f191666f3fe92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1311
Assets/Oculus/Avatar/Scripts/OvrAvatar.cs
Normal file
1311
Assets/Oculus/Avatar/Scripts/OvrAvatar.cs
Normal file
File diff suppressed because it is too large
Load Diff
12
Assets/Oculus/Avatar/Scripts/OvrAvatar.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatar.cs.meta
Normal 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:
|
||||
5
Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs
Normal file
5
Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System;
|
||||
|
||||
public class OvrAvatarAsset {
|
||||
public UInt64 assetID;
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs.meta
Normal 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:
|
||||
279
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs
Normal file
279
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs.meta
Normal 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:
|
||||
70
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs
Normal file
70
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs.meta
Normal 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:
|
||||
24
Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs
Normal file
24
Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs.meta
Normal 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:
|
||||
43
Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs
Normal file
43
Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs.meta
Normal 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:
|
||||
145
Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs
Normal file
145
Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs.meta
Normal 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:
|
||||
108
Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs
Normal file
108
Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs.meta
Normal 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:
|
||||
48
Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs
Normal file
48
Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs.meta
Normal 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:
|
||||
84
Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs
Normal file
84
Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs.meta
Normal 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:
|
||||
45
Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs
Normal file
45
Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs.meta
Normal 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:
|
||||
430
Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs
Normal file
430
Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a139d83bf6796734db220df8a5bfacbd
|
||||
timeCreated: 1518209612
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
231
Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs
Normal file
231
Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs
Normal 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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs.meta
Normal 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:
|
||||
121
Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs
Normal file
121
Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs.meta
Normal 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:
|
||||
135
Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs
Normal file
135
Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a9e8691abb99884880df5ecada5e4d8
|
||||
timeCreated: 1479155394
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1663
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs
Normal file
1663
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs
Normal file
File diff suppressed because it is too large
Load Diff
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs.meta
Normal 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:
|
||||
375
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs
Normal file
375
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs.meta
Normal 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:
|
||||
65
Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs
Normal file
65
Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs
Normal 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 = "";
|
||||
}
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs.meta
Normal 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:
|
||||
72
Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs
Normal file
72
Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs
Normal 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
|
||||
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs.meta
Normal file
12
Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs.meta
Normal 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:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4efdf8bc42b8b8843aff4ca38233f362
|
||||
timeCreated: 1479156282
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69cc01a6441317c4c8a6e24d979cc1b0
|
||||
timeCreated: 1479158964
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c45906825d398024fbe09e47cc72de24
|
||||
timeCreated: 1511398456
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
284
Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs
Normal file
284
Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb5b00817cd46d645ac8b607693c37ce
|
||||
timeCreated: 1519680044
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
44
Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs
Normal file
44
Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77e19ec58d4a9e844970103e5bd8946a
|
||||
timeCreated: 1464050556
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user