void EndSingleMaterial(MySingleMaterialHelper materialHelper)
        {
            //Synchronize to VRage render
            if (materialHelper.IndexCount > 0 && materialHelper.VertexCount > 0)
            {
                //Todo - is it possible without allocations?
                MyVertexFormatVoxelSingleData[] vertices = new MyVertexFormatVoxelSingleData[materialHelper.VertexCount];
                Array.Copy(materialHelper.Vertices, vertices, vertices.Length);
                short[] indices = new short[materialHelper.IndexCount];
                Array.Copy(materialHelper.Indices, indices, indices.Length);

                VRageRender.MyRenderProxy.UpdateRenderVoxelCell(
                    VoxelMap.GetRenderObjectID(ref this.CellCoord),
                    (VRageRender.MyLodTypeEnum)(int)CellHashType,
                    vertices,
                    indices,
                    (int)materialHelper.Material.Index,
                    -1,
                    -1);
            }

            //  Reset helper arrays, so we can start adding triangles to them again
            materialHelper.IndexCount = 0;
            materialHelper.VertexCount = 0;
            MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[(int)materialHelper.Material.Index]++;
        }
        private static void AddVertexToBuffer(MySingleMaterialHelper materialHelper, ref MyVoxelVertex vertex0,
                                              int matIndex, short vertexIndex0)
        {
            MyVoxelCacheCellRenderHelper.CreateArrayIfNotExist(matIndex);

            if (MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].CalcCounter !=
                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[matIndex])
            {
                int nextVertexIndex = materialHelper.VertexCount;

                //  Short overflow check
                System.Diagnostics.Debug.Assert(nextVertexIndex <= short.MaxValue);

                // copy position and ambient
                materialHelper.Vertices[nextVertexIndex].Position = vertex0.Position;
                materialHelper.Vertices[nextVertexIndex].Ambient  = vertex0.Ambient;

                // Copy normal
                materialHelper.Vertices[nextVertexIndex].Normal = vertex0.Normal;

                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].CalcCounter =
                    MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[matIndex];
                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].VertexIndex =
                    (short)nextVertexIndex;

                materialHelper.VertexCount++;
            }
        }
        void EndSingleMaterial(MySingleMaterialHelper materialHelper)
        {
            //Synchronize to VRage render
            if (materialHelper.IndexCount > 0 && materialHelper.VertexCount > 0)
            {
                //Todo - is it possible without allocations?
                MyVertexFormatVoxelSingleData[] vertices = new MyVertexFormatVoxelSingleData[materialHelper.VertexCount];
                Array.Copy(materialHelper.Vertices, vertices, vertices.Length);
                short[] indices = new short[materialHelper.IndexCount];
                Array.Copy(materialHelper.Indices, indices, indices.Length);

                VRageRender.MyRenderProxy.UpdateRenderVoxelCell(
                    VoxelMap.GetRenderObjectID(ref this.CellCoord),
                    (VRageRender.MyLodTypeEnum)(int) CellHashType,
                    vertices,
                    indices,
                    (int)materialHelper.Material.Index,
                    -1,
                    -1);
            }

            //  Reset helper arrays, so we can start adding triangles to them again
            materialHelper.IndexCount  = 0;
            materialHelper.VertexCount = 0;
            MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[(int)materialHelper.Material.Index]++;
        }
        private static void AddVertexToBuffer(MySingleMaterialHelper materialHelper, ref MyVoxelVertex vertex0,
            int matIndex, short vertexIndex0)
        {
            MyVoxelCacheCellRenderHelper.CreateArrayIfNotExist(matIndex);

            if (MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].CalcCounter !=
                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[matIndex])
            {
                int nextVertexIndex = materialHelper.VertexCount;

                //  Short overflow check
                System.Diagnostics.Debug.Assert(nextVertexIndex <= short.MaxValue);

                // copy position and ambient
                materialHelper.Vertices[nextVertexIndex].Position = vertex0.Position;
                materialHelper.Vertices[nextVertexIndex].Ambient = vertex0.Ambient;

                // Copy normal
                materialHelper.Vertices[nextVertexIndex].Normal = vertex0.Normal;

                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].CalcCounter =
                    MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[matIndex];
                MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][vertexIndex0].VertexIndex =
                    (short)nextVertexIndex;

                materialHelper.VertexCount++;
            }
        }
        //  This method adds triangles from one data cell into this render cell. Single-texture triangles are added using indices (so we use m_notCompressedIndex buffer).
        //  For this we need to find indices. We use lookup array for it.
        //  Now we support only 16-bit indices, so vertex buffer can't have more then short.MaxValue vertices.
        public void AddTriangles(List <MyVoxelGeometry.CellData> cacheDataArray)
        {
            foreach (var cacheData in cacheDataArray)
            {
                //  Increase lookup count, so we will think that all vertexes in helper arrays are new
                for (int i = 0; i < MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount.Length; i++)
                {
                    MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[i]++;
                }

                for (int i = 0; i < cacheData.VoxelTrianglesCount; i++)
                {
                    MyVoxelTriangle triangle = cacheData.VoxelTriangles[i];
                    MyVoxelVertex   vertex0, vertex1, vertex2;
                    cacheData.GetUnpackedVertex(triangle.VertexIndex0, out vertex0);
                    cacheData.GetUnpackedVertex(triangle.VertexIndex1, out vertex1);
                    cacheData.GetUnpackedVertex(triangle.VertexIndex2, out vertex2);

                    vertex0.Position = (vertex0.Position - m_positionOffset) / m_positionScale;
                    vertex1.Position = (vertex1.Position - m_positionOffset) / m_positionScale;
                    vertex2.Position = (vertex2.Position - m_positionOffset) / m_positionScale;
                    Debug.Assert(vertex0.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One));
                    Debug.Assert(vertex1.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One));
                    Debug.Assert(vertex2.Position.IsInsideInclusive(ref Vector3.Zero, ref Vector3.One));

                    if ((vertex0.Material == vertex1.Material) && (vertex0.Material == vertex2.Material))
                    {
                        var matDef = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)vertex0.Material);

                        //  This is single-texture triangleVertexes, so we can choose material from any edge
                        MySingleMaterialHelper materialHelper = MyVoxelCacheCellRenderHelper.GetForMaterial(matDef);

                        //  Add vertex0 to vertex buffer
                        AddVertexToBuffer(materialHelper, ref vertex0, matDef.Index, triangle.VertexIndex0);

                        //  Add vertex1 to vertex buffer
                        AddVertexToBuffer(materialHelper, ref vertex1, matDef.Index, triangle.VertexIndex1);

                        //  Add vertex2 to vertex buffer
                        AddVertexToBuffer(materialHelper, ref vertex2, matDef.Index, triangle.VertexIndex2);

                        MyVoxelCacheCellRenderHelper.CreateArrayIfNotExist(matDef.Index);

                        //  Add indices
                        int nextTriangleIndex = materialHelper.IndexCount;
                        materialHelper.Indices[nextTriangleIndex + 0] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex0].VertexIndex;
                        materialHelper.Indices[nextTriangleIndex + 1] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex1].VertexIndex;
                        materialHelper.Indices[nextTriangleIndex + 2] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matDef.Index][triangle.VertexIndex2].VertexIndex;
                        materialHelper.IndexCount += 3;

                        if ((materialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP) ||
                            (materialHelper.IndexCount >= MyVoxelCacheCellRenderHelper.MAX_INDICES_COUNT_STOP))
                        {
                            //  If this batch is almost full (or is full), we end it and start with new one
                            EndSingleMaterial(materialHelper);
                        }
                    }
                    else
                    {
                        int id = GetMultimaterialId(vertex0.Material, vertex1.Material, vertex2.Material);
                        // Assign current material
                        MyMultiMaterialHelper multiMaterialHelper = MyVoxelCacheCellRenderHelper.GetForMultimaterial(vertex0.Material, vertex1.Material, vertex2.Material);

                        // Copy packed normals
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 0].Normal = vertex0.Normal;
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 1].Normal = vertex0.Normal;
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 2].Normal = vertex0.Normal;

                        multiMaterialHelper.AddVertex(ref vertex0);
                        multiMaterialHelper.AddVertex(ref vertex1);
                        multiMaterialHelper.AddVertex(ref vertex2);

                        if (multiMaterialHelper.VertexCount >= MyVoxelCacheCellRenderHelper.MAX_VERTICES_COUNT_STOP)
                        {
                            EndMultiMaterial(multiMaterialHelper);
                        }
                    }
                }
            }
        }