public unsafe JobHandle?ScheduleMorphTargetJobs( IGltfBuffers buffers, int positionAccessorIndex, int normalAccessorIndex, int tangentAccessorIndex, ICodeLogger logger ) { Profiler.BeginSample("ScheduleMorphTargetJobs"); buffers.GetAccessor(positionAccessorIndex, out var posAcc, out var posData, out var posByteStride); positions = new Vector3[posAcc.count]; positionsHandle = GCHandle.Alloc(positions, GCHandleType.Pinned); var jobCount = 1; if (posAcc.isSparse && posAcc.bufferView >= 0) { jobCount++; } Accessor nrmAcc = null; void * nrmInput = null; int nrmInputByteStride = 0; if (normalAccessorIndex >= 0) { normals = new Vector3[posAcc.count]; normalsHandle = GCHandle.Alloc(normals, GCHandleType.Pinned); buffers.GetAccessor(normalAccessorIndex, out nrmAcc, out nrmInput, out nrmInputByteStride); if (nrmAcc.isSparse && nrmAcc.bufferView >= 0) { jobCount += 2; } else { jobCount++; } } Accessor tanAcc = null; void * tanInput = null; int tanInputByteStride = 0; if (tangentAccessorIndex >= 0) { tangents = new Vector3[posAcc.count]; tangentsHandle = GCHandle.Alloc(tangents, GCHandleType.Pinned); buffers.GetAccessor(normalAccessorIndex, out tanAcc, out tanInput, out tanInputByteStride); if (tanAcc.isSparse && tanAcc.bufferView >= 0) { jobCount += 2; } else { jobCount++; } } NativeArray <JobHandle> handles = new NativeArray <JobHandle>(jobCount, VertexBufferConfigBase.defaultAllocator); var handleIndex = 0; fixed(void *dest = &(positions[0])) { JobHandle?h = null; if (posData != null) { #if DEBUG if (posAcc.normalized) { Debug.LogError("Normalized Positions will likely produce incorrect results. Please report this error at https://github.com/atteneder/glTFast/issues/new?assignees=&labels=bug&template=bug_report.md&title=Normalized%20Positions"); } #endif h = VertexBufferConfigBase.GetVector3sJob( posData, posAcc.count, posAcc.componentType, posByteStride, (float3 *)dest, 12, posAcc.normalized, false // positional data never needs to be normalized ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (posAcc.isSparse) { buffers.GetAccessorSparseIndices(posAcc.sparse.indices, out var posIndexData); buffers.GetAccessorSparseValues(posAcc.sparse.values, out var posValueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( posIndexData, posValueData, posAcc.sparse.count, posAcc.sparse.indices.componentType, posAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, posAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } if (nrmAcc != null) { fixed(void *dest = &(normals[0])) { JobHandle?h = null; if (nrmAcc.bufferView >= 0) { h = VertexBufferConfigBase.GetVector3sJob( nrmInput, nrmAcc.count, nrmAcc.componentType, nrmInputByteStride, (float3 *)dest, 12, nrmAcc.normalized, false // morph target normals are deltas -> don't normalize ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (nrmAcc.isSparse) { buffers.GetAccessorSparseIndices(nrmAcc.sparse.indices, out var indexData); buffers.GetAccessorSparseValues(nrmAcc.sparse.values, out var valueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( indexData, valueData, nrmAcc.sparse.count, nrmAcc.sparse.indices.componentType, nrmAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, nrmAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } } if (tanAcc != null) { fixed(void *dest = &(tangents[0])) { JobHandle?h = null; if (tanAcc.bufferView >= 0) { h = VertexBufferConfigBase.GetVector3sJob( tanInput, tanAcc.count, tanAcc.componentType, tanInputByteStride, (float3 *)dest, 12, tanAcc.normalized, false // morph target tangents are deltas -> don't normalize ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (tanAcc.isSparse) { buffers.GetAccessorSparseIndices(tanAcc.sparse.indices, out var indexData); buffers.GetAccessorSparseValues(tanAcc.sparse.values, out var valueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( indexData, valueData, tanAcc.sparse.count, tanAcc.sparse.indices.componentType, tanAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, tanAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } } var handle = (jobCount > 1) ? JobHandle.CombineDependencies(handles) : handles[0]; handles.Dispose(); Profiler.EndSample(); return(handle); }
public override unsafe JobHandle?ScheduleVertexJobs( IGltfBuffers buffers, int positionAccessorIndex, int normalAccessorIndex, int tangentAccessorIndex, int[] uvAccessorIndices, int colorAccessorIndex, int weightsAccessorIndex, int jointsAccessorIndex ) { buffers.GetAccessor(positionAccessorIndex, out var posAcc, out var posData, out var posByteStride); Profiler.BeginSample("ScheduleVertexJobs"); Profiler.BeginSample("AllocateNativeArray"); vData = new NativeArray <VType>(posAcc.count, defaultAllocator); var vDataPtr = (byte *)vData.GetUnsafeReadOnlyPtr(); Profiler.EndSample(); bounds = posAcc.TryGetBounds(); int jobCount = 1; int outputByteStride = 12; // sizeof Vector3 if (posAcc.isSparse && posAcc.bufferView >= 0) { jobCount++; } if (normalAccessorIndex >= 0) { jobCount++; hasNormals = true; } hasNormals |= calculateNormals; if (hasNormals) { outputByteStride += 12; } if (tangentAccessorIndex >= 0) { jobCount++; hasTangents = true; } hasTangents |= calculateTangents; if (hasTangents) { outputByteStride += 16; } if (uvAccessorIndices != null && uvAccessorIndices.Length > 0) { // More than two UV sets are not supported yet Assert.IsTrue(uvAccessorIndices.Length < 3); jobCount += uvAccessorIndices.Length; switch (uvAccessorIndices.Length) { case 1: texCoords = new VertexBufferTexCoords <VTexCoord1>(logger); break; default: texCoords = new VertexBufferTexCoords <VTexCoord2>(logger); break; } } hasColors = colorAccessorIndex >= 0; if (hasColors) { jobCount++; colors = new VertexBufferColors(); } hasBones = weightsAccessorIndex >= 0 && jointsAccessorIndex >= 0; if (hasBones) { jobCount++; bones = new VertexBufferBones(logger); } NativeArray <JobHandle> handles = new NativeArray <JobHandle>(jobCount, defaultAllocator); int handleIndex = 0; { JobHandle?h = null; if (posAcc.bufferView >= 0) { h = GetVector3sJob( posData, posAcc.count, posAcc.componentType, posByteStride, (float3 *)vDataPtr, outputByteStride, posAcc.normalized, false // positional data never needs to be normalized ); } if (posAcc.isSparse) { buffers.GetAccessorSparseIndices(posAcc.sparse.indices, out var posIndexData); buffers.GetAccessorSparseValues(posAcc.sparse.values, out var posValueData); var sparseJobHandle = GetVector3sSparseJob( posIndexData, posValueData, posAcc.sparse.count, posAcc.sparse.indices.componentType, posAcc.componentType, (float3 *)vDataPtr, outputByteStride, dependsOn: ref h, posAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (normalAccessorIndex >= 0) { buffers.GetAccessor(normalAccessorIndex, out var nrmAcc, out var input, out var inputByteStride); if (nrmAcc.isSparse) { logger.Error(LogCode.SparseAccessor, "normals"); } var h = GetVector3sJob( input, nrmAcc.count, nrmAcc.componentType, inputByteStride, (float3 *)(vDataPtr + 12), outputByteStride, nrmAcc.normalized, true // normals need to be unit length ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (tangentAccessorIndex >= 0) { buffers.GetAccessor(tangentAccessorIndex, out var tanAcc, out var input, out var inputByteStride); if (tanAcc.isSparse) { logger.Error(LogCode.SparseAccessor, "tangents"); } var h = GetTangentsJob( input, tanAcc.count, tanAcc.componentType, inputByteStride, (float4 *)(vDataPtr + 24), outputByteStride, tanAcc.normalized ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (texCoords != null) { texCoords.ScheduleVertexUVJobs( buffers, uvAccessorIndices, posAcc.count, new NativeSlice <JobHandle>( handles, handleIndex, uvAccessorIndices.Length ) ); handleIndex += uvAccessorIndices.Length; } if (hasColors) { colors.ScheduleVertexColorJob( buffers, colorAccessorIndex, new NativeSlice <JobHandle>( handles, handleIndex, 1 ) ); handleIndex++; } if (hasBones) { var h = bones.ScheduleVertexBonesJob( buffers, weightsAccessorIndex, jointsAccessorIndex ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } var handle = (jobCount > 1) ? JobHandle.CombineDependencies(handles) : handles[0]; handles.Dispose(); Profiler.EndSample(); return(handle); }