Ejemplo n.º 1
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                Vertices.Unmap();
                Vertices.Dispose();
            }

            base.Dispose(disposing);
        }
Ejemplo n.º 2
0
        //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());
        }