1
0
mirror of https://github.com/xiaopeng12138/MaiDXR.git synced 2024-12-18 20:05:52 +01:00
MaiDXR/Assets/Oculus/VR/Scripts/OVRGLTFAccessor.cs

443 lines
13 KiB
C#
Raw Normal View History

2022-08-20 21:35:57 +02:00
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus 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);
}
}