unsafe private void ProcessMesh(FLVER2.Mesh mesh, FlverSubmesh dest) { var factory = Scene.Renderer.Factory; dest.Material = GPUMaterials[mesh.MaterialIndex]; //var MeshVertices = VerticesPool.Rent(mesh.VertexCount); var vSize = dest.Material.VertexSize; var meshVertices = Marshal.AllocHGlobal(mesh.VertexCount * (int)vSize); dest.PickingVertices = Marshal.AllocHGlobal(mesh.VertexCount * sizeof(Vector3)); var pvhandle = new Span <Vector3>(dest.PickingVertices.ToPointer(), mesh.VertexCount); if (dest.Material.LayoutType == MeshLayoutType.LayoutSky) { FillVerticesNormalOnly(mesh, pvhandle, meshVertices); } else if (dest.Material.LayoutType == MeshLayoutType.LayoutUV2) { FillVerticesUV2(mesh, pvhandle, meshVertices); } else { FillVerticesStandard(mesh, pvhandle, meshVertices); } dest.VertexCount = mesh.VertexCount; dest.MeshFacesets = new List <FlverSubmesh.FlverSubmeshFaceSet>(); var facesets = mesh.FaceSets; var fsUploadsPending = facesets.Count(); bool is32bit = Flver.Header.Version > 0x20005 && mesh.VertexCount > 65535; int indicesTotal = 0; ushort[] fs16 = null; int[] fs32 = null; foreach (var faceset in facesets) { indicesTotal += faceset.Indices.Length; } if (is32bit) { fs32 = new int[indicesTotal]; } else { fs16 = new ushort[indicesTotal]; } int idxoffset = 0; foreach (var faceset in facesets) { if (faceset.Indices.Length == 0) { continue; } //At this point they use 32-bit faceset vertex indices uint buffersize = (uint)faceset.IndicesCount * (is32bit ? 4u : 2u); var indices = faceset.TriangleStrip ? faceset.Triangulate(true).ToArray() : faceset.Indices.ToArray(); var newFaceSet = new FlverSubmesh.FlverSubmeshFaceSet() { BackfaceCulling = faceset.CullBackfaces, IsTriangleStrip = faceset.TriangleStrip, //IndexBuffer = factory.CreateBuffer(new BufferDescription(buffersize, BufferUsage.IndexBuffer)), IndexOffset = idxoffset, IndexCount = faceset.IndicesCount, Is32Bit = is32bit, PickingIndicesCount = indices.Length, //PickingIndices = Marshal.AllocHGlobal(indices.Length * 4), }; fixed(void *iptr = indices) { //Unsafe.CopyBlock(newFaceSet.PickingIndices.ToPointer(), iptr, (uint)indices.Length * 4); } if ((faceset.Flags & FLVER2.FaceSet.FSFlags.LodLevel1) > 0) { newFaceSet.LOD = 1; //HasNoLODs = false; newFaceSet.IsMotionBlur = false; } else if ((faceset.Flags & FLVER2.FaceSet.FSFlags.LodLevel2) > 0) { newFaceSet.LOD = 2; //HasNoLODs = false; newFaceSet.IsMotionBlur = false; } if ((faceset.Flags & FLVER2.FaceSet.FSFlags.MotionBlur) > 0) { newFaceSet.IsMotionBlur = true; } if (is32bit) { for (int i = 0; i < faceset.Indices.Length; i++) { if (faceset.Indices[i] == 0xFFFF && faceset.Indices[i] > mesh.Vertices.Length) { fs32[newFaceSet.IndexOffset + i] = -1; } else { fs32[newFaceSet.IndexOffset + i] = faceset.Indices[i]; } } } else { for (int i = 0; i < faceset.Indices.Length; i++) { if (faceset.Indices[i] == 0xFFFF && faceset.Indices[i] > mesh.Vertices.Length) { fs16[newFaceSet.IndexOffset + i] = 0xFFFF; } else { fs16[newFaceSet.IndexOffset + i] = (ushort)faceset.Indices[i]; } } } dest.MeshFacesets.Add(newFaceSet); idxoffset += faceset.Indices.Length; } dest.Bounds = BoundingBox.CreateFromPoints((Vector3 *)dest.PickingVertices.ToPointer(), dest.VertexCount, 12, Quaternion.Identity, Vector3.Zero, Vector3.One); uint vbuffersize = (uint)mesh.VertexCount * (uint)vSize; dest.GeomBuffer = Scene.Renderer.GeometryBufferAllocator.Allocate(vbuffersize, (uint)indicesTotal * (is32bit ? 4u : 2u), (int)vSize, 4, (h) => { h.FillVBuffer(meshVertices, vSize * (uint)mesh.VertexCount, () => { Marshal.FreeHGlobal(meshVertices); }); if (is32bit) { h.FillIBuffer(fs32); } else { h.FillIBuffer(fs16); } }); facesets = null; if (CaptureMaterialLayouts) { lock (_matLayoutLock) { if (!MaterialLayouts.ContainsKey(dest.Material.MaterialName)) { MaterialLayouts.Add(dest.Material.MaterialName, Flver.BufferLayouts[mesh.VertexBuffers[0].LayoutIndex]); } } } if (mesh.DefaultBoneIndex != -1 && mesh.DefaultBoneIndex < Bones.Count) { dest.LocalTransform = Utils.GetBoneObjectMatrix(Bones[mesh.DefaultBoneIndex], Bones); } Marshal.FreeHGlobal(dest.PickingVertices); }
unsafe private void ProcessMesh(FLVER0.Mesh mesh, FlverSubmesh dest) { var factory = Scene.Renderer.Factory; dest.Material = GPUMaterials[mesh.MaterialIndex]; //var MeshVertices = VerticesPool.Rent(mesh.VertexCount); var vSize = dest.Material.VertexSize; var meshVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * (int)vSize); dest.PickingVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * sizeof(Vector3)); var pvhandle = new Span <Vector3>(dest.PickingVertices.ToPointer(), mesh.Vertices.Count); if (dest.Material.LayoutType == MeshLayoutType.LayoutSky) { FillVerticesNormalOnly(mesh, pvhandle, meshVertices); } else if (dest.Material.LayoutType == MeshLayoutType.LayoutUV2) { FillVerticesUV2(mesh, pvhandle, meshVertices); } else { FillVerticesStandard(mesh, pvhandle, meshVertices); } dest.VertexCount = mesh.Vertices.Count; dest.MeshFacesets = new List <FlverSubmesh.FlverSubmeshFaceSet>(); bool is32bit = false;//FlverDeS.Version > 0x20005 && mesh.Vertices.Count > 65535; int indicesTotal = 0; ushort[] fs16 = null; int[] fs32 = null; int idxoffset = 0; if (mesh.VertexIndices.Count != 0) { var indices = mesh.Triangulate(FlverDeS.Version).ToArray(); uint buffersize = (uint)indices.Length * (is32bit ? 4u : 2u); indicesTotal = indices.Length; if (is32bit) { fs32 = new int[indicesTotal]; } else { fs16 = new ushort[indicesTotal]; } var newFaceSet = new FlverSubmesh.FlverSubmeshFaceSet() { BackfaceCulling = true, IsTriangleStrip = false, //IndexBuffer = factory.CreateBuffer(new BufferDescription(buffersize, BufferUsage.IndexBuffer)), IndexOffset = idxoffset, IndexCount = indices.Length, Is32Bit = is32bit, PickingIndicesCount = indices.Length, //PickingIndices = Marshal.AllocHGlobal(indices.Length * 4), }; fixed(void *iptr = indices) { //Unsafe.CopyBlock(newFaceSet.PickingIndices.ToPointer(), iptr, (uint)indices.Length * 4); } if (is32bit) { for (int i = 0; i < indices.Length; i++) { if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count) { fs32[newFaceSet.IndexOffset + i] = -1; } else { fs32[newFaceSet.IndexOffset + i] = indices[i]; } } } else { for (int i = 0; i < indices.Length; i++) { if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count) { fs16[newFaceSet.IndexOffset + i] = 0xFFFF; } else { fs16[newFaceSet.IndexOffset + i] = (ushort)indices[i]; } } } dest.MeshFacesets.Add(newFaceSet); } dest.Bounds = BoundingBox.CreateFromPoints((Vector3 *)dest.PickingVertices.ToPointer(), dest.VertexCount, 12, Quaternion.Identity, Vector3.Zero, Vector3.One); uint vbuffersize = (uint)mesh.Vertices.Count * (uint)vSize; dest.GeomBuffer = Scene.Renderer.GeometryBufferAllocator.Allocate(vbuffersize, (uint)indicesTotal * (is32bit ? 4u : 2u), (int)vSize, 4, (h) => { h.FillVBuffer(meshVertices, vSize * (uint)mesh.Vertices.Count, () => { Marshal.FreeHGlobal(meshVertices); }); if (is32bit) { h.FillIBuffer(fs32); } else { h.FillIBuffer(fs16); } }); if (CaptureMaterialLayouts) { lock (_matLayoutLock) { if (!MaterialLayouts.ContainsKey(dest.Material.MaterialName)) { MaterialLayouts.Add(dest.Material.MaterialName, Flver.BufferLayouts[mesh.LayoutIndex]); } } } }