private static void AddVertexToBuffer(MySingleMaterialHelper materialHelper, ref MyVoxelVertex vertex0,
                                              int matIndex, short vertexIndex0)
        {
            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].m_positionAndAmbient = vertex0.m_positionAndAmbient;
                materialHelper.Vertices[nextVertexIndex].Ambient = vertex0.Ambient;

                // Copy normal
#if PACKED_VERTEX_FORMAT
                materialHelper.Vertices[nextVertexIndex].m_normal = vertex0.m_normal;
#else
                materialHelper.Vertices[nextVertexIndex].Normal = vertex0.Normal;
#endif

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

                materialHelper.VertexCount++;
            }
        }
        public static MySingleMaterialHelper GetForMaterial(MyMwcVoxelMaterialsEnum material)
        {
            if (m_preallocatedSingleMaterialHelpers[(int)material] == null)
            {
                m_preallocatedSingleMaterialHelpers[(int)material] = new MySingleMaterialHelper();
                m_preallocatedSingleMaterialHelpers[(int)material].LoadData();
                m_preallocatedSingleMaterialHelpers[(int)material].SetMaterial(material);
            }

            return(m_preallocatedSingleMaterialHelpers[(int)material]);
            //m_singleMaterialHelper.SetMaterial(material);
            //return m_singleMaterialHelper;
        }
        void EndSingleMaterial(MySingleMaterialHelper materialHelper)
        {
            if (materialHelper.IndexCount > 0 && materialHelper.VertexCount > 0)
            {
                //  This will just preload textures used by this material - so they are ready in memory when first time drawn
                MyVoxelMaterials.Get(materialHelper.Material).GetTextures();

                MyVoxelCacheCellRenderBatch newBatch = new MyVoxelCacheCellRenderBatch();
                //  Vertex buffer
                newBatch.VertexBufferCount = materialHelper.VertexCount;
                newBatch.VertexBuffer      = new VertexBuffer(MyMinerGame.Static.GraphicsDevice, MyVertexFormatVoxelSingleMaterial.Stride * newBatch.VertexBufferCount, Usage.WriteOnly, VertexFormat.None, Pool.Default);
                newBatch.VertexBuffer.Lock(0, 0, LockFlags.None).WriteRange(materialHelper.Vertices, 0, newBatch.VertexBufferCount);
                newBatch.VertexBuffer.Unlock();
                newBatch.VertexBuffer.Tag       = newBatch;
                newBatch.VertexBuffer.DebugName = "VoxelBatchSingle";
                newBatch.VertexBufferSize       = materialHelper.VertexCount * MyVertexFormatVoxelSingleMaterial.Stride;
                MyPerformanceCounter.PerAppLifetime.VoxelVertexBuffersSize += newBatch.VertexBufferSize;

                //  Index buffer
                newBatch.IndexBufferCount = materialHelper.IndexCount;
                newBatch.IndexBuffer      = new IndexBuffer(MyMinerGame.Static.GraphicsDevice, newBatch.IndexBufferCount * sizeof(short), Usage.WriteOnly, Pool.Default, true);
                newBatch.IndexBuffer.Lock(0, 0, LockFlags.None).WriteRange(materialHelper.Indices, 0, newBatch.IndexBufferCount);
                newBatch.IndexBuffer.Unlock();
                newBatch.IndexBuffer.DebugName = "VoxelBatchSingle";
                newBatch.IndexBufferSize       = materialHelper.IndexCount * sizeof(short);
                MyPerformanceCounter.PerAppLifetime.VoxelIndexBuffersSize += newBatch.IndexBufferSize;

                newBatch.Type      = MyVoxelCacheCellRenderBatchType.SINGLE_MATERIAL;
                newBatch.Material0 = materialHelper.Material;
                newBatch.Material1 = null;
                newBatch.Material2 = null;
                newBatch.UpdateSortOrder();

                Batches.Add(newBatch);
            }
            //  Reset helper arrays, so we can start adding triangles to them again
            materialHelper.IndexCount  = 0;
            materialHelper.VertexCount = 0;
            MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookupCount[(int)materialHelper.Material]++;
        }
        //  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 <MyVoxelCacheCellData> cacheDataArray)
        {
            //     MyPerformanceTimer.VoxelGpuBuffersBuild.Start();


            //MyMwcVoxelMaterialsEnum? CurrentSingleMaterial = null;
            //            bool triangleAdded = true;

            // while (triangleAdded)
            //  {
            //   triangleAdded = false;
            //CurrentSingleMaterial = null;


            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  = cacheData.VoxelVertices[triangle.VertexIndex0];
                    MyVoxelVertex   vertex1  = cacheData.VoxelVertices[triangle.VertexIndex1];
                    MyVoxelVertex   vertex2  = cacheData.VoxelVertices[triangle.VertexIndex2];

                    if ((vertex0.Material == vertex1.Material) && (vertex0.Material == vertex2.Material))
                    {
                        int matIndex = (int)vertex0.Material;

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

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

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

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

                        //triangleAdded = true;

                        //  Add indices
                        int nextTriangleIndex = materialHelper.IndexCount;
                        materialHelper.Indices[nextTriangleIndex + 0] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][triangle.VertexIndex0].VertexIndex;
                        materialHelper.Indices[nextTriangleIndex + 1] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][triangle.VertexIndex1].VertexIndex;
                        materialHelper.Indices[nextTriangleIndex + 2] = MyVoxelCacheCellRenderHelper.SingleMaterialIndicesLookup[matIndex][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);

                        //triangleAdded = true;

#if PACKED_VERTEX_FORMAT
                        // Copy packed normals
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 0].PackedNormal = vertex0.PackedNormal;
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 1].PackedNormal = vertex0.PackedNormal;
                        multiMaterialHelper.Vertices[multiMaterialHelper.VertexCount + 2].PackedNormal = vertex0.PackedNormal;
#endif

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

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

                /*
                 * if (multiMaterialHelper != null)
                 * {
                 * int id = GetMultimaterialId(multiMaterialHelper.Material0, multiMaterialHelper.Material1, multiMaterialHelper.Material2);
                 * MyVoxelCacheCellRenderHelper.FinishedMultiMaterials[id] = true;
                 * EndMultimaterial(multiMaterialHelper);
                 * }
                 *
                 * if (singleMaterialHelper != null)
                 * {
                 * MyVoxelCacheCellRenderHelper.FinishedSingleMaterials[(int)singleMaterialHelper.Material] = true;
                 * EndSingleMaterial(singleMaterialHelper);
                 * }      */
            }


            //    }
            //MyPerformanceTimer.VoxelGpuBuffersBuild.End();
        }
        public static MySingleMaterialHelper GetForMaterial(MyMwcVoxelMaterialsEnum material)
        {
            if (m_preallocatedSingleMaterialHelpers[(int)material] == null)
            {
                m_preallocatedSingleMaterialHelpers[(int)material] = new MySingleMaterialHelper();
                m_preallocatedSingleMaterialHelpers[(int)material].LoadData();
                m_preallocatedSingleMaterialHelpers[(int)material].SetMaterial(material);
            }

            return m_preallocatedSingleMaterialHelpers[(int)material];
            //m_singleMaterialHelper.SetMaterial(material);
            //return m_singleMaterialHelper;
        }