internal static MyMaterialShadersBundleId Get(MyStringId material, MyStringId materialPass, VertexLayoutId vertexLayout, MyShaderUnifiedFlags flags) { int hash = 0; MyHashHelper.Combine(ref hash, material.GetHashCode()); MyHashHelper.Combine(ref hash, materialPass.GetHashCode()); MyHashHelper.Combine(ref hash, vertexLayout.GetHashCode()); MyHashHelper.Combine(ref hash, unchecked ((int)flags)); if (HashIndex.ContainsKey(hash)) { return(HashIndex[hash]); } var id = new MyMaterialShadersBundleId { Index = BundleInfo.Allocate() }; MyArrayHelpers.Reserve(ref Bundles, id.Index + 1); HashIndex[hash] = id; BundleInfo.Data[id.Index] = new MyMaterialShadersInfo { Material = material, Pass = materialPass, Layout = vertexLayout, Flags = flags }; Bundles[id.Index] = new MyMaterialShadersBundle { }; InitBundle(id); return(id); }
public static PixelShaderId CreatePs(string file, ShaderMacro[] macros = null) { var bytecode = CreateBytecode(); var id = new PixelShaderId { Index = PixelShaders.Allocate() }; PixelShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref PsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT_(file), Profile = MyShaderProfile.ps_5_0, Macros = macros }; PsObjects[id.Index] = null; InitPs(id, file); PsIndex.Add(id); return(id); }
internal static unsafe void UpdateGeneric(InstancingId id, List <MyInstanceData> instanceData, int capacity) { Debug.Assert(id.Info.Type == MyRenderInstanceBufferType.Generic); var info = id.Info; var byteSize = info.Stride * capacity; if (Instancings.Data[id.Index].Data == null) { Instancings.Data[id.Index].Data = new byte[byteSize]; } else { MyArrayHelpers.Reserve(ref Instancings.Data[id.Index].Data, byteSize); } var list = instanceData.ToArray(); fixed(void *src = list) { fixed(void *dst = Instancings.Data[id.Index].Data) { SharpDX.Utilities.CopyMemory(new IntPtr(dst), new IntPtr(src), info.Stride * list.Length); } } Instancings.Data[id.Index].Capacity = capacity; UpdateVertexBuffer(id); }
internal static ComputeShaderId CreateCs(string file, ShaderMacro[] macros = null) { var bytecode = CreateBytecode(); var id = new ComputeShaderId { Index = ComputeShaders.Allocate() }; ComputeShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref CsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT_(file), Profile = MyShaderProfile.cs_5_0, Macros = macros, }; CsObjects[id.Index] = null; InitCs(id, file); CsIndex.Add(id); return(id); }
internal unsafe static InstancingId Create(uint GID, MyRenderInstanceBufferType type, string debugName) { var id = new InstancingId { Index = Instancings.Allocate() }; Instancings.Data[id.Index] = new MyInstancingInfo { Type = type, DebugName = debugName }; MyArrayHelpers.Reserve(ref Data, id.Index + 1); Data[id.Index] = new MyInstancingData { VB = VertexBufferId.NULL }; if (type == MyRenderInstanceBufferType.Cube) { Instancings.Data[id.Index].Layout = MyVertexLayouts.GetLayout(new MyVertexInputComponent(MyVertexInputComponentType.CUBE_INSTANCE, 2, MyVertexInputComponentFreq.PER_INSTANCE)); Instancings.Data[id.Index].Stride = sizeof(MyVertexFormatCubeInstance); } else { Instancings.Data[id.Index].Layout = MyVertexLayouts.GetLayout(new MyVertexInputComponent(MyVertexInputComponentType.GENERIC_INSTANCE, 2, MyVertexInputComponentFreq.PER_INSTANCE)); Instancings.Data[id.Index].Stride = sizeof(MyVertexFormatGenericInstance); } Debug.Assert(!IdIndex.ContainsKey(GID), "Creating instance with ID that already exists!"); IdIndex.Add(GID, id); return(id); }
internal static LightId Create(uint GID) { var id = new LightId { Index = Lights.Allocate() }; Lights.Data[id.Index] = new MyLightInfo { }; MyArrayHelpers.Reserve(ref Pointlights, id.Index + 1); MyArrayHelpers.Reserve(ref Spotlights, id.Index + 1); Pointlights[id.Index] = new MyPointlightInfo { LastBvhUpdatePosition = Vector3.PositiveInfinity, BvhProxyId = -1 }; Spotlights[id.Index] = new MySpotlightInfo { LastBvhUpdatePosition = Vector3.PositiveInfinity, BvhProxyId = -1 }; IdIndex[GID] = id; return(id); }
internal static VertexBufferId CreateVertexBuffer(BufferDescription description, int stride, IntPtr?data, string debugName) { if (description.SizeInBytes == 0) { return(VertexBufferId.NULL); } var id = new VertexBufferId { Index = VBuffers.Allocate() }; MyArrayHelpers.Reserve(ref VBuffersData, id.Index + 1); VBuffers.Data[id.Index] = new MyHwBufferDesc { Description = description, DebugName = debugName }; VBuffersData[id.Index] = new MyVertexBufferData { Stride = stride }; VbIndices.Add(id); if (!data.HasValue) { InitVertexBuffer(id); } else { InitVertexBuffer(id, data.Value); } return(id); }
internal static VertexShaderId CreateVs(string file, ShaderMacro[] macros = null) { var bytecode = CreateBytecode(); var id = new VertexShaderId { Index = VertexShaders.Allocate() }; VertexShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref VsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT_(file), Profile = MyShadersDefines.Profiles.vs_5_0, Macros = macros }; VsObjects[id.Index] = null; InitVs(id); VsIndex.Add(id); return(id); }
internal static StructuredBufferId CreateStructuredBuffer(BufferDescription description, IntPtr?data, string debugName) { var id = new StructuredBufferId { Index = SBuffers.Allocate() }; MyArrayHelpers.Reserve(ref SBuffersData, id.Index + 1); SBuffers.Data[id.Index] = new MyHwBufferDesc { Description = description, DebugName = debugName }; SBuffersData[id.Index] = new MyStructuredBufferData { }; SbIndices.Add(id); if (!data.HasValue) { InitStructuredBuffer(id); } else { InitStructuredBuffer(id, data.Value); } return(id); }
internal static GeometryShaderId CreateGs(string file, ShaderMacro[] macros = null, MyShaderStreamOutputInfo?streamOut = null) { var bytecode = CreateBytecode(); var id = new GeometryShaderId { Index = GeometryShaders.Allocate() }; GeometryShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref GsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT_(file), Profile = MyShadersDefines.Profiles.gs_5_0, Macros = macros }; GsObjects[id.Index] = null; if (streamOut.HasValue) { StreamOutputs[id] = streamOut.Value; } InitGs(id); GsIndex.Add(id); return(id); }
internal static ComputeShaderId CreateCs(string file, string func, string header = "") { var bytecode = CreateBytecode(); var id = new ComputeShaderId { Index = ComputeShaders.Allocate() }; ComputeShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref CsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT(file), Function = X.TEXT(func), Profile = MyShaderProfileEnum.CS_5_0, Header = header, Name = String.Format("cs_[{0}][{1}]{2}", file, func, header != null ? header.Replace(Environment.NewLine, "_") : "") }; CsObjects[id.Index] = null; InitCs(id); CsIndex.Add(id); return(id); }
internal static IndexBufferId CreateIndexBuffer(BufferDescription description, Format format, IntPtr?data, string debugName) { var id = new IndexBufferId { Index = IBuffers.Allocate() }; MyArrayHelpers.Reserve(ref IBuffersData, id.Index + 1); IBuffers.Data[id.Index] = new MyHwBufferDesc { Description = description, DebugName = debugName }; IBuffersData[id.Index] = new MyIndexBufferData { Format = format }; IbIndices.Add(id); if (!data.HasValue) { InitIndexBuffer(id); } else { InitIndexBuffer(id, data.Value); } return(id); }
private void PrepareSpotlights() { MyLights.SpotlightsBvh.OverlapAllFrustum(ref MyEnvironment.ViewFrustumClippedD, MyLightRendering.VisibleSpotlights); if (MyLightRendering.VisibleSpotlights.Count == 0) { OtherShadowsTriangleCounter = 0; } MyLightRendering.VisibleSpotlights.Sort(m_spotlightCastersComparer); MyArrayHelpers.Reserve(ref MyLightRendering.Spotlights, MyLightRendering.VisibleSpotlights.Count); int index = 0; int casterIndex = 0; foreach (var id in MyLightRendering.VisibleSpotlights) { var nearPlaneDistance = 0.5f; var worldMatrix = MatrixD.CreateTranslation(MyEnvironment.CameraPosition); var viewMatrix = MatrixD.CreateLookAt(id.Position, id.Position + MyLights.Spotlights[id.Index].Direction, MyLights.Spotlights[id.Index].Up); var projectionMatrix = MatrixD.CreatePerspectiveFieldOfView((float)(Math.Acos(MyLights.Spotlights[id.Index].ApertureCos) * 2), 1.0f, nearPlaneDistance, Math.Max(id.ShadowDistance, nearPlaneDistance)); var viewProjection = viewMatrix * projectionMatrix; MatrixD worldViewProjection = worldMatrix * viewProjection; MyLightRendering.Spotlights[index].ShadowMatrix = Matrix.Transpose(worldViewProjection * MyMatrixHelpers.ClipspaceToTexture); if (id.CastsShadows && casterIndex < MAX_SPOTLIGHT_SHADOWCASTERS) { if (ShadowmapsPool.Count <= casterIndex) { ShadowmapsPool.Add(MyRwTextures.CreateShadowmap(SpotlightShadowmapSize, SpotlightShadowmapSize)); } MyLights.Lights.Data[id.Index].CastsShadowsThisFrame = true; var query = new MyShadowmapQuery { DepthBuffer = ShadowmapsPool[casterIndex].Dsv, Viewport = new MyViewport(SpotlightShadowmapSize, SpotlightShadowmapSize), QueryType = MyFrustumEnum.ShadowProjection, ProjectionInfo = new MyProjectionInfo { WorldCameraOffsetPosition = MyEnvironment.CameraPosition, WorldToProjection = viewProjection, LocalToProjection = worldViewProjection }, IgnoredEntities = MyLights.IgnoredEntitites.ContainsKey(id) ? MyLights.IgnoredEntitites[id] : null, }; m_shadowmapQueries.Add(query); ++casterIndex; } else { MyLights.Lights.Data[id.Index].CastsShadowsThisFrame = false; } MyLights.WriteSpotlightConstants(id, ref MyLightRendering.Spotlights[index]); index++; } }
static void PrepareSpotlights() { MyLights.SpotlightsBvh.OverlapAllFrustum(ref MyEnvironment.ViewFrustum, MyLightRendering.VisibleSpotlights); MyLightRendering.VisibleSpotlights.Sort(m_spotlightCastersComparer); while (MyLightRendering.VisibleSpotlights.Count > MAX_SPOTLIGHT_SHADOWCASTERS) { MyLightRendering.VisibleSpotlights.RemoveAtFast(MyLightRendering.VisibleSpotlights.Count - 1); } MyArrayHelpers.Reserve(ref MyLightRendering.Spotlights, MyLightRendering.VisibleSpotlights.Count); int index = 0; int casterIndex = 0; foreach (var id in MyLightRendering.VisibleSpotlights) { MyLights.WriteSpotlightConstants(id, ref MyLightRendering.Spotlights[index]); if (id.CastsShadows) { var query = new MyShadowmapQuery(); if (MyLights.IgnoredEntitites.ContainsKey(id)) { query.IgnoredEntities = MyLights.IgnoredEntitites[id]; } var shadowMatrix = Matrix.CreateLookAt(id.Position, id.Position + MyLights.Spotlights[id.Index].Direction, MyLights.Spotlights[id.Index].Up) * Matrix.CreatePerspectiveFieldOfView((float)(Math.Acos(MyLights.Spotlights[id.Index].ApertureCos) * 2), 1.0f, 0.5f, id.ShadowDistance); if (ShadowmapsPool.Count <= casterIndex) { ShadowmapsPool.Add(MyRwTextures.CreateShadowmap(512, 512)); } query.DepthBuffer = ShadowmapsPool[casterIndex].Dsv; query.Viewport = new MyViewport(512, 512); query.QueryType = MyFrustumEnum.ShadowProjection; query.ProjectionInfo = new MyProjectionInfo { WorldCameraOffsetPosition = MyEnvironment.CameraPosition, WorldToProjection = shadowMatrix, LocalToProjection = Matrix.CreateTranslation(MyEnvironment.CameraPosition) * shadowMatrix }; MyLightRendering.Spotlights[index].ShadowMatrix = Matrix.Transpose(query.ProjectionInfo.CurrentLocalToProjection * MyMatrixHelpers.ClipspaceToTexture); m_shadowmapQueries.Add(query); casterIndex++; } index++; } }
internal static RasterizerId CreateRasterizerState(RasterizerStateDescription description) { var id = new RasterizerId { Index = RasterizerStates.Allocate() }; MyArrayHelpers.Reserve(ref RasterizerObjects, id.Index + 1); RasterizerStates.Data[id.Index] = description; InitRasterizerState(id); RasterizerIndices.Add(id); return(id); }
internal static DepthStencilId CreateDepthStencil(DepthStencilStateDescription description) { var id = new DepthStencilId { Index = DepthStencilStates.Allocate() }; MyArrayHelpers.Reserve(ref DepthStencilObjects, id.Index + 1); DepthStencilStates.Data[id.Index] = description; InitDepthStencilState(id); DepthStencilIndices.Add(id); return(id); }
internal static SamplerId CreateSamplerState(SamplerStateDescription description) { var id = new SamplerId { Index = SamplerStates.Allocate() }; MyArrayHelpers.Reserve(ref SamplerObjects, id.Index + 1); SamplerStates.Data[id.Index] = description; InitSamplerState(id); SamplerIndices.Add(id); return(id); }
internal static BlendId CreateBlendState(BlendStateDescription description) { var id = new BlendId { Index = BlendStates.Allocate() }; MyArrayHelpers.Reserve(ref BlendObjects, id.Index + 1); BlendStates.Data[id.Index] = description.Clone(); InitBlendState(id); BlendIndices.Add(id); return(id); }
internal static unsafe void RebuildGeneric(InstancingId id) { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("RebuildGeneric"); Debug.Assert(id.Info.Type == MyRenderInstanceBufferType.Generic); var info = id.Info; int capacity = Instancings.Data[id.Index].InstanceData.Length; for (int i = 0; i < Instancings.Data[id.Index].TotalCapacity; i++) { if (!Instancings.Data[id.Index].VisibilityMask[i]) { capacity--; } } var byteSize = info.Stride * capacity; if (Instancings.Data[id.Index].Data == null) { Instancings.Data[id.Index].Data = new byte[byteSize]; } else { MyArrayHelpers.Reserve(ref Instancings.Data[id.Index].Data, byteSize); } fixed(void *src = Instancings.Data[id.Index].InstanceData) { fixed(void *dst = Instancings.Data[id.Index].Data) { int currentIndex = 0; for (int i = 0; i < Instancings.Data[id.Index].TotalCapacity; i++) { if (Instancings.Data[id.Index].VisibilityMask[i]) { SharpDX.Utilities.CopyMemory(new IntPtr(dst) + currentIndex * info.Stride, new IntPtr(src) + i * info.Stride, info.Stride); currentIndex++; } } } } Instancings.Data[id.Index].VisibleCapacity = capacity; UpdateVertexBuffer(id); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); }
public static void CreateBlendState(ref BlendId id, BlendStateDescription description) { if (id == BlendId.NULL) { id = new BlendId(BlendStates.Allocate()); MyArrayHelpers.Reserve(ref BlendObjects, id.Index + 1); BlendIndices.Add(id); } else { BlendObjects[id.Index].Dispose(); } BlendStates.Data[id.Index] = description.Clone(); InitBlendState(id); }
public static void CreateDepthStencil(ref DepthStencilId id, DepthStencilStateDescription description) { if (id == DepthStencilId.NULL) { id = new DepthStencilId(DepthStencilStates.Allocate()); MyArrayHelpers.Reserve(ref DepthStencilObjects, id.Index + 1); DepthStencilIndices.Add(id); } else { DepthStencilObjects[id.Index].Dispose(); } DepthStencilStates.Data[id.Index] = description; InitDepthStencilState(id); }
internal static ConstantsBufferId CreateConstantsBuffer(BufferDescription description, string debugName) { var id = new ConstantsBufferId { Index = CBuffers.Allocate() }; MyArrayHelpers.Reserve(ref CBuffersData, id.Index + 1); CBuffers.Data[id.Index] = new MyHwBufferDesc { Description = description, DebugName = debugName }; CbIndices.Add(id); InitConstantsBuffer(id); return(id); }
private void PrepareSpotlights() { MyLights.SpotlightsBvh.OverlapAllFrustum(ref MyEnvironment.ViewFrustumClippedD, MyLightRendering.VisibleSpotlights); if (MyLightRendering.VisibleSpotlights.Count == 0) OtherShadowsTriangleCounter = 0; return; MyLightRendering.VisibleSpotlights.Sort(m_spotlightCastersComparer); MyArrayHelpers.Reserve(ref MyLightRendering.Spotlights, MyLightRendering.VisibleSpotlights.Count); int index = 0; int casterIndex = 0; var worldMatrix = MatrixD.CreateTranslation(MyEnvironment.CameraPosition); foreach (var id in MyLightRendering.VisibleSpotlights) { if (id.CastsShadows && casterIndex < MAX_SPOTLIGHT_SHADOWCASTERS) { if(ShadowmapsPool.Count <= casterIndex) ShadowmapsPool.Add(MyRwTextures.CreateShadowmap(SpotlightShadowmapSize, SpotlightShadowmapSize)); MyLights.Lights.Data[id.Index].CastsShadowsThisFrame = true; MatrixD viewProjection = MyLights.GetSpotlightViewProjection(id); var query = new MyShadowmapQuery { DepthBuffer = ShadowmapsPool[casterIndex].Dsv, Viewport = new MyViewport(SpotlightShadowmapSize, SpotlightShadowmapSize), QueryType = MyFrustumEnum.ShadowProjection, ProjectionInfo = new MyProjectionInfo { WorldCameraOffsetPosition = MyEnvironment.CameraPosition, WorldToProjection = viewProjection, LocalToProjection = worldMatrix * viewProjection }, IgnoredEntities = MyLights.IgnoredEntitites.ContainsKey(id) ? MyLights.IgnoredEntitites[id] : null, }; m_shadowmapQueries.Add(query); ++casterIndex; } else { MyLights.Lights.Data[id.Index].CastsShadowsThisFrame = false; } index++; } }
internal static unsafe void UpdateCube(InstancingId id, List <MyCubeInstanceData> instanceData, int capacity) { Debug.Assert(id.Info.Type == MyRenderInstanceBufferType.Cube); var info = id.Info; var byteSize = info.Stride * capacity; if (Instancings.Data[id.Index].Data == null) { Instancings.Data[id.Index].Data = new byte[byteSize]; } else { MyArrayHelpers.Reserve(ref Instancings.Data[id.Index].Data, byteSize); } //var rawBuffer = new MyVertexFormatCubeInstance[m_capacity]; fixed(void *dst = Instancings.Data[id.Index].Data) { MyVertexFormatCubeInstance *ptr = (MyVertexFormatCubeInstance *)dst; for (int i = 0; i < instanceData.Count; i++) { fixed(byte *pSource = instanceData[i].RawBones()) { for (int j = 0; j < MyRender11Constants.CUBE_INSTANCE_BONES_NUM * 4; j++) { ptr[i].bones[j] = pSource[j]; } } ptr[i].translationRotation = new HalfVector4(instanceData[i].m_translationAndRot); var colorMaskHSV = instanceData[i].ColorMaskHSV; //Vector3 color = MyRender11.ColorFromMask(new Vector3(colorMaskHSV.X, colorMaskHSV.Y, colorMaskHSV.Z)); ptr[i].colorMaskHSV = new HalfVector4(colorMaskHSV); } } Instancings.Data[id.Index].Capacity = capacity; UpdateVertexBuffer(id); }
internal static InputLayoutId CreateIL(ShaderBytecodeId bytecode, VertexLayoutId layout) { var id = new InputLayoutId { Index = InputLayouts.Allocate() }; MyArrayHelpers.Reserve(ref ILObjects, id.Index + 1); InputLayouts.Data[id.Index] = new InputLayoutInfo { BytecodeId = bytecode, VLayoutId = layout }; ILObjects[id.Index] = null; InitIL(id); ILIndex.Add(id); return(id); }
internal static GeometryShaderId CreateGs(string file, string func, string header = "", MyShaderStreamOutputInfo?streamOut = null) { var bytecode = CreateBytecode(); var id = new GeometryShaderId { Index = GeometryShaders.Allocate() }; GeometryShaders.Data[id.Index] = new MyShaderInfo { Bytecode = bytecode }; MyArrayHelpers.Reserve(ref GsObjects, id.Index + 1); // compile at once Shaders[bytecode] = new MyShaderCompilationInfo { File = X.TEXT(file), Function = X.TEXT(func), Profile = MyShaderProfileEnum.GS_5_0, Header = header, Name = String.Format("gs_[{0}][{1}]{2}", file, func, header != null ? header.Replace(Environment.NewLine, "_") : "") }; GsObjects[id.Index] = null; if (streamOut.HasValue) { StreamOutputs[id] = streamOut.Value; } InitGs(id); GsIndex.Add(id); return(id); }
internal unsafe void AddMesh(MeshId model) { Debug.Assert(IsMergable(model)); var key = new MyMeshTableEntry { Model = model, Lod = 0, Part = 0 }; if (!ContainsKey(key)) { var vertexOffset = m_vertices; var indexOffset = m_indices; var mesh = MyMeshes.GetLodMesh(model, 0); Debug.Assert(mesh.Info.Data.IndicesFmt == SharpDX.DXGI.Format.R16_UInt); var meshInfo = mesh.Info; var data = meshInfo.Data; int verticesCapacity = vertexOffset + meshInfo.VerticesNum; int indicesCapacity = CalculateIndicesCapacity(indexOffset, meshInfo.IndicesNum); m_vertices = verticesCapacity; m_indices = indicesCapacity; MyArrayHelpers.Reserve(ref m_vertexStream0, verticesCapacity * Stride0, 1024 * 1024); MyArrayHelpers.Reserve(ref m_vertexStream1, verticesCapacity * Stride1, 1024 * 1024); MyArrayHelpers.Reserve(ref m_indexStream, indicesCapacity * IndexStride, 1024 * 1024); var list = new List <int>(); fixed(byte *src = data.VertexStream0, dst_ = m_vertexStream0) { byte *dst = dst_ + data.Stride0 * vertexOffset; SharpDX.Utilities.CopyMemory(new IntPtr(dst), new IntPtr(src), data.Stride0 * meshInfo.VerticesNum); } fixed(byte *src = data.VertexStream1, dst_ = m_vertexStream1) { byte *dst = dst_ + data.Stride1 * vertexOffset; SharpDX.Utilities.CopyMemory(new IntPtr(dst), new IntPtr(src), data.Stride1 * meshInfo.VerticesNum); } fixed(void *dst = m_indexStream) { uint *stream = (uint *)dst; stream += indexOffset; fixed(void *src = data.Indices) { ushort *indices = (ushort *)src; for (int k = 0; k < meshInfo.IndicesNum; k += m_indexPageSize) { int iEnd = Math.Min(k + m_indexPageSize, meshInfo.IndicesNum); for (int i = k; i < iEnd; i++) { stream[i] = (uint)(indices[i] + vertexOffset); } list.Add(m_pagesUsed++); } if ((meshInfo.IndicesNum % m_indexPageSize) != 0) { var pageIndex = meshInfo.IndicesNum / m_indexPageSize; var pageOffset = meshInfo.IndicesNum % m_indexPageSize; uint lastIndex = stream[pageIndex * m_indexPageSize + pageOffset - 1]; for (int i = pageOffset; i < m_indexPageSize; i++) { stream[pageIndex * m_indexPageSize + i] = lastIndex; } } } } m_table.Add(key, new MyMeshTableSrv_Entry { Pages = list }); m_dirty = true; } }