void EndMultiMaterial(MyMultiMaterialHelper helper)
        {
            if (helper.VertexCount > 0)
            {
                //Todo - is it possible without allocations?
                MyVertexFormatVoxelSingleData[] vertices = new MyVertexFormatVoxelSingleData[helper.VertexCount];
                Array.Copy(helper.Vertices, vertices, vertices.Length);

                short[] indices = new short[helper.VertexCount];
                for (short i = 0; i < indices.Length; i++)
                {
                    indices[i] = i;
                }

                VRageRender.MyRenderProxy.UpdateRenderVoxelCell(
                    VoxelMap.GetRenderObjectID(ref this.CellCoord),
                    (VRageRender.MyLodTypeEnum)(int) CellHashType,
                    vertices,
                    indices,
                    (int)helper.Material0.Index,
                    (int)helper.Material1.Index,
                    (int)helper.Material2.Index);
            }

            //  Reset helper arrays, so we can start adding triangles to them again
            helper.VertexCount = 0;
        }
        public static MyMultiMaterialHelper GetForMultimaterial(int material0, int material1, int material2)
        {
            int id = MyVoxelCacheCellRender.GetMultimaterialId(material0, material1, material2);
            MyMultiMaterialHelper helper = null;

            m_preallocatedMultiMaterialHelpers.TryGetValue(id, out helper);
            if (helper == null)
            {
                helper = new MyMultiMaterialHelper();
                helper.LoadData();
                helper.SetMaterials(MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material0),
                                    MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material1),
                                    MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material2));
                m_preallocatedMultiMaterialHelpers.Add(id, helper);
            }
            return(helper);

            //m_multiMaterialHelper.SetMaterials(material0, material1, material2);
            //return m_multiMaterialHelper;
        }
        void EndMultiMaterial(MyMultiMaterialHelper helper)
        {
            if (helper.VertexCount > 0)
            {
                //Todo - is it possible without allocations?
                MyVertexFormatVoxelSingleData[] vertices = new MyVertexFormatVoxelSingleData[helper.VertexCount];
                Array.Copy(helper.Vertices, vertices, vertices.Length);

                short[] indices = new short[helper.VertexCount];
                for (short i = 0; i < indices.Length; i++)
                {
                    indices[i] = i;
                }

                VRageRender.MyRenderProxy.UpdateRenderVoxelCell(
                    VoxelMap.GetRenderObjectID(ref this.CellCoord),
                    (VRageRender.MyLodTypeEnum)(int)CellHashType,
                    vertices,
                    indices,
                    (int)helper.Material0.Index,
                    (int)helper.Material1.Index,
                    (int)helper.Material2.Index);
            }

            //  Reset helper arrays, so we can start adding triangles to them again
            helper.VertexCount = 0;
        }
        public static MyMultiMaterialHelper GetForMultimaterial(int material0, int material1, int material2)
        {
            int id = MyVoxelCacheCellRender.GetMultimaterialId(material0, material1, material2);
            MyMultiMaterialHelper helper = null;
            m_preallocatedMultiMaterialHelpers.TryGetValue(id, out helper);
            if (helper == null)
            {
                helper = new MyMultiMaterialHelper();
                helper.LoadData();
                helper.SetMaterials(MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material0),
                    MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material1),
                    MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)material2));
                m_preallocatedMultiMaterialHelpers.Add(id, helper);
            }
            return helper;

            //m_multiMaterialHelper.SetMaterials(material0, material1, material2);
            //return m_multiMaterialHelper;
        }
        //  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);
                        }
                    }
                }
            }
        }