/// <summary> /// インデックスバッファを更新する /// MEMO: 出力に対するushortを考慮することをやめればかなりシンプルに書ける /// </summary> private static void UpdateIndices(MeshGroup meshGroup, int vertexCount, int indexCount, Mesh resultMesh) { Profiler.BeginSample("MeshImporterDivided.UpdateIndices"); JobHandle jobHandle = default; var disposables = new List <IDisposable>(); // // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_accessor_componenttype // if (vertexCount < ushort.MaxValue) { // vertex buffer への index が ushort に収まる var indices = new NativeArray <ushort>(indexCount, Allocator.TempJob); disposables.Add(indices); var indexOffset = 0; var vertexOffset = 0; foreach (var mesh in meshGroup.Meshes) { switch (mesh.IndexBuffer.ComponentType) { case AccessorValueType.BYTE: case AccessorValueType.UNSIGNED_BYTE: case AccessorValueType.FLOAT: throw new NotImplementedException($"{mesh.IndexBuffer.ComponentType}"); case AccessorValueType.SHORT: case AccessorValueType.UNSIGNED_SHORT: { // unsigned short -> unsigned short var source = mesh.IndexBuffer.Bytes.Reinterpret <ushort>(1); jobHandle = new CopyIndicesJobs.Ushort2Ushort( (ushort)vertexOffset, new NativeSlice <ushort>(source), new NativeSlice <ushort>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } case AccessorValueType.UNSIGNED_INT: { // unsigned int -> unsigned short var source = mesh.IndexBuffer.Bytes.Reinterpret <uint>(1); jobHandle = new CopyIndicesJobs.Uint2Ushort( (ushort)vertexOffset, source, new NativeSlice <ushort>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } default: throw new ArgumentException($"unknown index buffer type: {mesh.IndexBuffer.ComponentType}"); } vertexOffset += mesh.VertexBuffer.Count; indexOffset += mesh.IndexBuffer.Count; } jobHandle.Complete(); resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt16); resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); } else { // vertex buffer への index が ushort を超える var indices = new NativeArray <uint>(indexCount, Allocator.TempJob); disposables.Add(indices); var indexOffset = 0; var vertexOffset = 0; foreach (var mesh in meshGroup.Meshes) { switch (mesh.IndexBuffer.ComponentType) { case AccessorValueType.BYTE: case AccessorValueType.UNSIGNED_BYTE: case AccessorValueType.FLOAT: throw new NotImplementedException($"{mesh.IndexBuffer.ComponentType}"); case AccessorValueType.SHORT: case AccessorValueType.UNSIGNED_SHORT: { // unsigned short -> unsigned int var source = mesh.IndexBuffer.Bytes.Reinterpret <ushort>(1); jobHandle = new CopyIndicesJobs.Ushort2Uint( (uint)vertexOffset, source, new NativeSlice <uint>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } case AccessorValueType.UNSIGNED_INT: { // unsigned int -> unsigned int var source = mesh.IndexBuffer.Bytes.Reinterpret <uint>(1); jobHandle = new CopyIndicesJobs.UInt2UInt( (uint)vertexOffset, source, new NativeSlice <uint>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } default: throw new ArgumentException($"unknown index buffer type: {mesh.IndexBuffer.ComponentType}"); } vertexOffset += mesh.VertexBuffer.Count; indexOffset += mesh.IndexBuffer.Count; } jobHandle.Complete(); resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); } foreach (var disposable in disposables) { disposable.Dispose(); } Profiler.EndSample(); }
/// <summary> /// インデックスバッファを更新する /// MEMO: 出力に対するushortを考慮することをやめればかなりシンプルに書ける /// </summary> private static void UpdateIndices(MeshGroup meshGroup, int vertexCount, int indexCount, Mesh resultMesh) { Profiler.BeginSample("MeshImporterDivided.UpdateIndices"); JobHandle jobHandle = default; var disposables = new List <IDisposable>(); // 出力をushortにするべきかどうかを判別 if (vertexCount < ushort.MaxValue) { var indices = new NativeArray <ushort>(indexCount, Allocator.TempJob); disposables.Add(indices); var indexOffset = 0; var vertexOffset = 0; foreach (var mesh in meshGroup.Meshes) { switch (mesh.IndexBuffer.ComponentType) { case AccessorValueType.SHORT: { // unsigned short -> unsigned short var source = mesh.IndexBuffer.AsNativeArray <ushort>(Allocator.TempJob); disposables.Add(source); jobHandle = new CopyIndicesJobs.Ushort2Ushort( (ushort)vertexOffset, new NativeSlice <ushort>(source), new NativeSlice <ushort>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } case AccessorValueType.UNSIGNED_INT: { // unsigned int -> unsigned short var source = mesh.IndexBuffer.AsNativeArray <uint>(Allocator.TempJob); disposables.Add(source); jobHandle = new CopyIndicesJobs.Uint2Ushort( (ushort)vertexOffset, source, new NativeSlice <ushort>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } default: throw new ArgumentOutOfRangeException(); } vertexOffset += mesh.VertexBuffer.Count; indexOffset += mesh.IndexBuffer.Count; } jobHandle.Complete(); resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt16); resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); } else { var indices = new NativeArray <uint>(indexCount, Allocator.TempJob); disposables.Add(indices); var indexOffset = 0; var vertexOffset = 0; foreach (var mesh in meshGroup.Meshes) { switch (mesh.IndexBuffer.ComponentType) { case AccessorValueType.SHORT: { // unsigned short -> unsigned int var source = mesh.IndexBuffer.AsNativeArray <ushort>(Allocator.TempJob); disposables.Add(source); jobHandle = new CopyIndicesJobs.Ushort2Uint( (uint)vertexOffset, source, new NativeSlice <uint>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } case AccessorValueType.UNSIGNED_INT: { // unsigned int -> unsigned int var source = mesh.IndexBuffer.AsNativeArray <uint>(Allocator.TempJob); disposables.Add(source); jobHandle = new CopyIndicesJobs.UInt2UInt( (uint)vertexOffset, source, new NativeSlice <uint>(indices, indexOffset, mesh.IndexBuffer.Count)) .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); break; } default: throw new ArgumentOutOfRangeException(); } vertexOffset += mesh.VertexBuffer.Count; indexOffset += mesh.IndexBuffer.Count; } jobHandle.Complete(); resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); } foreach (var disposable in disposables) { disposable.Dispose(); } Profiler.EndSample(); }