private glTFLoader.Schema.Image GetImageFromFileText(string fileName) { byte[] imageBytes = GetImageBytesFromFile(fileName); var textureBuffer = new glTFLoader.Schema.Buffer() { Uri = Constants.TextBufferHeader + Convert.ToBase64String(imageBytes), ByteLength = imageBytes.Length, }; int textureBufferIdx = dummy.Buffers.AddAndReturnIndex(textureBuffer); var textureBufferView = new glTFLoader.Schema.BufferView() { Buffer = textureBufferIdx, ByteOffset = 0, ByteLength = textureBuffer.ByteLength, }; int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView); return(new glTFLoader.Schema.Image() { BufferView = textureBufferViewIdx, MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png, }); }
private int CreateBufferView(string name, out Schema.BufferView bufferView) { bufferView = CreateInstance <Schema.BufferView>(); bufferView.Name = name; var bufferViewIndex = bufferViews.Count(); bufferViews.Add(bufferView); return(bufferViewIndex); }
private void InitBufferViews() { _indicesBv = new gltf.BufferView(); _indicesBv.Buffer = 0; _indicesBv.Target = gltf.BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER; _bufferViews.Add(_indicesBv); _coordinatesBv = new gltf.BufferView(); _coordinatesBv.Buffer = 0; _coordinatesBv.Target = gltf.BufferView.TargetEnum.ARRAY_BUFFER; _coordinatesBv.ByteStride = 12; // todo: what is this number? _bufferViews.Add(_coordinatesBv); }
private void InitBufferViews() { _indicesBv = new gltf.BufferView(); _indicesBv.Buffer = 0; _indicesBv.Target = gltf.BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER; _bufferViews.Add(_indicesBv); _coordinatesBv = new gltf.BufferView(); _coordinatesBv.Buffer = 0; _coordinatesBv.Target = gltf.BufferView.TargetEnum.ARRAY_BUFFER; _coordinatesBv.ByteStride = 12; // distance in bytes from one element to the next. Thanks to @tmarti _bufferViews.Add(_coordinatesBv); }
private void WriteBufferView(Schema.BufferView bufferView, BinaryData binaryData, Action <int> writeData) { binaryData.Writer.Align(4); int byteOffset = (int)binaryData.Writer.BaseStream.Position; writeData(byteOffset); int byteLength = (int)binaryData.Writer.BaseStream.Position - byteOffset; bufferView.Buffer = binaryDataToBufferIndex[binaryData]; bufferView.ByteOffset = byteOffset; bufferView.ByteLength = byteLength; }
public Image[] LoadImages() { if (gltf.Images == null) { return new Image[] {} } ; List <Image> textures = new List <Image> (); foreach (GL.Image img in gltf.Images) { Image vkimg = null; string imgName = img.Name; if (img.BufferView != null) //load image from gltf buffer view { GL.BufferView bv = gltf.BufferViews[(int)img.BufferView]; EnsureBufferIsLoaded(bv.Buffer); vkimg = Image.Load(dev, transferQ, cmdPool, bufferHandles[bv.Buffer].AddrOfPinnedObject() + bv.ByteOffset, (ulong)bv.ByteLength); } else if (img.Uri.StartsWith("data:", StringComparison.Ordinal)) //load base64 encoded image { Debug.WriteLine("loading embedded image {0} : {1}", img.Name, img.MimeType); vkimg = Image.Load(dev, transferQ, cmdPool, glTFLoader.loadDataUri(img)); } else { Debug.WriteLine("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri); //load image from file path in uri vkimg = Image.Load(dev, transferQ, cmdPool, Path.Combine(baseDirectory, img.Uri)); imgName += ";" + img.Uri; } vkimg.CreateView(); vkimg.CreateSampler(); vkimg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; vkimg.SetName(imgName); vkimg.Descriptor.imageView.SetDebugMarkerName(dev, "imgView " + imgName); vkimg.Descriptor.sampler.SetDebugMarkerName(dev, "sampler " + imgName); textures.Add(vkimg); } return(textures.ToArray()); }
private glTFLoader.Schema.Image GetImageFromFileBinary(string fileName) { byte[] imageBytes = GetImageBytesFromFile(fileName); int imageBytesOffset = (int)binaryBuffer.Count; binaryBuffer.AddRange(imageBytes); var textureBufferView = new glTFLoader.Schema.BufferView() { Buffer = 0, ByteOffset = imageBytesOffset, ByteLength = imageBytes.Length, }; int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView); return(new glTFLoader.Schema.Image() { BufferView = textureBufferViewIdx, MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png, }); }
///// <summary> ///// build texture array ///// </summary> ///// <returns>The images.</returns> ///// <param name="textureSize">Uniformized Texture size for all images</param> public void BuildTexArray (ref Image texArray, uint firstImg = 0) { int texDim = (int)texArray.CreateInfo.extent.width; PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer); transferQ.EndSubmitAndWait (cmd, true); VkImageBlit imageBlit = new VkImageBlit { srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0), dstOffsets_1 = new VkOffset3D (texDim, texDim, 1) }; for (int l = 0; l < gltf.Images.Length; l++) { GL.Image img = gltf.Images[l]; Image vkimg = null; if (img.BufferView != null) {//load image from gltf buffer view GL.BufferView bv = gltf.BufferViews[(int)img.BufferView]; ensureBufferIsLoaded (bv.Buffer); vkimg = Image.Load (dev, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset), (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc); } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType); vkimg = Image.Load (dev, glTFLoader.loadDataUri (img), VkImageUsageFlags.TransferSrc); } else { Debug.WriteLine ("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);//load image from file path in uri vkimg = Image.Load (dev, Path.Combine (baseDirectory, img.Uri), VkImageUsageFlags.TransferSrc); } imageBlit.srcOffsets_1 = new VkOffset3D ((int)vkimg.CreateInfo.extent.width, (int)vkimg.CreateInfo.extent.height, 1); imageBlit.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0, (uint)l + firstImg); cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); vkimg.SetLayout (cmd, VkImageAspectFlags.Color, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer); Vk.vkCmdBlitImage (cmd.Handle, vkimg.Handle, VkImageLayout.TransferSrcOptimal, texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear); transferQ.EndSubmitAndWait (cmd, true); vkimg.Dispose (); } cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); uint imgCount = (uint)gltf.Images.Length; VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, firstImg, imgCount); for (int i = 1; i < texArray.CreateInfo.mipLevels; i++) { imageBlit = new VkImageBlit { srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i - 1, firstImg), srcOffsets_1 = new VkOffset3D ((int)texDim >> (i - 1), (int)texDim >> (i - 1), 1), dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i, firstImg), dstOffsets_1 = new VkOffset3D ((int)texDim >> i, (int)texDim >> i, 1) }; texArray.SetLayout (cmd, VkAccessFlags.TransferWrite, VkAccessFlags.TransferRead, VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer); Vk.vkCmdBlitImage (cmd.Handle, texArray.Handle, VkImageLayout.TransferSrcOptimal, texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear); texArray.SetLayout (cmd, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader); mipSubRange.baseMipLevel = (uint)i; } mipSubRange.baseMipLevel = texArray.CreateInfo.mipLevels - 1; texArray.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader); cmd.End (); transferQ.Submit (cmd); transferQ.WaitIdle (); cmd.Free (); }
//TODO: some buffer data are reused between primitives, and I duplicate the datas //buffers must be constructed without duplications public Mesh[] LoadMeshes<TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset) { ulong vCount, iCount; VkIndexType idxType; GetVertexCount (out vCount, out iCount, out idxType); int vertexByteSize = Marshal.SizeOf<TVertex> (); ulong vertSize = vCount * (ulong)vertexByteSize; ulong idxSize = iCount * (indexType == VkIndexType.Uint16 ? 2ul : 4ul); ulong size = vertSize + idxSize; int vertexCount = 0, indexCount = 0; int autoNamedMesh = 1; meshes = new List<Mesh> (); using (HostBuffer stagging = new HostBuffer (dev, VkBufferUsageFlags.TransferSrc, size)) { stagging.Map (); unsafe { Span<byte> stagVertPtrInit = new Span<byte>(stagging.MappedData.ToPointer (), (int)vertSize); Span<byte> stagIdxPtrInit = new Span<byte>((byte*)stagging.MappedData.ToPointer() + vertSize, (int)idxSize); Span<byte> stagVertPtr = stagVertPtrInit, stagIdxPtr = stagIdxPtrInit; foreach (GL.Mesh mesh in gltf.Meshes) { string meshName = mesh.Name; if (string.IsNullOrEmpty (meshName)) { meshName = "mesh_" + autoNamedMesh.ToString (); autoNamedMesh++; } Mesh m = new Mesh { Name = meshName }; foreach (GL.MeshPrimitive p in mesh.Primitives) { GL.Accessor AccPos = null, AccNorm = null, AccUv = null, AccUv1 = null; int accessorIdx; if (p.Attributes.TryGetValue ("POSITION", out accessorIdx)) { AccPos = gltf.Accessors[accessorIdx]; ensureBufferIsLoaded (gltf.BufferViews[(int)AccPos.BufferView].Buffer); } if (p.Attributes.TryGetValue ("NORMAL", out accessorIdx)) { AccNorm = gltf.Accessors[accessorIdx]; ensureBufferIsLoaded (gltf.BufferViews[(int)AccNorm.BufferView].Buffer); } if (p.Attributes.TryGetValue ("TEXCOORD_0", out accessorIdx)) { AccUv = gltf.Accessors[accessorIdx]; ensureBufferIsLoaded (gltf.BufferViews[(int)AccUv.BufferView].Buffer); } if (p.Attributes.TryGetValue ("TEXCOORD_1", out accessorIdx)) { AccUv1 = gltf.Accessors[accessorIdx]; ensureBufferIsLoaded (gltf.BufferViews[(int)AccUv1.BufferView].Buffer); } Primitive prim = new Primitive { indexBase = (uint)indexCount, vertexBase = vertexCount, vertexCount = (uint)AccPos.Count, material = (uint)(p.Material ?? 0) }; prim.bb.min.ImportFloatArray (AccPos.Min); prim.bb.max.ImportFloatArray (AccPos.Max); prim.bb.isValid = true; //Interleaving vertices Span<byte> inPosPtr = Span<byte>.Empty, inNormPtr = Span<byte>.Empty, inUvPtr = Span<byte>.Empty, inUv1Ptr = Span<byte>.Empty; GL.BufferView bv = gltf.BufferViews[(int)AccPos.BufferView]; inPosPtr = loadedBuffers[bv.Buffer].Span.Slice (AccPos.ByteOffset + bv.ByteOffset); if (AccNorm != null) { bv = gltf.BufferViews[(int)AccNorm.BufferView]; inNormPtr = loadedBuffers[bv.Buffer].Span.Slice (AccNorm.ByteOffset + bv.ByteOffset); } if (AccUv != null) { bv = gltf.BufferViews[(int)AccUv.BufferView]; inUvPtr = loadedBuffers[bv.Buffer].Span.Slice (AccUv.ByteOffset + bv.ByteOffset); } if (AccUv1 != null) { bv = gltf.BufferViews[(int)AccUv1.BufferView]; inUv1Ptr = loadedBuffers[bv.Buffer].Span.Slice (AccUv1.ByteOffset + bv.ByteOffset); } //TODO: use vertex attributes scan for copying data if they exists for (int j = 0; j < prim.vertexCount; j++) { inPosPtr.Slice (0, 12).CopyTo (stagVertPtr); inPosPtr = inPosPtr.Slice(12); if (!inNormPtr.IsEmpty) { inNormPtr.Slice (0, 12).CopyTo (stagVertPtr.Slice (12)); inNormPtr = inNormPtr.Slice (12); } if (inUvPtr != null) { inUvPtr.Slice (0, 8).CopyTo (stagVertPtr.Slice (24)); inUvPtr = inUvPtr.Slice (8); } if (inUv1Ptr != null) { inUv1Ptr.Slice (0, 8).CopyTo (stagVertPtr.Slice (32)); inUv1Ptr = inUvPtr.Slice (8); } stagVertPtr = stagVertPtr.Slice (vertexByteSize); } /*Span<byte> s = stagVertPtrInit; for (int i = 0; i < s.Length; i++) Console.Write (s[i].ToString ("X2") + (i % 32 == 0 ? "\n" : " "));*/ //indices loading if (p.Indices != null) { GL.Accessor acc = gltf.Accessors[(int)p.Indices]; bv = gltf.BufferViews[(int)acc.BufferView]; Span<byte> inIdxPtr = loadedBuffers[bv.Buffer].Span.Slice (acc.ByteOffset + bv.ByteOffset); //TODO:double check this, I dont seems to increment stag pointer if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_SHORT) { if (indexType == VkIndexType.Uint16) { inIdxPtr.Slice (0, acc.Count * 2).CopyTo (stagIdxPtr); stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2); } else { Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr); Span<ushort> inPtr = MemoryMarshal.Cast < byte, ushort> (inIdxPtr); for (int i = 0; i < acc.Count; i++) usPtr[i] = inPtr[i]; stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4); } } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_INT) { if (indexType == VkIndexType.Uint32) { inIdxPtr.Slice (0, acc.Count * 4).CopyTo (stagIdxPtr); stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4); } else { Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr); Span<uint> inPtr = MemoryMarshal.Cast<byte, uint> (inIdxPtr); for (int i = 0; i < acc.Count; i++) usPtr[i] = (ushort)inPtr[i]; stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2); } } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_BYTE) { //convert if (indexType == VkIndexType.Uint16) { Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr); for (int i = 0; i < acc.Count; i++) usPtr[i] = (ushort)inIdxPtr[i]; stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2); } else { Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr); for (int i = 0; i < acc.Count; i++) usPtr[i] = (uint)inIdxPtr[i]; stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4); } } else throw new NotImplementedException (); prim.indexCount = (uint)acc.Count; indexCount += acc.Count; } m.AddPrimitive (prim); vertexCount += AccPos.Count; } meshes.Add (m); } /*ReadOnlySpan<byte> tmp = new ReadOnlySpan<byte> (stagging.MappedData.ToPointer (), (int)size); Memory<byte> mtmp = new Memory<byte> (tmp.ToArray()); mtmp.Dump();*/ } stagging.Unmap (); PrimaryCommandBuffer cmd = cmdPool.AllocateCommandBuffer (); cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit); stagging.CopyTo (cmd, vbo, vertSize, 0, vboOffset); if (iCount>0) stagging.CopyTo (cmd, ibo, idxSize, vertSize, iboOffset); cmd.End (); transferQ.Submit (cmd); dev.WaitIdle (); cmd.Free (); } return meshes.ToArray (); }
private Dictionary <string, int> ConvertData(Dictionary <string, DataConvertArgs> argsMap, BinaryData binaryData, bool attribute) { Schema.BufferView bufferView = null; int?bufferViewIndex = null; var states = new List <ConvertDataState>(); var accessorsMap = new Dictionary <string, int>(); foreach (var pair in argsMap) { var args = pair.Value; var info = DataConverter.GetInfo(args.Data, binaryData.Writer); if (info.Values != null && bufferViewIndex == null) { var bufferViewName = argsMap.Count == 1 ? argsMap.First().Value.BufferViewName : "Interleaved attributes"; bufferViewIndex = CreateBufferView(bufferViewName, out bufferView); } var accessor = CreateInstance <Schema.Accessor>(); accessor.Name = args.AccessorName; accessor.BufferView = bufferViewIndex; info.SetCommon(accessor); if (args.MinMax) { info.SetMinMax(accessor); } states.Add(new ConvertDataState { Accessor = accessor, ValuesEnumerator = info.Values?.GetEnumerator(), SparseIndices = info.SparseIndices, SparseValues = info.SparseValues, }); accessorsMap.Add(pair.Key, accessors.Count); accessors.Add(accessor); } var counts = states.Select(state => state.Accessor.Count); if (counts.Skip(1).Any(count => count != counts.First())) { throw new InvalidOperationException("Data values cannot have different counts"); } if (bufferView != null) { bool aligned = false; int byteStride = 0; WriteBufferView(bufferView, binaryData, byteOffset => { while (states.All(state => state.ValuesEnumerator.MoveNext())) { foreach (var state in states) { if (byteStride == 0) { aligned |= binaryData.Writer.Align(state.Accessor.ComponentType.GetSize()); state.Accessor.ByteOffset = (int)binaryData.Writer.BaseStream.Position - byteOffset; } state.ValuesEnumerator.Current.Write(); } if (attribute) { aligned |= binaryData.Writer.Align(4); } if (byteStride == 0) { byteStride = (int)binaryData.Writer.BaseStream.Position - byteOffset; } } }); if (aligned || argsMap.Count > 1) { bufferView.ByteStride = byteStride; } } foreach (var state in states) { if (state.SparseIndices != null && state.SparseValues != null) { state.Accessor.Sparse.Indices.BufferView = CreateBufferView("Sparse Indices", out var indicesBufferView); WriteBufferView(indicesBufferView, binaryData, byteOffset => { foreach (var index in state.SparseIndices) { index.Write(); } }); state.Accessor.Sparse.Values.BufferView = CreateBufferView("Sparse Values", out var valuesBufferView); WriteBufferView(valuesBufferView, binaryData, byteOffset => { foreach (var index in state.SparseValues) { index.Write(); } }); } } return(accessorsMap); }
//TODO: some buffer data are reused between primitives, and I duplicate the datas //buffers must be constructed without duplications public Mesh[] LoadMeshes <TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset) { ulong vCount, iCount; VkIndexType idxType; GetVertexCount(out vCount, out iCount, out idxType); int vertexByteSize = Marshal.SizeOf <TVertex> (); ulong vertSize = vCount * (ulong)vertexByteSize; ulong idxSize = iCount * (indexType == VkIndexType.Uint16 ? 2ul : 4ul); ulong size = vertSize + idxSize; int vertexCount = 0, indexCount = 0; int autoNamedMesh = 1; meshes = new List <Mesh> (); using (HostBuffer stagging = new HostBuffer(dev, VkBufferUsageFlags.TransferSrc, size)) { stagging.Map(); unsafe { byte *stagVertPtrInit = (byte *)stagging.MappedData.ToPointer(); byte *stagIdxPtrInit = (byte *)(stagging.MappedData.ToPointer()) + vertSize; byte *stagVertPtr = stagVertPtrInit; byte *stagIdxPtr = stagIdxPtrInit; foreach (GL.Mesh mesh in gltf.Meshes) { string meshName = mesh.Name; if (string.IsNullOrEmpty(meshName)) { meshName = "mesh_" + autoNamedMesh.ToString(); autoNamedMesh++; } Mesh m = new Mesh { Name = meshName }; foreach (GL.MeshPrimitive p in mesh.Primitives) { GL.Accessor AccPos = null, AccNorm = null, AccUv = null, AccUv1 = null; int accessorIdx; if (p.Attributes.TryGetValue("POSITION", out accessorIdx)) { AccPos = gltf.Accessors[accessorIdx]; EnsureBufferIsLoaded(gltf.BufferViews[(int)AccPos.BufferView].Buffer); } if (p.Attributes.TryGetValue("NORMAL", out accessorIdx)) { AccNorm = gltf.Accessors[accessorIdx]; EnsureBufferIsLoaded(gltf.BufferViews[(int)AccNorm.BufferView].Buffer); } if (p.Attributes.TryGetValue("TEXCOORD_0", out accessorIdx)) { AccUv = gltf.Accessors[accessorIdx]; EnsureBufferIsLoaded(gltf.BufferViews[(int)AccUv.BufferView].Buffer); } if (p.Attributes.TryGetValue("TEXCOORD_1", out accessorIdx)) { AccUv1 = gltf.Accessors[accessorIdx]; EnsureBufferIsLoaded(gltf.BufferViews[(int)AccUv1.BufferView].Buffer); } Primitive prim = new Primitive { indexBase = (uint)indexCount, vertexBase = vertexCount, vertexCount = (uint)AccPos.Count, material = (uint)(p.Material ?? 0) }; prim.bb.min.ImportFloatArray(AccPos.Min); prim.bb.max.ImportFloatArray(AccPos.Max); prim.bb.isValid = true; //Interleaving vertices byte *inPosPtr = null, inNormPtr = null, inUvPtr = null, inUv1Ptr = null; GL.BufferView bv = gltf.BufferViews[(int)AccPos.BufferView]; inPosPtr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer(); inPosPtr += AccPos.ByteOffset + bv.ByteOffset; if (AccNorm != null) { bv = gltf.BufferViews[(int)AccNorm.BufferView]; inNormPtr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer(); inNormPtr += AccNorm.ByteOffset + bv.ByteOffset; } if (AccUv != null) { bv = gltf.BufferViews[(int)AccUv.BufferView]; inUvPtr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer(); inUvPtr += AccUv.ByteOffset + bv.ByteOffset; } if (AccUv1 != null) { bv = gltf.BufferViews[(int)AccUv1.BufferView]; inUv1Ptr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer(); inUv1Ptr += AccUv1.ByteOffset + bv.ByteOffset; } for (int j = 0; j < prim.vertexCount; j++) { System.Buffer.MemoryCopy(inPosPtr, stagVertPtr, 12, 12); inPosPtr += 12; if (inNormPtr != null) { System.Buffer.MemoryCopy(inNormPtr, stagVertPtr + 12, 12, 12); inNormPtr += 12; } if (inUvPtr != null) { System.Buffer.MemoryCopy(inUvPtr, stagVertPtr + 24, 8, 8); inUvPtr += 8; } if (inUv1Ptr != null) { System.Buffer.MemoryCopy(inUv1Ptr, stagVertPtr + 32, 8, 8); inUv1Ptr += 8; } stagVertPtr += vertexByteSize; } //indices loading if (p.Indices != null) { GL.Accessor acc = gltf.Accessors[(int)p.Indices]; bv = gltf.BufferViews[(int)acc.BufferView]; byte *inIdxPtr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer(); inIdxPtr += acc.ByteOffset + bv.ByteOffset; //TODO:double check this, I dont seems to increment stag pointer if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_SHORT) { if (indexType == VkIndexType.Uint16) { System.Buffer.MemoryCopy(inIdxPtr, stagIdxPtr, (long)acc.Count * 2, (long)acc.Count * 2); stagIdxPtr += (long)acc.Count * 2; } else { uint * usPtr = (uint *)stagIdxPtr; ushort *inPtr = (ushort *)inIdxPtr; for (int i = 0; i < acc.Count; i++) { usPtr[i] = inPtr[i]; } stagIdxPtr += (long)acc.Count * 4; } } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_INT) { if (indexType == VkIndexType.Uint32) { System.Buffer.MemoryCopy(inIdxPtr, stagIdxPtr, (long)acc.Count * 4, (long)acc.Count * 4); stagIdxPtr += (long)acc.Count * 4; } else { ushort *usPtr = (ushort *)stagIdxPtr; uint * inPtr = (uint *)inIdxPtr; for (int i = 0; i < acc.Count; i++) { usPtr[i] = (ushort)inPtr[i]; } stagIdxPtr += (long)acc.Count * 2; } } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_BYTE) { //convert if (indexType == VkIndexType.Uint16) { ushort *usPtr = (ushort *)stagIdxPtr; for (int i = 0; i < acc.Count; i++) { usPtr[i] = (ushort)inIdxPtr[i]; } stagIdxPtr += (long)acc.Count * 2; } else { uint *usPtr = (uint *)stagIdxPtr; for (int i = 0; i < acc.Count; i++) { usPtr[i] = (uint)inIdxPtr[i]; } stagIdxPtr += (long)acc.Count * 4; } } else { throw new NotImplementedException(); } prim.indexCount = (uint)acc.Count; indexCount += acc.Count; } m.AddPrimitive(prim); vertexCount += AccPos.Count; } meshes.Add(m); } } stagging.Unmap(); CommandBuffer cmd = cmdPool.AllocateCommandBuffer(); cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit); stagging.CopyTo(cmd, vbo, vertSize, 0, vboOffset); if (iCount > 0) { stagging.CopyTo(cmd, ibo, idxSize, vertSize, iboOffset); } cmd.End(); transferQ.Submit(cmd); dev.WaitIdle(); cmd.Free(); } return(meshes.ToArray()); }