public override void Close()
 {
     base.Close();
     Metadata = new MyClipmapCellMeshMetadata();
     Batches.Clear();
 }
Ejemplo n.º 2
0
        internal void BuildCell(
            MyPrecalcJobRender.Args args,
            MyIsoMesh highResMesh,
            MyIsoMesh lowResMesh,
            List<MyClipmapCellBatch> outBatches,
            out MyClipmapCellMeshMetadata meta)
        {
            ProfilerShort.Begin("MyRenderCellBuilder.BuildCell");
            Debug.Assert(highResMesh != null);

            meta.Cell = args.Cell;
            meta.PositionOffset = highResMesh.PositionOffset;
            meta.PositionScale = highResMesh.PositionScale;
            meta.LocalAabb = BoundingBox.CreateInvalid();

            m_lowVertices.SetSize(0);
            m_highVertices.SetSize(0);

            ProcessLowMesh(highResMesh, lowResMesh);

            //  Increase lookup count, so we will think that all vertices in helper arrays are new
            foreach (var lookup in SM_BatchLookups.Values)
            {
                lookup.ResetBatch();
            }

    
            for (int i = 0; i < highResMesh.VerticesCount; i++)
            {
                MyVoxelVertex vertex;
                ProcessHighVertex(highResMesh, i, out vertex);
            }

            if (lowResMesh != null)
            {
                m_highGrid.ClearFast();

                for (int i = 0; i < m_highVertices.Count; i++)
                {
                    Vector3 position = m_highVertices[i].Position;
                    m_highGrid.AddPoint(ref position, i);
                }

                //TODO: Fix ocassional bad triangles on asteroid
                /*
                //Closest vertex
                for (int l = 0; l < m_lowVertices.Count; l++)
                {
                    Vector3 targetPosition = m_lowVertices[l].Target.Position;

                    int bestV = -1;
                    float ldist = float.MaxValue;
                    float startMeters = 1;
                    float maxDistance = 10;

                    MyVector3Grid<int>.Enumerator points = default(MyVector3Grid<int>.Enumerator);
                    while (startMeters < maxDistance)
                    {
                        points = m_highGrid.GetPointsCloserThan(ref targetPosition, startMeters);

                        while (points.MoveNext())
                        {
                            var dist = Vector3.DistanceSquared(targetPosition, m_highVertices[points.Current].Position);
                            if (dist < ldist)
                            {
                                ldist = dist;
                                bestV = points.Current;
                            }
                        }

                        if (bestV != -1)
                            break;

                        startMeters += 1;
                    }

                    if (bestV != -1)
                    {
                        var vtx = m_highVertices[bestV];
                        vtx.PositionMorph = m_lowVertices[l].Target.Position;
                        vtx.NormalMorph = m_lowVertices[l].Target.Normal;
                        vtx.MaterialMorph = m_lowVertices[l].Target.Material;
                        vtx.AmbientMorph = m_lowVertices[l].Target.Ambient;
                        m_highVertices[bestV] = vtx;
                    }
                    else
                    {
                    }
                }

                */

                //Closest vertex
                float largestDistance = float.MinValue;
                for (int i = 0; i < m_highVertices.Count; i++)
                {
                    float ldist = float.MaxValue;
                    int bestV = -1;

                    for (int l = 0; l < m_lowVertices.Count; l++)
                    {
                        var dist = Vector3.DistanceSquared(m_lowVertices[l].Target.Position, m_highVertices[i].Position);
                        if (dist < ldist)
                        {
                            ldist = dist;
                            bestV = l;
                        }
                    }

                    var highVertex = m_highVertices[i];
                    highVertex.PositionMorph = m_lowVertices[bestV].Target.Position;
                    highVertex.NormalMorph = m_lowVertices[bestV].Target.Normal;
                    highVertex.MaterialMorph = m_lowVertices[bestV].Target.Material;
                    highVertex.AmbientMorph = m_lowVertices[bestV].Target.Ambient;

                    float p1 = highVertex.Position.AbsMax();
                    if (p1 > largestDistance)
                        largestDistance = p1;
                    float p2 = highVertex.PositionMorph.AbsMax();
                    if (p2 > largestDistance)
                        largestDistance = p2;

                    m_highVertices[i] = highVertex;
                }

                for (int i = 0; i < m_highVertices.Count; i++)
                {
                    MyVoxelVertex vertex = m_highVertices[i];

                    vertex.Position /= largestDistance;
                    vertex.PositionMorph /= largestDistance;

                    m_highVertices[i] = vertex;
                }

                meta.PositionScale *= largestDistance;
            }
            
            //Create batches
            for (int i = 0; i < m_highVertices.Count; i++)
            {
                MyVoxelVertex vertex = m_highVertices[i];

                meta.LocalAabb.Include(vertex.Position * meta.PositionScale + meta.PositionOffset);
                meta.LocalAabb.Include(vertex.PositionMorph * meta.PositionScale + meta.PositionOffset);

                Debug.Assert(vertex.Position.IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One));
                Debug.Assert(vertex.PositionMorph.IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One));
            }

            for (int i = 0; i < highResMesh.TrianglesCount; i++)
            {
                MyVoxelTriangle srcTriangle = highResMesh.Triangles[i];
                MyVoxelVertex vertex0 = m_highVertices[srcTriangle.VertexIndex0];
                MyVoxelVertex vertex1 = m_highVertices[srcTriangle.VertexIndex1];
                MyVoxelVertex vertex2 = m_highVertices[srcTriangle.VertexIndex2];
                
                if (vertex0.Material == vertex1.Material &&
                    vertex0.Material == vertex2.Material &&
                    vertex0.Material == vertex0.MaterialMorph &&
                    vertex0.Material == vertex1.MaterialMorph &&
                    vertex0.Material == vertex2.MaterialMorph)
                { // single material
                    var matIdx = vertex0.Material;

                    //  This is single-texture triangleVertexes, so we can choose material from any edge
                    SingleMaterialHelper materialHelper;
                    if (!SM_Helpers.TryGetValue(matIdx, out materialHelper))
                    {
                        if (!SM_HelperPool.TryDequeue(out materialHelper))
                            materialHelper = new SingleMaterialHelper();
                        materialHelper.Material = matIdx;
                        SM_Helpers.Add(matIdx, materialHelper);
                    }

                    VertexInBatchLookup batchLookup;
                    if (!SM_BatchLookups.TryGetValue(matIdx, out batchLookup))
                    {
                        if (!SM_BatchLookupPool.TryDequeue(out batchLookup))
                            batchLookup = new VertexInBatchLookup();
                        SM_BatchLookups.Add(matIdx, batchLookup);
                    }

                    AddVertexToBuffer(materialHelper, ref vertex0, batchLookup, srcTriangle.VertexIndex0);
                    AddVertexToBuffer(materialHelper, ref vertex1, batchLookup, srcTriangle.VertexIndex1);
                    AddVertexToBuffer(materialHelper, ref vertex2, batchLookup, srcTriangle.VertexIndex2);

                    //  Add indices
                    int nextTriangleIndex = materialHelper.IndexCount;
                    materialHelper.Indices[nextTriangleIndex + 0] = batchLookup.GetIndexInBatch(srcTriangle.VertexIndex0);
                    materialHelper.Indices[nextTriangleIndex + 1] = batchLookup.GetIndexInBatch(srcTriangle.VertexIndex1);
                    materialHelper.Indices[nextTriangleIndex + 2] = batchLookup.GetIndexInBatch(srcTriangle.VertexIndex2);
                    materialHelper.IndexCount += 3;

                    if ((materialHelper.VertexCount >= MAX_VERTICES_COUNT_STOP) ||
                        (materialHelper.IndexCount >= MAX_INDICES_COUNT_STOP))
                    {
                        //  If this batch is almost full (or is full), we end it and start with new one
                        EndSingleMaterial(materialHelper, outBatches);
                    }
                }
                else
                {
                    Vector3I materials = GetMaterials(ref vertex0, ref vertex1, ref vertex2);
                    Debug.Assert(materials.X < 1 << 10, "Too many materials");
                    Debug.Assert(materials.Y < 1 << 10, "Too many materials");
                    Debug.Assert(materials.Z < 1 << 10, "Too many materials");
                    int id = materials.X + (materials.Y + (materials.Z << 10) << 10);

                    // Assign current material
                    MultiMaterialHelper helper = null;
                    if (!MM_Helpers.TryGetValue(id, out helper))
                    {
                        if (!MM_HelperPool.TryDequeue(out helper))
                            helper = new MultiMaterialHelper();
                        helper.Material0 = materials.X;
                        helper.Material1 = materials.Y;
                        helper.Material2 = materials.Z;
                        MM_Helpers.Add(id, helper);
                    }

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

                    if (helper.Vertices.Count >= MAX_VERTICES_COUNT_STOP)
                    {
                        EndMultiMaterial(helper, outBatches);
                    }
                }
            }

            { //renderCell.End();
                foreach (var helper in SM_Helpers.Values)
                {
                    Debug.Assert(helper != null);
                    if (helper.IndexCount > 0)
                    {
                        EndSingleMaterial(helper, outBatches);
                    }
                    helper.IndexCount = 0;
                    helper.VertexCount = 0;
                    SM_HelperPool.Enqueue(helper);
                }
                SM_Helpers.Clear();

                foreach (var helper in MM_Helpers.Values)
                {
                    if (helper.Vertices.Count > 0)
                    {
                        EndMultiMaterial(helper, outBatches);
                    }
                    helper.Vertices.Clear();
                    MM_HelperPool.Enqueue(helper);
                }
                MM_Helpers.Clear();

                foreach (var lookup in SM_BatchLookups.Values)
                {
                    SM_BatchLookupPool.Enqueue(lookup);
                }
                SM_BatchLookups.Clear();
            }

            m_morphMap.Clear();
            meta.BatchCount = outBatches.Count;
            ProfilerShort.End();
        }
 public override void Close()
 {
     base.Close();
     Metadata = new MyClipmapCellMeshMetadata();
     Batches.Clear();
 }