diff --git a/Runtime/Scripts/BoneWeightData.cs b/Runtime/Scripts/BoneWeightData.cs
index 8bd2edd..847f4d3 100644
--- a/Runtime/Scripts/BoneWeightData.cs
+++ b/Runtime/Scripts/BoneWeightData.cs
@@ -37,6 +37,16 @@ public void ApplyOnMesh(Mesh mesh)
mesh.SetBoneWeights(m_BonesPerVertex, m_BoneWeights);
}
+ ///
+ /// Assigns the weight and index buffers as outputs to the GetDracoBonesJob job
+ ///
+ ///
+ internal void AssignToJob(ref DracoNative.GetDracoBonesJob job)
+ {
+ job.bonesPerVertex = m_BonesPerVertex;
+ job.boneWeights = m_BoneWeights;
+ }
+
///
/// Releases allocated resources.
///
diff --git a/Runtime/Scripts/DracoDecoder.cs b/Runtime/Scripts/DracoDecoder.cs
index e8764e4..10f4c3b 100644
--- a/Runtime/Scripts/DracoDecoder.cs
+++ b/Runtime/Scripts/DracoDecoder.cs
@@ -157,6 +157,86 @@ DecodeSettings decodeSettings
return await DecodeMesh(encodedData, decodeSettings, null);
}
+ public static async Task DecodeMesh(
+ NativeSlice[] encodedDataArray,
+ DecodeSettings decodeSettings,
+ Dictionary[] attributeIdMaps,
+ int[] vertexIntervals,
+ int[] indicesIntervals,
+ Bounds?[] bounds
+ )
+ {
+ CertifySupportedPlatform(
+#if UNITY_EDITOR
+ false
+#endif
+ );
+
+ var meshDataArray = Mesh.AllocateWritableMeshData(1);
+ var mesh = meshDataArray[0];
+ Bounds combinedBounds = default;
+ bool calculateNormals = false;
+ BoneWeightData boneWeightData = null;
+
+ for (var i = 0; i < encodedDataArray.Length; i++)
+ {
+ var encodedData = encodedDataArray[i];
+ var attributeIdMap = attributeIdMaps[i];
+ var encodedDataPtr = GetUnsafeReadOnlyIntPtr(encodedData);
+
+ var result = await DecodeMesh(
+ mesh,
+ encodedDataPtr,
+ encodedData.Length,
+ decodeSettings,
+ attributeIdMap,
+ i,
+ vertexIntervals,
+ indicesIntervals,
+ bounds,
+ boneWeightData
+ );
+ if (!result.success)
+ {
+ meshDataArray.Dispose();
+ return null;
+ }
+
+ boneWeightData = result.boneWeightData;
+
+ if (i == 0)
+ combinedBounds = result.bounds;
+ else
+ combinedBounds.Encapsulate(result.bounds);
+
+ calculateNormals |= result.calculateNormals;
+ }
+
+ var unityMesh = new Mesh();
+ Mesh.ApplyAndDisposeWritableMeshData(meshDataArray, unityMesh);
+ unityMesh.bounds = combinedBounds;
+ if (boneWeightData != null)
+ {
+ boneWeightData.ApplyOnMesh(unityMesh);
+ boneWeightData.Dispose();
+ }
+
+ if (unityMesh.GetTopology(0) == MeshTopology.Triangles)
+ {
+ if (calculateNormals)
+ {
+ unityMesh.RecalculateNormals();
+ }
+
+ if ((decodeSettings & DecodeSettings.RequireTangents) != 0)
+ {
+ unityMesh.RecalculateTangents();
+ }
+ }
+
+ return unityMesh;
+ }
+
///
/// Attribute type to index map
public static async Task DecodeMesh(
@@ -291,7 +371,7 @@ Dictionary attributeIdMap
decodeSettings,
attributeIdMap
#if UNITY_EDITOR
- ,sync
+ , sync: sync
#endif
);
UnsafeUtility.ReleaseGCObject(gcHandle);
@@ -320,13 +400,18 @@ static async Task DecodeMesh(
IntPtr encodedData,
int size,
DecodeSettings decodeSettings,
- Dictionary attributeIdMap
+ Dictionary attributeIdMap,
+ int submeshIndex = 0,
+ int[] vertexIntervals = null,
+ int[] indicesIntervals = null,
+ Bounds?[] bounds = null,
+ BoneWeightData boneWeightData = null
#if UNITY_EDITOR
,bool sync = false
#endif
)
{
- var dracoNative = new DracoNative(meshData, decodeSettings);
+ var dracoNative = new DracoNative(meshData, decodeSettings, submeshIndex, vertexIntervals, indicesIntervals, bounds?[submeshIndex], boneWeightData);
#if UNITY_EDITOR
if (sync) {
@@ -363,19 +448,12 @@ Dictionary attributeIdMap
return new DecodeResult();
}
- var bounds = dracoNative.CreateBounds();
- var success = dracoNative.PopulateMeshData(bounds);
- BoneWeightData boneWeightData = null;
- if (success && dracoNative.hasBoneWeightData)
- {
- boneWeightData = new BoneWeightData(dracoNative.bonesPerVertex, dracoNative.boneWeights);
- dracoNative.DisposeBoneWeightData();
- }
+ var success = dracoNative.PopulateMeshData(out var subMeshBounds);
return new DecodeResult(
success,
- bounds,
+ subMeshBounds,
calculateNormals,
- boneWeightData
+ dracoNative.boneWeightData
);
}
diff --git a/Runtime/Scripts/DracoMeshLoader.cs b/Runtime/Scripts/DracoMeshLoader.cs
deleted file mode 100644
index a8e4f0e..0000000
--- a/Runtime/Scripts/DracoMeshLoader.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-FileCopyrightText: 2023 Unity Technologies and the Draco for Unity authors
-// SPDX-License-Identifier: Apache-2.0
-
-using System;
-using System.Threading.Tasks;
-using Unity.Collections;
-using UnityEngine;
-
-namespace Draco
-{
- ///
- /// Obsolete! Please use instead. Provides Draco mesh decoding.
- ///
- ///
- [Obsolete("Use DracoDecoder.DecodeMesh methods instead.")]
- public class DracoMeshLoader
- {
- ///
- /// If true, coordinate space is converted from right-hand (like in glTF) to left-hand (Unity).
- ///
- readonly bool m_ConvertSpace;
-
- ///
- /// Create a DracoMeshLoader instance which let's you decode Draco data.
- ///
- /// If true, coordinate space is converted from right-hand (like in glTF) to left-hand (Unity).
- public DracoMeshLoader(bool convertSpace = true)
- {
- m_ConvertSpace = convertSpace;
- }
-
- ///
- /// Decodes a Draco mesh
- ///
- /// Compressed Draco data
- /// If draco does not contain normals and this is set to true, normals are calculated.
- /// If draco does not contain tangents and this is set to true, tangents and normals are calculated.
- /// Draco attribute ID that contains bone weights (for skinning)
- /// Draco attribute ID that contains bone joint indices (for skinning)
- /// Enforces vertex buffer layout with highest compatibility. Enable this if you want to use blend shapes on the resulting mesh
- /// Unity Mesh or null in case of errors
- ///
- [Obsolete("Use DracoDecoder.DecodeMesh instead.")]
- public async Task ConvertDracoMeshToUnity(
- NativeSlice encodedData,
- bool requireNormals = false,
- bool requireTangents = false,
- int weightsAttributeId = -1,
- int jointsAttributeId = -1,
- bool forceUnityLayout = false
- )
- {
- return await DracoDecoder.DecodeMesh(
- encodedData,
- CreateDecodeSettings(requireNormals, requireTangents, forceUnityLayout),
- DracoDecoder.CreateAttributeIdMap(weightsAttributeId, jointsAttributeId)
- );
- }
-
- ///
- /// Decodes a Draco mesh
- ///
- /// Compressed Draco data
- /// If draco does not contain normals and this is set to true, normals are calculated.
- /// If draco does not contain tangents and this is set to true, tangents and normals are calculated.
- /// Draco attribute ID that contains bone weights (for skinning)
- /// Draco attribute ID that contains bone joint indices (for skinning)
- /// Enforces vertex buffer layout with highest compatibility. Enable this if you want to use blend shapes on the resulting mesh
- /// Unity Mesh or null in case of errors
- ///
- [Obsolete("Use DracoDecoder.DecodeMesh instead.")]
- public async Task ConvertDracoMeshToUnity(
- byte[] encodedData,
- bool requireNormals = false,
- bool requireTangents = false,
- int weightsAttributeId = -1,
- int jointsAttributeId = -1,
- bool forceUnityLayout = false
- )
- {
- return await DracoDecoder.DecodeMesh(
- encodedData,
- CreateDecodeSettings(requireNormals, requireTangents, forceUnityLayout),
- DracoDecoder.CreateAttributeIdMap(weightsAttributeId, jointsAttributeId)
- );
- }
-
- ///
- /// Decodes a Draco mesh
- ///
- /// MeshData used to create the mesh
- /// Compressed Draco data
- /// If draco does not contain normals and this is set to true, normals are calculated.
- /// If draco does not contain tangents and this is set to true, tangents and normals are calculated.
- /// Draco attribute ID that contains bone weights (for skinning)
- /// Draco attribute ID that contains bone joint indices (for skinning)
- /// Enforces vertex buffer layout with highest compatibility. Enable this if you want to use blend shapes on the resulting mesh
- /// A DecodeResult
- ///
- [Obsolete("Use DracoDecoder.DecodeMesh instead.")]
- public async Task ConvertDracoMeshToUnity(
- Mesh.MeshData mesh,
- byte[] encodedData,
- bool requireNormals = false,
- bool requireTangents = false,
- int weightsAttributeId = -1,
- int jointsAttributeId = -1,
- bool forceUnityLayout = false
- )
- {
- return await DracoDecoder.DecodeMesh(
- mesh,
- encodedData,
- CreateDecodeSettings(requireNormals, requireTangents, forceUnityLayout),
- DracoDecoder.CreateAttributeIdMap(weightsAttributeId, jointsAttributeId)
- );
- }
-
- ///
- /// Decodes a Draco mesh
- ///
- /// MeshData used to create the mesh
- /// Compressed Draco data
- /// If draco does not contain normals and this is set to true, normals are calculated.
- /// If draco does not contain tangents and this is set to true, tangents and normals are calculated.
- /// Draco attribute ID that contains bone weights (for skinning)
- /// Draco attribute ID that contains bone joint indices (for skinning)
- /// Enforces vertex buffer layout with highest compatibility. Enable this if you want to use blend shapes on the resulting mesh
- /// A DecodeResult
- ///
- [Obsolete("Use DracoDecoder.DecodeMesh instead.")]
- public async Task ConvertDracoMeshToUnity(
- Mesh.MeshData mesh,
- NativeArray encodedData,
- bool requireNormals = false,
- bool requireTangents = false,
- int weightsAttributeId = -1,
- int jointsAttributeId = -1,
- bool forceUnityLayout = false
- )
- {
- return await DracoDecoder.DecodeMesh(
- mesh,
- encodedData,
- CreateDecodeSettings(requireNormals, requireTangents, forceUnityLayout),
- DracoDecoder.CreateAttributeIdMap(weightsAttributeId, jointsAttributeId)
- );
- }
-
- DecodeSettings CreateDecodeSettings(bool requireNormals, bool requireTangents, bool forceUnityLayout)
- {
- var flags = DecodeSettings.None;
- if (requireNormals) flags |= DecodeSettings.RequireNormals;
- if (requireTangents) flags |= DecodeSettings.RequireTangents;
- if (forceUnityLayout) flags |= DecodeSettings.ForceUnityVertexLayout;
- if (m_ConvertSpace) flags |= DecodeSettings.ConvertSpace;
- return flags;
- }
- }
-}
diff --git a/Runtime/Scripts/DracoMeshLoader.cs.meta b/Runtime/Scripts/DracoMeshLoader.cs.meta
deleted file mode 100644
index dfb7fe8..0000000
--- a/Runtime/Scripts/DracoMeshLoader.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 0c6cd7d1ea670421cb7d7e71240d682d
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/Runtime/Scripts/DracoNative.cs b/Runtime/Scripts/DracoNative.cs
index e9ed386..368e56e 100644
--- a/Runtime/Scripts/DracoNative.cs
+++ b/Runtime/Scripts/DracoNative.cs
@@ -68,6 +68,11 @@ unsafe class DracoNative
Mesh.MeshData m_Mesh;
int m_IndicesCount;
+ private readonly int m_SubMeshIndex;
+ private int[] m_VertexIntervals;
+ private int[] m_IndicesIntervals;
+ private readonly bool m_SetupBuffers = true;
+ private Bounds? m_Bounds;
// START BLEND-HACK
// TODO: Unity does not support setting bone weights and indices via new Mesh API
@@ -77,8 +82,7 @@ unsafe class DracoNative
AttributeMap m_BoneIndexMap;
AttributeMap m_BoneWeightMap;
public bool hasBoneWeightData => m_BoneIndexMap != null && m_BoneWeightMap != null;
- public NativeArray bonesPerVertex;
- public NativeArray boneWeights;
+ public BoneWeightData boneWeightData;
// END BLEND-HACK
public DracoNative(
@@ -90,6 +94,19 @@ DecodeSettings decodeSettings
m_Mesh = mesh;
}
+ public DracoNative(Mesh.MeshData mesh, DecodeSettings decodeSettings, int subMeshIndex, int[] vertexIntervals,
+ int[] indicesIntervals, Bounds? bounds, BoneWeightData boneWeightData)
+ {
+ m_DecodeSettings = decodeSettings;
+ m_Mesh = mesh;
+ m_SubMeshIndex = subMeshIndex;
+ m_VertexIntervals = vertexIntervals;
+ m_IndicesIntervals = indicesIntervals;
+ m_SetupBuffers = subMeshIndex == 0;
+ m_Bounds = bounds;
+ this.boneWeightData = boneWeightData;
+ }
+
public JobHandle Init(IntPtr encodedData, int size)
{
var decodeJob = CreateDecodeJob(encodedData, size);
@@ -122,11 +139,10 @@ public bool ErrorOccured()
return m_DracoDecodeResult[0] < 0;
}
- void CalculateVertexParams(
- DracoMesh* dracoMesh,
+ void CalculateVertexParams(DracoMesh* dracoMesh,
Dictionary attributeIdMap,
- out bool calculateNormals
- )
+ bool canFitIn16BitBuffer,
+ out bool calculateNormals)
{
Profiler.BeginSample("CalculateVertexParams");
@@ -154,7 +170,7 @@ out m_BoneIndexMap
// on performance. Therefore we stick to Unity's layout (which
// combines pos+normal+tangent in one stream) for smaller meshes.
// See: https://github.com/atteneder/glTFast/issues/197
- forceUnityVertexLayout |= dracoMesh->numVertices <= ushort.MaxValue;
+ forceUnityVertexLayout |= canFitIn16BitBuffer;
foreach (var attributeMap in m_Attributes)
{
@@ -231,6 +247,11 @@ public JobHandle DecodeVertexData(
decodeVerticesJobHandle.Complete();
}
#endif
+
+ var indicesOffset = m_IndicesIntervals[m_SubMeshIndex];
+ var indicesLength = m_IndicesIntervals[m_SubMeshIndex + 1] - indicesOffset;
+ var vertOffset = m_VertexIntervals[m_SubMeshIndex];
+ var vertLength = m_VertexIntervals[m_SubMeshIndex + 1] - vertOffset;
JobHandle indicesJob;
var dracoMeshJobCount = m_Attributes.Count;
@@ -239,7 +260,9 @@ public JobHandle DecodeVertexData(
{
indicesJob = new GeneratePointCloudIndicesJob
{
- mesh = m_Mesh
+ mesh = m_Mesh,
+ indicesOffset = indicesOffset,
+ indicesLength = indicesLength
}.Schedule();
}
else
@@ -250,7 +273,9 @@ public JobHandle DecodeVertexData(
dracoTempResources = m_DracoTempResources,
flip = (m_DecodeSettings & DecodeSettings.ConvertSpace) != 0,
dataType = m_Mesh.indexFormat == IndexFormat.UInt16 ? DataType.UInt16 : DataType.UInt32,
- mesh = m_Mesh
+ mesh = m_Mesh,
+ indicesOffset = indicesOffset,
+ indicesLength = indicesLength
}.Schedule(decodeVerticesJobHandle);
dracoMeshJobCount++;
}
@@ -281,7 +306,8 @@ public JobHandle DecodeVertexData(
// weights were removed from attributes before
if (map.attribute == VertexAttribute.BlendIndices) continue; // Blend
- var calculateBound = map.attribute == VertexAttribute.Position;
+
+ var calculateBound = map.attribute == VertexAttribute.Position && !m_Bounds.HasValue;
if (calculateBound)
{
Assert.IsFalse(m_PositionMinMax.IsCreated, "Multiple position attributes are not supported");
@@ -305,6 +331,8 @@ public JobHandle DecodeVertexData(
streamIndex = map.stream,
offset = map.offset,
bounds = m_PositionMinMax,
+ vertOffset = vertOffset,
+ vertLength = vertLength
};
jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle);
}
@@ -321,6 +349,8 @@ public JobHandle DecodeVertexData(
mesh = m_Mesh,
streamIndex = map.stream,
offset = map.offset,
+ vertOffset = vertOffset,
+ vertLength = vertLength
};
jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle);
}
@@ -339,6 +369,8 @@ public JobHandle DecodeVertexData(
mesh = m_Mesh,
streamIndex = map.stream,
bounds = m_PositionMinMax,
+ vertOffset = vertOffset,
+ vertLength = vertLength,
};
jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle);
}
@@ -353,6 +385,8 @@ public JobHandle DecodeVertexData(
componentStride = map.numComponents,
mesh = m_Mesh,
streamIndex = map.stream,
+ vertOffset = vertOffset,
+ vertLength = vertLength
};
jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle);
}
@@ -374,10 +408,12 @@ public JobHandle DecodeVertexData(
dracoTempResources = m_DracoTempResources,
indicesAttribute = m_BoneIndexMap.dracoAttribute,
weightsAttribute = m_BoneWeightMap.dracoAttribute,
- bonesPerVertex = bonesPerVertex,
- boneWeights = boneWeights,
+ boneOffset = vertOffset,
indexValueConverter = GetIndexValueConverter(m_BoneIndexMap.format)
};
+
+ boneWeightData.AssignToJob(ref job);
+
jobHandles[jobIndex] = job.Schedule(decodeVerticesJobHandle);
}
@@ -418,37 +454,52 @@ Dictionary attributeIdMap
var dracoMesh = (DracoMesh*)m_DracoTempResources[k_MeshPtrIndex];
m_Allocator = dracoMesh->numVertices > k_PersistentDataThreshold ? Allocator.Persistent : Allocator.TempJob;
+ m_IsPointCloud = dracoMesh->isPointCloud;
+ m_IndicesCount = m_IsPointCloud ? dracoMesh->numVertices : dracoMesh->numFaces * 3;
+
+ m_VertexIntervals ??= new[] { 0, dracoMesh->numVertices };
+ m_IndicesIntervals ??= new[] { 0, m_IndicesCount };
+
+ var totalVertCount = m_VertexIntervals[m_VertexIntervals.Length - 1];
+ var canFitIn16BitBuffer = totalVertCount < ushort.MaxValue; // Max value is excluded because it is reserved in some Graphics APIs for triggering primitive restart (https://github.com/KhronosGroup/glTF/issues/1142#issuecomment-433717774)
+
CalculateVertexParams(
dracoMesh,
attributeIdMap,
+ canFitIn16BitBuffer,
out calculateNormals
);
Profiler.BeginSample("SetParameters");
- m_IsPointCloud = dracoMesh->isPointCloud;
- if (m_IsPointCloud)
- {
- m_IndicesCount = dracoMesh->numVertices;
- m_Mesh.SetIndexBufferParams(dracoMesh->numVertices, dracoMesh->indexFormat);
- }
- else
- {
- m_IndicesCount = dracoMesh->numFaces * 3;
- m_Mesh.SetIndexBufferParams(dracoMesh->numFaces * 3, dracoMesh->indexFormat);
- }
- var vertexParams = new List(m_Attributes.Count);
- foreach (var map in m_Attributes)
+ // The first submesh will setup the entire mesh buffer.
+ if (m_SetupBuffers)
{
- vertexParams.Add(map.GetVertexAttributeDescriptor());
- }
- m_Mesh.SetVertexBufferParams(dracoMesh->numVertices, vertexParams.ToArray());
- if (hasBoneWeightData)
- {
- var boneCount = m_BoneIndexMap.numComponents;
- bonesPerVertex = new NativeArray(dracoMesh->numVertices, m_Allocator);
- boneWeights = new NativeArray(dracoMesh->numVertices * boneCount, m_Allocator);
+ var totalIndicesCount = m_IsPointCloud ? totalVertCount : m_IndicesIntervals[m_IndicesIntervals.Length - 1];
+ var indexFormat = canFitIn16BitBuffer ? IndexFormat.UInt16 : IndexFormat.UInt32;
+
+ m_Mesh.SetIndexBufferParams(totalIndicesCount, indexFormat);
+
+ var vertexParams = new List(m_Attributes.Count);
+ foreach (var map in m_Attributes)
+ {
+ vertexParams.Add(map.GetVertexAttributeDescriptor());
+ }
+
+ m_Mesh.SetVertexBufferParams(totalVertCount, vertexParams.ToArray());
+
+ m_Mesh.subMeshCount = m_VertexIntervals.Length - 1;
+
+ if (hasBoneWeightData)
+ {
+ var boneCount = m_BoneIndexMap.numComponents;
+ var boneAllocator = totalVertCount > k_PersistentDataThreshold ? Allocator.Persistent : Allocator.TempJob;
+ var bonesPerVertex = new NativeArray(totalVertCount, boneAllocator);
+ var boneWeights = new NativeArray(totalVertCount * boneCount, boneAllocator);
+ boneWeightData = new BoneWeightData(bonesPerVertex, boneWeights);
+ }
}
+
Profiler.EndSample(); // SetParameters
Profiler.EndSample(); // CreateMesh
}
@@ -471,10 +522,8 @@ public Bounds CreateBounds()
return bounds;
}
- public bool
- PopulateMeshData(Bounds bounds)
+ public bool PopulateMeshData(out Bounds bounds)
{
-
Profiler.BeginSample("PopulateMeshData");
foreach (var map in m_Attributes)
@@ -485,19 +534,21 @@ public bool
Profiler.BeginSample("MeshAssign");
+ bounds = m_Bounds ?? CreateBounds();
const MeshUpdateFlags flags = DracoDecoder.defaultMeshUpdateFlags;
-
- m_Mesh.subMeshCount = 1;
var subMeshDescriptor = new SubMeshDescriptor(
- 0,
+ m_IndicesIntervals[m_SubMeshIndex],
m_IndicesCount,
m_IsPointCloud ? MeshTopology.Points : MeshTopology.Triangles
)
{
- vertexCount = m_Mesh.vertexCount,
+ baseVertex = m_VertexIntervals[m_SubMeshIndex],
+ vertexCount = m_VertexIntervals[m_SubMeshIndex + 1] - m_VertexIntervals[m_SubMeshIndex],
+ firstVertex = m_VertexIntervals[m_SubMeshIndex],
bounds = bounds
};
- m_Mesh.SetSubMesh(0, subMeshDescriptor, flags);
+ m_Mesh.SetSubMesh(m_SubMeshIndex, subMeshDescriptor, flags);
+
Profiler.EndSample(); // CreateUnityMesh.CreateMesh
Profiler.EndSample();
@@ -571,7 +622,7 @@ struct DracoData
}
[StructLayout(LayoutKind.Sequential)]
- struct DracoAttribute
+ internal struct DracoAttribute
{
// ReSharper disable MemberCanBePrivate.Local
public int attributeType;
@@ -589,8 +640,6 @@ struct DracoMesh
// ReSharper disable once MemberCanBePrivate.Local
public int numAttributes;
public bool isPointCloud;
-
- public IndexFormat indexFormat => numVertices >= ushort.MaxValue ? IndexFormat.UInt32 : IndexFormat.UInt16;
}
///
@@ -1042,7 +1091,6 @@ public void Execute()
[BurstCompile]
struct DecodeVerticesJob : IJob
{
-
public NativeArray result;
public NativeArray dracoTempResources;
@@ -1064,7 +1112,6 @@ public void Execute()
[BurstCompile]
struct GetDracoIndicesJob : IJob
{
-
[ReadOnly]
public NativeArray result;
[ReadOnly]
@@ -1073,6 +1120,10 @@ struct GetDracoIndicesJob : IJob
public bool flip;
[ReadOnly]
public DataType dataType;
+ [ReadOnly]
+ public int indicesOffset;
+ [ReadOnly]
+ public int indicesLength;
public Mesh.MeshData mesh;
public void Execute()
@@ -1084,28 +1135,24 @@ public void Execute()
var dracoMesh = (DracoMesh*)dracoTempResources[k_MeshPtrIndex];
Assert.IsFalse(dracoMesh->isPointCloud);
void* indicesPtr;
- int indicesLength;
switch (dataType)
{
case DataType.UInt16:
{
- var indices = mesh.GetIndexData();
- indicesPtr = indices.GetUnsafePtr();
- indicesLength = indices.Length;
+ indicesPtr = (ushort*)mesh.GetIndexData().GetUnsafePtr() + indicesOffset;
break;
}
case DataType.UInt32:
{
- var indices = mesh.GetIndexData();
- indicesPtr = indices.GetUnsafePtr();
- indicesLength = indices.Length;
+ indicesPtr = (uint*)mesh.GetIndexData().GetUnsafePtr() + indicesOffset;
break;
}
default:
result[0] = -1;
return;
}
+
GetMeshIndices(dracoMesh, dataType, indicesPtr, indicesLength, flip);
}
}
@@ -1114,6 +1161,11 @@ public void Execute()
struct GeneratePointCloudIndicesJob : IJob
{
public Mesh.MeshData mesh;
+
+ [ReadOnly]
+ public int indicesOffset;
+ [ReadOnly]
+ public int indicesLength;
public void Execute()
{
@@ -1122,18 +1174,18 @@ public void Execute()
case IndexFormat.UInt16:
{
var indices = mesh.GetIndexData();
- for (var i = 0; i < indices.Length; i++)
+ for (var i = 0; i < indicesLength; i++)
{
- indices[i] = (ushort)i;
+ indices[i + indicesOffset] = (ushort)i;
}
break;
}
case IndexFormat.UInt32:
{
var indices = mesh.GetIndexData();
- for (var i = 0; i < indices.Length; i++)
+ for (var i = 0; i < indicesLength; i++)
{
- indices[i] = (uint)i;
+ indices[i + indicesOffset] = (uint)i;
}
break;
}
@@ -1163,6 +1215,11 @@ struct GetDracoDataJob : IJob
public Mesh.MeshData mesh;
[ReadOnly]
public int streamIndex;
+
+ [ReadOnly]
+ public int vertOffset;
+ [ReadOnly]
+ public int vertLength;
public void Execute()
{
@@ -1175,8 +1232,8 @@ public void Execute()
GetAttributeData(dracoMesh, attribute, &data, flip, componentStride);
var elementSize = DataTypeSize((DataType)data->dataType) * componentStride;
var dst = mesh.GetVertexData(streamIndex);
- var dstPtr = dst.GetUnsafePtr();
- UnsafeUtility.MemCpy(dstPtr, (void*)data->data, elementSize * dracoMesh->numVertices);
+ var dstPtr = (byte*)dst.GetUnsafePtr() + vertOffset * elementSize;
+ UnsafeUtility.MemCpy(dstPtr, (void*)data->data, elementSize * vertLength);
ReleaseDracoData(&data);
}
}
@@ -1206,6 +1263,11 @@ struct GetDracoDataBoundsJob : IJob
public NativeArray bounds;
+ [ReadOnly]
+ public int vertOffset;
+ [ReadOnly]
+ public int vertLength;
+
public void Execute()
{
if (result[0] < 0)
@@ -1217,8 +1279,8 @@ public void Execute()
GetAttributeData(dracoMesh, attribute, &data, flip, componentStride);
var elementSize = DataTypeSize((DataType)data->dataType) * componentStride;
var dst = mesh.GetVertexData(streamIndex);
- var dstPtr = dst.GetUnsafePtr();
- for (var v = 0; v < dracoMesh->numVertices; v++)
+ var dstPtr = (byte*)dst.GetUnsafePtr() + vertOffset * elementSize;
+ for (var v = 0; v < vertLength; v++)
{
var value = *(float3*)((byte*)data->data + elementSize * v);
bounds[0] = math.min(bounds[0], value);
@@ -1258,6 +1320,11 @@ struct GetDracoDataInterleavedJob : IJob
[ReadOnly]
public int offset;
+
+ [ReadOnly]
+ public int vertOffset;
+ [ReadOnly]
+ public int vertLength;
public void Execute()
{
@@ -1270,8 +1337,8 @@ public void Execute()
GetAttributeData(dracoMesh, attribute, &data, flip, componentStride);
var elementSize = DataTypeSize((DataType)data->dataType) * componentStride;
var dst = mesh.GetVertexData(streamIndex);
- var dstPtr = ((byte*)dst.GetUnsafePtr()) + offset;
- for (var v = 0; v < dracoMesh->numVertices; v++)
+ var dstPtr = ((byte*)dst.GetUnsafePtr()) + offset + vertOffset * stride;
+ for (var v = 0; v < vertLength; v++)
{
UnsafeUtility.MemCpy(dstPtr + (stride * v), ((byte*)data->data) + (elementSize * v), elementSize);
}
@@ -1311,6 +1378,11 @@ struct GetDracoDataInterleavedBoundsJob : IJob
public int offset;
public NativeArray bounds;
+
+ [ReadOnly]
+ public int vertOffset;
+ [ReadOnly]
+ public int vertLength;
public void Execute()
{
@@ -1323,8 +1395,8 @@ public void Execute()
GetAttributeData(dracoMesh, attribute, &data, flip, componentStride);
var elementSize = DataTypeSize((DataType)data->dataType) * componentStride;
var dst = mesh.GetVertexData(streamIndex);
- var dstPtr = ((byte*)dst.GetUnsafePtr()) + offset;
- for (var v = 0; v < dracoMesh->numVertices; v++)
+ var dstPtr = ((byte*)dst.GetUnsafePtr()) + offset + vertOffset * stride;
+ for (var v = 0; v < vertLength; v++)
{
var value = *(float3*)((byte*)data->data + elementSize * v);
bounds[0] = math.min(bounds[0], value);
@@ -1336,7 +1408,7 @@ public void Execute()
}
[BurstCompile]
- struct GetDracoBonesJob : IJob
+ internal struct GetDracoBonesJob : IJob
{
public delegate int GetIndexValueDelegate(IntPtr baseAddress, int index);
@@ -1355,6 +1427,9 @@ struct GetDracoBonesJob : IJob
[ReadOnly]
[NativeDisableUnsafePtrRestriction]
public DracoAttribute* weightsAttribute;
+
+ [ReadOnly]
+ public int boneOffset;
[WriteOnly]
public NativeArray bonesPerVertex;
@@ -1380,12 +1455,12 @@ public void Execute()
for (var v = 0; v < dracoMesh->numVertices; v++)
{
- bonesPerVertex[v] = (byte)indicesAttribute->numComponents;
+ bonesPerVertex[v + boneOffset] = (byte)indicesAttribute->numComponents;
var indicesPtr = (IntPtr)(((byte*)indicesData->data) + (indexSize * v));
var weightsPtr = (float*)(((byte*)weightsData->data) + (weightSize * v));
for (var b = 0; b < indicesAttribute->numComponents; b++)
{
- boneWeights[v * indicesAttribute->numComponents + b] = new BoneWeight1
+ boneWeights[(v + boneOffset) * indicesAttribute->numComponents + b] = new BoneWeight1
{
boneIndex = indexValueConverter.Invoke(indicesPtr, b),
weight = *(weightsPtr + b)