private void ProcessHighVertex(MyIsoMesh mesh, int vertexIndex, ref MyClipmapCellMeshMetadata meta, out MyVoxelVertex vertex) { vertex = new MyVoxelVertex(); vertex.Position = mesh.Positions[vertexIndex]; vertex.Normal = mesh.Normals[vertexIndex]; vertex.Material = mesh.Materials[vertexIndex]; vertex.Ambient = mesh.Ambient[vertexIndex]; vertex.Cell = mesh.Cells[vertexIndex]; vertex.PositionMorph = vertex.Position; vertex.NormalMorph = vertex.Normal; vertex.MaterialMorph = vertex.Material; vertex.AmbientMorph = vertex.Ambient; //Vertex morph; //Vector3I lowerLodCell = (mesh.Cells[vertexIndex]) >> 1; //if (m_morphMap.TryGetValue(lowerLodCell, out morph)) //{ // vertex.PositionMorph = morph.Target.Position; // vertex.NormalMorph = morph.Target.Normal; // vertex.MaterialMorph = morph.Target.Material; // vertex.AmbientMorph = morph.Target.Ambient; //} //else //{ //} //if (m_lowVertices.Count > 0) //{ // float closestDistance = float.MaxValue; // int closestLowVertex = -1; // for (int i = 0; i < m_lowVertices.Count; i++) // { // float dist = Vector3.DistanceSquared(vertex.Position, m_lowVertices[i].Target.Position); // if (dist < closestDistance) // { // closestDistance = dist; // closestLowVertex = i; // } // } // vertex.PositionMorph = m_lowVertices[closestLowVertex].Target.Position; // vertex.NormalMorph = m_lowVertices[closestLowVertex].Target.Normal; // vertex.MaterialMorph = m_lowVertices[closestLowVertex].Target.Material; // vertex.AmbientMorph = m_lowVertices[closestLowVertex].Target.Ambient; // m_lowToHighMapping[closestLowVertex].Add(vertexIndex); // m_highToLowMapping.Add(closestLowVertex); //} m_highVertices.Add(vertex); }
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 static void UpdateClipmapCell( uint clipmapId, ref MyClipmapCellMeshMetadata metadata, ref List<MyClipmapCellBatch> batches) { var message = MessagePool.Get<MyRenderMessageUpdateClipmapCell>(MyRenderMessageEnum.UpdateClipmapCell); Debug.Assert(message.Batches.Count == 0, "Message was not properly cleared"); message.ClipmapId = clipmapId; message.Metadata = metadata; MyUtils.Swap(ref message.Batches, ref batches); EnqueueMessage(message); }
internal void BuildCell( MyPrecalcJobRender.Args args, MyIsoMesh highResMesh, MyIsoMesh lowResMesh, List <MyClipmapCellBatch> outBatches, out MyClipmapCellMeshMetadata meta) { Debug.Assert(highResMesh != null); meta.Cell = args.Cell; meta.PositionOffset = highResMesh.PositionOffset; meta.PositionScale = highResMesh.PositionScale; meta.LocalAabb = BoundingBox.CreateInvalid(); m_lowVertices.Clear(); m_highVertices.Clear(); m_lowToHighMapping.Clear(); m_highToLowMapping.Clear(); m_highTriangles.Clear(); 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.TrianglesCount; i++) //{ // var v0 = highResMesh.Triangles[i].VertexIndex0; // var v1 = highResMesh.Triangles[i].VertexIndex1; // var v2 = highResMesh.Triangles[i].VertexIndex2; // MyVoxelVertex vertex; // ProcessHighVertex(highResMesh, v0, ref meta, out vertex); // ProcessHighVertex(highResMesh, v1, ref meta, out vertex); // ProcessHighVertex(highResMesh, v2, ref meta, out vertex); // m_highTriangles.Add(new MyVoxelTriangle() // { // VertexIndex0 = (ushort)(i * 3), // VertexIndex1 = (ushort)(i * 3 + 1), // VertexIndex2 = (ushort)(i * 3 + 2), // }); //} for (int i = 0; i < highResMesh.TrianglesCount; i++) { m_highTriangles.Add(highResMesh.Triangles[i]); } for (int i = 0; i < highResMesh.VerticesCount; i++) { MyVoxelVertex vertex; ProcessHighVertex(highResMesh, i, ref meta, out vertex); } if (lowResMesh != null) { //Closest vertex 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 vtx = m_highVertices[i]; vtx.PositionMorph = m_lowVertices[bestV].Target.Position; vtx.Normal = m_lowVertices[bestV].Target.Normal; vtx.Material = m_lowVertices[bestV].Target.Material; vtx.Ambient = m_lowVertices[bestV].Target.Ambient; m_highVertices[i] = vtx; } //// //HashSet<int> alreadySetHighTris = new HashSet<int>(); ////all low tris must have at least one tri from high set, otherwise holes appear. //for (int l = 0; l < lowResMesh.TrianglesCount; l++) //{ // float triDist = float.MaxValue; // int bestT = -1; // for (int i = 0; i < m_highTriangles.Count; i++) // { // if (alreadySetHighTris.Contains(i)) // continue; // float dist = 0; // dist += Vector3.DistanceSquared(m_highVertices[m_highTriangles[i].VertexIndex0].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Position); // dist += Vector3.DistanceSquared(m_highVertices[m_highTriangles[i].VertexIndex1].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Position); // dist += Vector3.DistanceSquared(m_highVertices[m_highTriangles[i].VertexIndex2].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Position); // if (dist < triDist) // { // triDist = dist; // bestT = i; // } // } // if (bestT == -1) // { // //Happens when LOD0 has less tris than LOD1 // bestT = 0; // } // alreadySetHighTris.Add(bestT); // var v0 = m_highVertices[m_highTriangles[bestT].VertexIndex0]; // v0.PositionMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Position; // v0.NormalMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Normal; // v0.AmbientMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Ambient; // m_highVertices[m_highTriangles[bestT].VertexIndex0] = v0; // var v1 = m_highVertices[m_highTriangles[bestT].VertexIndex1]; // v1.PositionMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Position; // v1.NormalMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Normal; // v1.AmbientMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Ambient; // m_highVertices[m_highTriangles[bestT].VertexIndex1] = v1; // var v2 = m_highVertices[m_highTriangles[bestT].VertexIndex2]; // v2.PositionMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Position; // v2.NormalMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Normal; // v2.AmbientMorph = m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Ambient; // m_highVertices[m_highTriangles[bestT].VertexIndex2] = v2; //} //List<MyVoxelTriangle> restHighTriangles = new List<MyVoxelTriangle>(m_highTriangles); //List<int> toRemove = new List<int>(); //foreach (var i in alreadySetHighTris) //{ // toRemove.Add(i); //} //toRemove.Sort(); //for (int i = toRemove.Count - 1; i >= 0; i--) //{ // restHighTriangles.RemoveAt(toRemove[i]); //} //for (int i = 0; i < restHighTriangles.Count; i++) //{ // float triDist = float.MaxValue; // int bestT = -1; // int swtch = 0; // for (int l = 0; l < lowResMesh.TrianglesCount; l++) // { // float dist = 0; // dist += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex0].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Position); // dist += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex1].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Position); // dist += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex2].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Position); // float dist1 = 0; // dist1 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex0].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Position); // dist1 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex1].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Position); // dist1 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex2].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Position); // float dist2 = 0; // dist2 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex0].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex2].Target.Position); // dist2 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex1].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex0].Target.Position); // dist2 += Vector3.DistanceSquared(m_highVertices[restHighTriangles[i].VertexIndex2].Position, m_lowVertices[lowResMesh.Triangles[l].VertexIndex1].Target.Position); // int sw = 0; // if (dist1 < dist && dist1 < dist2) // { // dist = dist1; // sw = 1; // } // if (dist2 < dist && dist2 < dist1) // { // dist = dist2; // sw = 2; // } // if (dist < triDist) // { // triDist = dist; // bestT = l; // swtch = sw; // } // } // //bestT = i % lowResMesh.TrianglesCount; // //bestT = MyUtils.GetRandomInt(lowResMesh.TrianglesCount); // int vi0 = lowResMesh.Triangles[bestT].VertexIndex0; // int vi1 = lowResMesh.Triangles[bestT].VertexIndex1; // int vi2 = lowResMesh.Triangles[bestT].VertexIndex2; // if (swtch == 1) // { // vi0 = lowResMesh.Triangles[bestT].VertexIndex1; // vi1 = lowResMesh.Triangles[bestT].VertexIndex2; // vi2 = lowResMesh.Triangles[bestT].VertexIndex0; // } // if (swtch == 2) // { // vi0 = lowResMesh.Triangles[bestT].VertexIndex2; // vi1 = lowResMesh.Triangles[bestT].VertexIndex0; // vi2 = lowResMesh.Triangles[bestT].VertexIndex1; // } // var v0 = m_highVertices[restHighTriangles[i].VertexIndex0]; // v0.PositionMorph = m_lowVertices[vi0].Target.Position; // v0.NormalMorph = m_lowVertices[vi0].Target.Normal; // v0.AmbientMorph = m_lowVertices[vi0].Target.Ambient; // m_highVertices[restHighTriangles[i].VertexIndex0] = v0; // var v1 = m_highVertices[restHighTriangles[i].VertexIndex1]; // v1.PositionMorph = m_lowVertices[vi1].Target.Position; // v1.NormalMorph = m_lowVertices[vi1].Target.Normal; // v1.AmbientMorph = m_lowVertices[vi1].Target.Ambient; // m_highVertices[restHighTriangles[i].VertexIndex1] = v1; // var v2 = m_highVertices[restHighTriangles[i].VertexIndex2]; // v2.PositionMorph = m_lowVertices[vi2].Target.Position; // v2.NormalMorph = m_lowVertices[vi2].Target.Normal; // v2.AmbientMorph = m_lowVertices[vi2].Target.Ambient; // m_highVertices[restHighTriangles[i].VertexIndex2] = v2; //} ////add low lod //for (int i = 0; i < lowResMesh.TrianglesCount; i++) //{ // var lt = lowResMesh.Triangles[i]; // m_highTriangles.Add(new MyVoxelTriangle() // { // VertexIndex0 = (ushort)(lt.VertexIndex0 + m_highVertices.Count), // VertexIndex1 = (ushort)(lt.VertexIndex1 + m_highVertices.Count), // VertexIndex2 = (ushort)(lt.VertexIndex2 + m_highVertices.Count), // } // ); //} //for (int i = 0; i < m_lowVertices.Count; i++) //{ // var vertex = new MyVoxelVertex(); // vertex.Position = m_lowVertices[i].Target.Position; // vertex.Normal = m_lowVertices[i].Target.Normal; // vertex.Material = m_lowVertices[i].Target.Material; // vertex.Ambient = 0; // vertex.PositionMorph = vertex.Position; // vertex.NormalMorph = vertex.Normal; // vertex.MaterialMorph = vertex.Material; // vertex.AmbientMorph = vertex.Ambient; // m_highVertices.Add(vertex); //} // List<MyVoxelTriangle> newTriangles = new List<MyVoxelTriangle>(); // for (int i = 0; i < m_highTriangles.Count; i++) // { // MyVoxelVertex v0 = m_highVertices[m_highTriangles[i].VertexIndex0]; // MyVoxelVertex v1 = m_highVertices[m_highTriangles[i].VertexIndex1]; // MyVoxelVertex v2 = m_highVertices[m_highTriangles[i].VertexIndex2]; // for (int v = 0; v < m_highVertices.Count; v++) // { // if (v0.Position == m_highVertices[v].Position) // { // if (v0.PositionMorph == m_highVertices[v].PositionMorph) // { // var t = m_highTriangles[i]; // t.VertexIndex0 = (ushort)v; // m_highTriangles[i] = t; // break; // } // else // { // var vert1 = m_highVertices[m_highTriangles[i].VertexIndex1]; // var vert2 = m_highVertices[m_highTriangles[i].VertexIndex2]; // vert1.Position = m_highVertices[v].Position; // vert2.Position = m_highVertices[v].Position; // m_highVertices.Add(vert1); // m_highVertices.Add(vert2); // newTriangles.Add(new MyVoxelTriangle() // { // VertexIndex0 = (ushort)v, // VertexIndex1 = (ushort)(m_highVertices.Count - 2), // VertexIndex2 = (ushort)(m_highVertices.Count - 1) // }); // } // } // } // for (int v = 0; v < m_highVertices.Count; v++) // { // if (v1.Position == m_highVertices[v].Position) // { // if (v1.PositionMorph == m_highVertices[v].PositionMorph) // { // var t = m_highTriangles[i]; // t.VertexIndex1 = (ushort)v; // m_highTriangles[i] = t; // break; // } // else // { // var vert0 = m_highVertices[m_highTriangles[i].VertexIndex0]; // var vert2 = m_highVertices[m_highTriangles[i].VertexIndex2]; // vert0.Position = m_highVertices[v].Position; // vert2.Position = m_highVertices[v].Position; // m_highVertices.Add(vert0); // m_highVertices.Add(vert2); // newTriangles.Add(new MyVoxelTriangle() // { // VertexIndex0 = (ushort)(m_highVertices.Count - 2), // VertexIndex1 = (ushort)v, // VertexIndex2 = (ushort)(m_highVertices.Count - 1) // }); // } // } // } // for (int v = 0; v < m_highVertices.Count; v++) // { // if (v2.Position == m_highVertices[v].Position) // { // if (v2.PositionMorph == m_highVertices[v].PositionMorph) // { // var t = m_highTriangles[i]; // t.VertexIndex2 = (ushort)v; // m_highTriangles[i] = t; // break; // } // else // { // var vert0 = m_highVertices[m_highTriangles[i].VertexIndex0]; // var vert1 = m_highVertices[m_highTriangles[i].VertexIndex1]; // vert0.Position = m_highVertices[v].Position; // vert1.Position = m_highVertices[v].Position; // m_highVertices.Add(vert0); // m_highVertices.Add(vert1); // newTriangles.Add(new MyVoxelTriangle() // { // VertexIndex0 = (ushort)(m_highVertices.Count - 2), // VertexIndex1 = (ushort)(m_highVertices.Count - 1), // VertexIndex2 = (ushort)v // }); // } // } // } // } // foreach (var t in newTriangles) // { // m_highTriangles.Add(t); // } float largestDistance = float.MinValue; for (int i = 0; i < m_highVertices.Count; i++) { MyVoxelVertex vertex = m_highVertices[i]; float p1 = vertex.Position.AbsMax(); if (p1 > largestDistance) { largestDistance = p1; } float p2 = vertex.PositionMorph.AbsMax(); if (p2 > largestDistance) { largestDistance = p2; } } 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; } else { } 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 < m_highTriangles.Count; i++) { MyVoxelTriangle srcTriangle = m_highTriangles[i]; MyVoxelVertex vertex0, vertex1, vertex2; vertex0 = m_highVertices[srcTriangle.VertexIndex0]; vertex1 = m_highVertices[srcTriangle.VertexIndex1]; 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); var voxelMaterialCount = MyDefinitionManager.Static.VoxelMaterialCount; int id = materials.X + voxelMaterialCount * (materials.Y + materials.Z * voxelMaterialCount); // 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(); }
public static void UpdateMergedVoxelMesh(uint clipmapId, int lod, ulong workId, MyClipmapCellMeshMetadata metaData, List<MyClipmapCellBatch> mergedBatches) { var message = MessagePool.Get<MyRenderMessageUpdateMergedVoxelMesh>(MyRenderMessageEnum.UpdateMergedVoxelMesh); Debug.Assert(message.MergedBatches.Count == 0, "Message was not properly cleared"); message.ClipmapId = clipmapId; message.Lod = lod; message.WorkId = workId; message.Metadata = metaData; message.MergedBatches.AddList(mergedBatches); EnqueueMessage(message); }