Heroes_of_Hiis/Assets/Oculus/VR/Scripts/OVRGLTFAccessor.cs

435 lines
13 KiB
C#

/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine;
using OVRSimpleJSON;
using Unity.Jobs;
using Unity.Collections;
public enum OVRGLTFType
{
NONE,
SCALAR,
VEC2,
VEC3,
VEC4,
MAT4,
}
public enum OVRGLTFComponentType
{
BYTE = 5120,
UNSIGNED_BYTE = 5121,
SHORT = 5122,
UNSIGNED_SHORT = 5123,
UNSIGNED_INT = 5125,
FLOAT = 5126,
}
public class OVRGLTFAccessor
{
// Buffer View parameters
private int byteOffset;
private int byteLength;
private int byteStride;
private int bufferId;
private int bufferLength;
// Accessor parameters
private int additionalOffset;
private OVRGLTFType dataType;
private OVRGLTFComponentType componentType;
private int dataCount;
public OVRGLTFAccessor(JSONNode node, JSONNode root, bool bufferViewOnly = false)
{
JSONNode jsonBufferView = node;
if (!bufferViewOnly)
{
additionalOffset = node["byteOffset"].AsInt;
dataType = ToOVRType(node["type"].Value);
componentType = (OVRGLTFComponentType)node["componentType"].AsInt;
dataCount = node["count"].AsInt;
int bufferViewId = node["bufferView"].AsInt;
jsonBufferView = root["bufferViews"][bufferViewId];
}
int bufferId = jsonBufferView["buffer"].AsInt;
byteOffset = jsonBufferView["byteOffset"].AsInt;
byteLength = jsonBufferView["byteLength"].AsInt;
byteStride = jsonBufferView["byteStride"].AsInt;
var jsonBuffer = root["buffers"][bufferId];
bufferLength = jsonBuffer["byteLength"].AsInt;
}
public int GetDataCount()
{
return dataCount;
}
private static OVRGLTFType ToOVRType(string type)
{
switch(type)
{
case "SCALAR":
return OVRGLTFType.SCALAR;
case "VEC2":
return OVRGLTFType.VEC2;
case "VEC3":
return OVRGLTFType.VEC3;
case "VEC4":
return OVRGLTFType.VEC4;
case "MAT4":
return OVRGLTFType.MAT4;
default:
Debug.LogError("Unsupported accessor type.");
return OVRGLTFType.NONE;
}
}
public void ReadAsInt(OVRBinaryChunk chunk, ref int[] data, int offset)
{
if (dataType != OVRGLTFType.SCALAR)
{
Debug.LogError("Tried to read non-scalar data as a uint array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int stride = byteStride > 0 ? byteStride : GetStrideForType(componentType);
for(int i = 0; i < dataCount; i++)
{
data[offset + i] = (int)ReadElementAsUint(bufferData, i * stride, componentType);
}
}
public void ReadAsVector2(OVRBinaryChunk chunk, ref Vector2[] data, int offset)
{
if (dataType != OVRGLTFType.VEC2)
{
Debug.LogError("Tried to read non-vec3 data as a vec2 array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * 2;
for (int i = 0; i < dataCount; i++)
{
if (componentType == OVRGLTFComponentType.FLOAT)
{
data[offset + i].x = ReadElementAsFloat(bufferData, i * stride);
data[offset + i].y = ReadElementAsFloat(bufferData, i * stride + dataTypeSize);
}
}
}
public void ReadAsVector3(OVRBinaryChunk chunk, ref Vector3[] data, int offset, Vector3 conversionScale)
{
if (dataType != OVRGLTFType.VEC3)
{
Debug.LogError("Tried to read non-vec3 data as a vec3 array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * 3;
for (int i = 0; i < dataCount; i++)
{
if (componentType == OVRGLTFComponentType.FLOAT)
{
data[offset + i].x = ReadElementAsFloat(bufferData, i * stride);
data[offset + i].y = ReadElementAsFloat(bufferData, i * stride + dataTypeSize);
data[offset + i].z = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 2);
}
else
{
data[offset + i].x = ReadElementAsUint(bufferData, i * stride, componentType);
data[offset + i].y = ReadElementAsUint(bufferData, i * stride + dataTypeSize, componentType);
data[offset + i].z = ReadElementAsUint(bufferData, i * stride + dataTypeSize * 2, componentType);
}
data[offset + i].Scale(conversionScale);
}
}
public void ReadAsVector4(OVRBinaryChunk chunk, ref Vector4[] data, int offset, Vector4 conversionScale)
{
if (dataType != OVRGLTFType.VEC4)
{
Debug.LogError("Tried to read non-vec4 data as a vec4 array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * 4;
for (int i = 0; i < dataCount; i++)
{
if (componentType == OVRGLTFComponentType.FLOAT)
{
data[offset + i].x = ReadElementAsFloat(bufferData, i * stride);
data[offset + i].y = ReadElementAsFloat(bufferData, i * stride + dataTypeSize);
data[offset + i].z = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 2);
data[offset + i].w = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 3);
}
else
{
data[offset + i].x = ReadElementAsUint(bufferData, i * stride, componentType);
data[offset + i].y = ReadElementAsUint(bufferData, i * stride + dataTypeSize, componentType);
data[offset + i].z = ReadElementAsUint(bufferData, i * stride + dataTypeSize * 2, componentType);
data[offset + i].w = ReadElementAsUint(bufferData, i * stride + dataTypeSize * 3, componentType);
}
data[offset + i].Scale(conversionScale);
}
}
public void ReadAsColor(OVRBinaryChunk chunk, ref Color[] data, int offset)
{
if (dataType != OVRGLTFType.VEC4 && dataType != OVRGLTFType.VEC3)
{
Debug.LogError("Tried to read non-color type as a color array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int vecSize = dataType == OVRGLTFType.VEC3 ? 3 : 4;
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * vecSize;
float maxValue = GetMaxValueForType(componentType);
for (int i = 0; i < dataCount; i++)
{
if (componentType == OVRGLTFComponentType.FLOAT)
{
data[offset + i].r = ReadElementAsFloat(bufferData, i * stride);
data[offset + i].g = ReadElementAsFloat(bufferData, i * stride + dataTypeSize);
data[offset + i].b = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 2);
data[offset + i].a = dataType == OVRGLTFType.VEC3 ? 1.0f : ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 3);
}
else
{
data[offset + i].r = ReadElementAsUint(bufferData, i * stride, componentType) / maxValue;
data[offset + i].g = ReadElementAsUint(bufferData, i * stride + dataTypeSize, componentType) / maxValue;
data[offset + i].b = ReadElementAsUint(bufferData, i * stride + dataTypeSize * 2, componentType) / maxValue;
data[offset + i].a = dataType == OVRGLTFType.VEC3 ? 1.0f : ReadElementAsUint(bufferData, i * stride + dataTypeSize * 3, componentType) / maxValue;
}
}
}
public void ReadAsMatrix4x4(OVRBinaryChunk chunk, ref Matrix4x4[] data, int offset, Vector3 conversionScale)
{
if (dataType != OVRGLTFType.MAT4)
{
Debug.LogError("Tried to read non-vec3 data as a vec3 array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * 16;
Matrix4x4 scale = Matrix4x4.Scale(conversionScale);
for (int i = 0; i < dataCount; i++)
{
for (int m = 0; m < 16; m++)
{
data[offset + i][m] = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * m);
}
data[offset + i] = scale * data[offset + i] * scale;
}
}
public byte[] ReadAsKtxTexture(OVRBinaryChunk chunk)
{
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return null;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
return bufferData;
}
public void ReadAsBoneWeights(OVRBinaryChunk chunk, ref Vector4[] data, int offset)
{
if (dataType != OVRGLTFType.VEC4)
{
Debug.LogError("Tried to read bone weights data as a non-vec4 array.");
return;
}
if (chunk.chunkLength != bufferLength)
{
Debug.LogError("Chunk length is not equal to buffer length.");
return;
}
byte[] bufferData = new byte[byteLength];
chunk.chunkStream.Seek(chunk.chunkStart + byteOffset + additionalOffset, SeekOrigin.Begin);
chunk.chunkStream.Read(bufferData, 0, byteLength);
int dataTypeSize = GetStrideForType(componentType);
int stride = byteStride > 0 ? byteStride : dataTypeSize * 4;
for (int i = 0; i < dataCount; i++)
{
data[offset + i].x = ReadElementAsFloat(bufferData, i * stride);
data[offset + i].y = ReadElementAsFloat(bufferData, i * stride + dataTypeSize);
data[offset + i].z = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 2);
data[offset + i].w = ReadElementAsFloat(bufferData, i * stride + dataTypeSize * 3);
float weightSum = data[offset + i].x + data[offset + i].y + data[offset + i].z + data[offset + i].w;
if (!Mathf.Approximately(weightSum, 0))
{
data[offset + i] /= weightSum;
}
}
}
private int GetStrideForType(OVRGLTFComponentType type)
{
switch (type)
{
case OVRGLTFComponentType.BYTE:
return sizeof(sbyte);
case OVRGLTFComponentType.UNSIGNED_BYTE:
return sizeof(byte);
case OVRGLTFComponentType.SHORT:
return sizeof(short);
case OVRGLTFComponentType.UNSIGNED_SHORT:
return sizeof(ushort);
case OVRGLTFComponentType.UNSIGNED_INT:
return sizeof(uint);
case OVRGLTFComponentType.FLOAT:
return sizeof(float);
default:
return 0;
}
}
private float GetMaxValueForType(OVRGLTFComponentType type)
{
switch (type)
{
case OVRGLTFComponentType.BYTE:
return sbyte.MaxValue;
case OVRGLTFComponentType.UNSIGNED_BYTE:
return byte.MaxValue;
case OVRGLTFComponentType.SHORT:
return short.MaxValue;
case OVRGLTFComponentType.UNSIGNED_SHORT:
return ushort.MaxValue;
case OVRGLTFComponentType.UNSIGNED_INT:
return uint.MaxValue;
case OVRGLTFComponentType.FLOAT:
return float.MaxValue;
default:
return 0;
}
}
private uint ReadElementAsUint(byte[] data, int index, OVRGLTFComponentType type)
{
switch(type)
{
case OVRGLTFComponentType.BYTE:
return (uint)Convert.ToSByte(data[index]);
case OVRGLTFComponentType.UNSIGNED_BYTE:
return data[index];
case OVRGLTFComponentType.SHORT:
return (uint)BitConverter.ToInt16(data, index);
case OVRGLTFComponentType.UNSIGNED_SHORT:
return BitConverter.ToUInt16(data, index);
case OVRGLTFComponentType.UNSIGNED_INT:
return BitConverter.ToUInt32(data, index);
default:
Debug.Log(String.Format("Failed to read Component Type {0} as a uint.", type));
return 0;
}
}
private float ReadElementAsFloat(byte[] data, int index)
{
return BitConverter.ToSingle(data, index);
}
}