public override void Close() { base.Close(); Metadata = new MyClipmapCellMeshMetadata(); Batches.Clear(); }
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(); }