//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override void LoadData() { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("MyVoxelCacheRender.LoadData"); MySandboxGame.Log.WriteLine("MyVoxelCacheRender.LoadData() - START"); MySandboxGame.Log.IncreaseIndent(); m_capacity = MyVoxelConstants.RENDER_CELL_CACHE_SIZE; m_cellsByCoordinate = new Dictionary <Int64, LinkedListNode <MyVoxelCacheCellRender> >(m_capacity); m_priority = new LinkedList <MyVoxelCacheCellRender>(); m_priorityArray = new LinkedListNode <MyVoxelCacheCellRender> [m_capacity]; m_cellsPreallocated = new MyVoxelCacheCellRender[m_capacity]; m_helperLodCachedDataCell = new MyVoxelGeometry.CellData(); m_dataCellsQueue = new List <MyVoxelGeometry.CellData>(MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS_TOTAL); for (int i = 0; i < m_capacity; i++) { m_cellsPreallocated[i] = new MyVoxelCacheCellRender(); m_priorityArray[i] = new LinkedListNode <MyVoxelCacheCellRender>(m_cellsPreallocated[i]); m_priority.AddLast(m_priorityArray[i]); } MySandboxGame.Log.DecreaseIndent(); MySandboxGame.Log.WriteLine("MyVoxelCacheRender.LoadData() - END"); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); LoadCache(); }
public MyVoxelPrecalcTaskItem(MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelGeometry.CellData cache, Vector3I voxelStart) { Type = type; VoxelMap = voxelMap; Cache = cache; VoxelStart = voxelStart; }
public static void AddToQueue( MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelGeometry.CellData cache, int voxelStartX, int voxelStartY, int voxelStartZ) { Debug.Assert(Thread.CurrentThread == MySandboxGame.Static.UpdateThread, "Only update thread should queue voxel precalc."); MyVoxelPrecalcTaskItem a = new MyVoxelPrecalcTaskItem(type, voxelMap, cache, new Vector3I(voxelStartX, voxelStartY, voxelStartZ)); Tasks.Enqueue(a); }
protected override void UnloadData() { UnloadCache(); m_cellsPreallocated = null; m_priority = null; m_priorityArray = null; if (m_dataCellsQueue != null) { m_dataCellsQueue.Clear(); } m_helperLodCachedDataCell = null; }
private bool AddCell(Vector3I cellPos) { MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cellPos); var geometry = m_voxelMap.Storage.Geometry; MyVoxelGeometry.CellData data = geometry.GetCell(ref coord); if (data == null) { m_processedCells.Add(ref cellPos); m_higherLevelHelper.AddExplored(ref cellPos); return(false); } ulong packedCoord = coord.PackId64(); List <DebugDrawEdge> debugEdgesList = new List <DebugDrawEdge>(); m_debugCellEdges[packedCoord] = debugEdgesList; MyVoxelPathfinding.CellId cellId = new MyVoxelPathfinding.CellId() { VoxelMap = m_voxelMap, Pos = cellPos }; MyTrace.Send(TraceWindow.Ai, "Adding cell " + cellPos); m_connectionHelper.ClearCell(); m_vertexMapping.Init(data.VoxelVerticesCount); // Prepare list of possibly intersecting cube grids for voxel-grid navmesh intersection testing Vector3D bbMin = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (new Vector3D(-0.125) + cellPos)); Vector3D bbMax = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (Vector3D.One + cellPos)); BoundingBoxD cellBB = new BoundingBoxD(bbMin, bbMax); m_tmpGridList.Clear(); m_navmeshCoordinator.PrepareVoxelTriangleTests(cellBB, m_tmpGridList); Vector3D voxelMapCenter = m_voxelMap.PositionComp.GetPosition(); Vector3 centerDisplacement = voxelMapCenter - m_voxelMap.PositionLeftBottomCorner; // This is needed for correct edge classification - to tell, whether the edges are inner or outer edges of the cell ProfilerShort.Begin("Triangle preprocessing"); for (int i = 0; i < data.VoxelTrianglesCount; i++) { short a = data.VoxelTriangles[i].VertexIndex0; short b = data.VoxelTriangles[i].VertexIndex1; short c = data.VoxelTriangles[i].VertexIndex2; Vector3 aPos, bPos, cPos; Vector3 vert; data.GetUnpackedPosition(a, out vert); aPos = vert - centerDisplacement; data.GetUnpackedPosition(b, out vert); bPos = vert - centerDisplacement; data.GetUnpackedPosition(c, out vert); cPos = vert - centerDisplacement; bool invalidTriangle = false; if ((bPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ) { m_vertexMapping.Union(a, b); invalidTriangle = true; } if ((cPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ) { m_vertexMapping.Union(a, c); invalidTriangle = true; } if ((cPos - bPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ) { m_vertexMapping.Union(b, c); invalidTriangle = true; } if (invalidTriangle) { continue; } m_connectionHelper.PreprocessInnerEdge(a, b); m_connectionHelper.PreprocessInnerEdge(b, c); m_connectionHelper.PreprocessInnerEdge(c, a); } ProfilerShort.End(); ProfilerShort.Begin("Free face sorting"); // Ensure that the faces have increasing index numbers Mesh.SortFreeFaces(); ProfilerShort.End(); m_higherLevelHelper.OpenNewCell(coord); ProfilerShort.Begin("Adding triangles"); for (int i = 0; i < data.VoxelTrianglesCount; i++) { short a = data.VoxelTriangles[i].VertexIndex0; short b = data.VoxelTriangles[i].VertexIndex1; short c = data.VoxelTriangles[i].VertexIndex2; short setA = (short)m_vertexMapping.Find(a); short setB = (short)m_vertexMapping.Find(b); short setC = (short)m_vertexMapping.Find(c); if (setA == setB || setB == setC || setA == setC) { continue; } Vector3 aPos, bPos, cPos; Vector3 vert; data.GetUnpackedPosition(setA, out vert); aPos = vert - centerDisplacement; data.GetUnpackedPosition(setB, out vert); bPos = vert - centerDisplacement; data.GetUnpackedPosition(setC, out vert); cPos = vert - centerDisplacement; if (MyFakes.NAVMESH_PRESUMES_DOWNWARD_GRAVITY) { Vector3 normal = (cPos - aPos).Cross(bPos - aPos); normal.Normalize(); if (normal.Dot(ref Vector3.Up) <= Math.Cos(MathHelper.ToRadians(54.0f))) { continue; } } Vector3D aTformed = aPos + voxelMapCenter; Vector3D bTformed = bPos + voxelMapCenter; Vector3D cTformed = cPos + voxelMapCenter; bool intersecting = false; m_tmpLinkCandidates.Clear(); m_navmeshCoordinator.TestVoxelNavmeshTriangle(ref aTformed, ref bTformed, ref cTformed, m_tmpGridList, m_tmpLinkCandidates, out intersecting); if (intersecting) { m_tmpLinkCandidates.Clear(); continue; } if (!m_connectionHelper.IsInnerEdge(a, b)) { debugEdgesList.Add(new DebugDrawEdge(aTformed, bTformed)); } if (!m_connectionHelper.IsInnerEdge(b, c)) { debugEdgesList.Add(new DebugDrawEdge(bTformed, cTformed)); } if (!m_connectionHelper.IsInnerEdge(c, a)) { debugEdgesList.Add(new DebugDrawEdge(cTformed, aTformed)); } int edgeAB = m_connectionHelper.TryGetAndRemoveEdgeIndex(b, a, ref bPos, ref aPos); int edgeBC = m_connectionHelper.TryGetAndRemoveEdgeIndex(c, b, ref cPos, ref bPos); int edgeCA = m_connectionHelper.TryGetAndRemoveEdgeIndex(a, c, ref aPos, ref cPos); int formerAB = edgeAB; int formerBC = edgeBC; int formerCA = edgeCA; ProfilerShort.Begin("AddTriangle"); var tri = AddTriangle(ref aPos, ref bPos, ref cPos, ref edgeAB, ref edgeBC, ref edgeCA); ProfilerShort.End(); CheckMeshConsistency(); m_higherLevelHelper.AddTriangle(tri.Index); if (formerAB == -1) { m_connectionHelper.AddEdgeIndex(a, b, ref aPos, ref bPos, edgeAB); } if (formerBC == -1) { m_connectionHelper.AddEdgeIndex(b, c, ref bPos, ref cPos, edgeBC); } if (formerCA == -1) { m_connectionHelper.AddEdgeIndex(c, a, ref cPos, ref aPos, edgeCA); } // TODO: Instead of this, just add the tri into a list of tris that want to connect with the link candidates //m_navmeshCoordinator.TryAddVoxelNavmeshLinks(tri, cellId, m_tmpLinkCandidates); foreach (var candidate in m_tmpLinkCandidates) { List <MyNavigationPrimitive> primitives = null; if (!m_tmpCubeLinkCandidates.TryGetValue(candidate, out primitives)) { primitives = m_primitiveListPool.Allocate(); m_tmpCubeLinkCandidates.Add(candidate, primitives); } primitives.Add(tri); } m_tmpLinkCandidates.Clear(); } ProfilerShort.End(); m_tmpGridList.Clear(); m_connectionHelper.ClearCell(); m_vertexMapping.Clear(); Debug.Assert(!m_processedCells.Contains(ref cellPos)); m_processedCells.Add(ref cellPos); m_higherLevelHelper.AddExplored(ref cellPos); // Find connected components in the current cell's subgraph of the navigation mesh m_higherLevelHelper.ProcessCellComponents(); m_higherLevelHelper.CloseCell(); // Create navmesh links using the navmesh coordinator, taking into consideration the high level components m_navmeshCoordinator.TryAddVoxelNavmeshLinks2(cellId, m_tmpCubeLinkCandidates); m_navmeshCoordinator.UpdateVoxelNavmeshCellHighLevelLinks(cellId); foreach (var candidate in m_tmpCubeLinkCandidates) { candidate.Value.Clear(); m_primitiveListPool.Deallocate(candidate.Value); } m_tmpCubeLinkCandidates.Clear(); return(true); }
private static MyVoxelCacheCellRender LoadCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType) { Profiler.Begin("AddCell"); MyVoxelCacheCellRender ret = AddCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType); ret.Begin(voxelMap, ref renderCellCoord); ret.CellHashType = cellHashType; Profiler.End(); if (cellHashType == MyLodTypeEnum.LOD0) { Profiler.Begin("LOD0 - queue cells"); m_dataCellsQueue.Clear(); // Create normal (LOD0) version for (int dataX = 0; dataX < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataX++) { for (int dataY = 0; dataY < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataY++) { for (int dataZ = 0; dataZ < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataZ++) { // Don't precalculate this cells now. Store it in queue and calculate all cells at once by MyVoxelPrecalc.PrecalcQueue() Vector3I dataCellCoord = new Vector3I( renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataX, renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataY, renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataZ); MyVoxelGeometry.CellData cachedDataCell = voxelMap.Geometry.GetCellLater(MyLodTypeEnum.LOD0, ref dataCellCoord); if (cachedDataCell != null) { m_dataCellsQueue.Add(cachedDataCell); } } } } Profiler.BeginNextBlock("LOD0 - PrecalcQueue"); // Precalculate all queued data cells in parallel threads - using multiple cores if possible. MyVoxelPrecalc.PrecalcQueue(); Profiler.BeginNextBlock("LOD0 - AddTriangles"); ret.AddTriangles(m_dataCellsQueue); Profiler.End(); } else if (cellHashType == MyLodTypeEnum.LOD1) { Profiler.Begin("LOD1 - PrecalcImmediatelly"); m_helperLodCachedDataCell.Reset(); // Create LOD1 render cell MyVoxelPrecalc.PrecalcImmediatelly( new MyVoxelPrecalcTaskItem( MyLodTypeEnum.LOD1, voxelMap, m_helperLodCachedDataCell, new Vector3I( renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS, renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS, renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS))); Profiler.BeginNextBlock("LOD1 - AddTriangles"); m_dataCellsQueue.Clear(); m_dataCellsQueue.Add(m_helperLodCachedDataCell); ret.AddTriangles(m_dataCellsQueue); Profiler.End(); } else { throw new InvalidBranchException(); } ret.End(); return(ret); }