public void OpenNewCell(MyCellCoord coord) { this.m_cellOpen = true; this.m_currentCell = coord.CoordInLod; this.m_packedCoord = coord.PackId64(); this.m_triangleList.Clear(); }
internal void InvalidateRange(Vector3I lodMin, Vector3I lodMax) { // MyLog.Default.WriteLine("InvalidateRange Lod: " + m_lodIndex + " Min: " + lodMin + " Max: " + lodMax); var cell = new MyCellCoord(m_lodIndex, lodMin); for (var it = new Vector3I_RangeIterator(ref lodMin, ref lodMax); it.IsValid(); it.GetNext(out cell.CoordInLod)) { MyClipmap_CellData data; var id = cell.PackId64(); // MyLog.Default.WriteLine("Setting to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod); if (m_storedCellData.TryGetValue(id, out data)) { data.State = CellState.Invalid; //MyLog.Default.WriteLine("Really set to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod); } if (MyClipmap.UseCache) { var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, id); var cachedCell = MyClipmap.CellsCache.Read(clipmapCellId); if (cachedCell != null) { cachedCell.State = CellState.Invalid; } } } }
private unsafe void MarkExploredDirections(ref MyNavmeshComponents.ClosedCellInfo cellInfo) { foreach (Base6Directions.Direction direction in Base6Directions.EnumDirections) { Base6Directions.DirectionFlags directionFlag = Base6Directions.GetDirectionFlag(direction); if (!cellInfo.ExploredDirections.HasFlag(directionFlag)) { Vector3I intVector = Base6Directions.GetIntVector(direction); MyCellCoord coord = new MyCellCoord { Lod = 0, CoordInLod = (Vector3I)(this.m_currentCell + intVector) }; if (((coord.CoordInLod.X != -1) && (coord.CoordInLod.Y != -1)) && (coord.CoordInLod.Z != -1)) { ulong key = coord.PackId64(); if (this.m_triangleLists.ContainsKey(key)) { this.m_navmeshComponents.MarkExplored(key, Base6Directions.GetFlippedDirection(direction)); Base6Directions.DirectionFlags *flagsPtr1 = (Base6Directions.DirectionFlags *) ref cellInfo.ExploredDirections; *((sbyte *)flagsPtr1) = *(((byte *)flagsPtr1)) | Base6Directions.GetDirectionFlag(direction); } } } } this.m_navmeshComponents.SetExplored(this.m_packedCoord, cellInfo.ExploredDirections); }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCell, maxCell; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCell); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCell); Vector3I currentCell = minCell; for (var it = new Vector3I.RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out currentCell)) { if (m_processedCells.Contains(ref currentCell)) { RemoveCell(currentCell); } MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, currentCell); m_higherLevelHelper.TryClearCell(coord.PackId64()); } }
private unsafe void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData) { Vector3I voxelCoord = minChanged - MyPrecalcComponent.InvalidatedRangeInflate; Vector3I vectori2 = (Vector3I)(maxChanged + MyPrecalcComponent.InvalidatedRangeInflate); this.m_storage.ClampVoxelCoord(ref voxelCoord, 1); this.m_storage.ClampVoxelCoord(ref vectori2, 1); Vector3I start = voxelCoord >> 3; Vector3I end = vectori2 >> 3; using (this.m_lock.AcquireExclusiveUsing()) { if ((start == Vector3I.Zero) && (end == (this.m_cellsCount - 1))) { this.m_cellsByCoordinate.Clear(); this.m_coordinateToMesh.Clear(); this.m_isEmptyCache.Reset(); } else { MyCellCoord cell = new MyCellCoord(); if ((this.m_cellsByCoordinate.Count > 0) || (this.m_coordinateToMesh.Count > 0)) { cell.CoordInLod = start; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end); while (iterator.IsValid()) { ulong key = cell.PackId64(); this.m_cellsByCoordinate.Remove(key); this.m_coordinateToMesh.Remove(key); iterator.GetNext(out cell.CoordInLod); } } if ((end - start).Volume() <= 0x186a0) { Vector3I_RangeIterator iterator3 = new Vector3I_RangeIterator(ref start, ref end); while (iterator3.IsValid()) { this.SetEmpty(ref cell, false); iterator3.GetNext(out cell.CoordInLod); } } else { Vector3I vectori6 = start >> 2; Vector3I vectori7 = (Vector3I)((end >> 2) + 1); cell.CoordInLod = vectori6; Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori6, ref vectori7); while (iterator2.IsValid()) { Vector3I *vectoriPtr1 = (Vector3I *)ref cell.CoordInLod; vectoriPtr1[0] = vectoriPtr1[0] << 2; this.RemoveEmpty(ref cell); iterator2.GetNext(out cell.CoordInLod); } } } } }
private unsafe void ComputeIsEmptyLookup(MyCellCoord cell, out ulong outCacheKey, out int outBit) { Vector3I vectori = cell.CoordInLod % 4; Vector3I *vectoriPtr1 = (Vector3I *)ref cell.CoordInLod; vectoriPtr1[0] = vectoriPtr1[0] >> 2; outCacheKey = cell.PackId64(); outBit = vectori.X + (4 * (vectori.Y + (4 * vectori.Z))); }
/// <summary> /// Begins processing a voxel geometry cell /// </summary> public void OpenNewCell(MyCellCoord coord) { Debug.Assert(m_cellOpen == false, "Cannot open a new cell in MyVoxelHighLevelHelper while another one is open!"); m_cellOpen = true; m_currentCell = coord.CoordInLod; m_packedCoord = coord.PackId64(); m_triangleList.Clear(); }
private void ComputeIsEmptyLookup(MyCellCoord cell, out ulong outCacheKey, out int outBit) { var offset = cell.CoordInLod % 4; cell.CoordInLod >>= 2; Debug.Assert(offset.IsInsideInclusive(Vector3I.Zero, new Vector3I(3))); outCacheKey = cell.PackId64(); outBit = offset.X + 4 * (offset.Y + 4 * offset.Z); Debug.Assert((uint)outBit < 64u); }
internal CellData GetCell(ref MyCellCoord cell) { MyPrecalcComponent.AssertUpdateThread(); bool isEmpty; CellData data; if (TryGetCell(cell, out isEmpty, out data)) { return(data); } MyIsoMesh mesh; if (!TryGetMesh(cell, out isEmpty, out mesh)) { ProfilerShort.Begin("Cell precalc"); mesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs() { Storage = m_storage, GeometryCell = cell, }); ProfilerShort.End(); } if (mesh != null) { data = new CellData(); data.Init( mesh.PositionOffset, mesh.PositionScale, mesh.Positions.GetInternalArray(), mesh.VerticesCount, mesh.Triangles.GetInternalArray(), mesh.TrianglesCount); } if (cell.Lod == 0) { using (m_lock.AcquireExclusiveUsing()) { if (data != null) { var key = cell.PackId64(); m_cellsByCoordinate[key] = data; } else { SetEmpty(ref cell, true); } } } return(data); }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate + 1; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate + 1; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCellLod0, maxCellLod0; minVoxelChanged -= m_voxelMap.StorageMin; maxVoxelChanged -= m_voxelMap.StorageMin; MyVoxelCoordSystems.VoxelCoordToRenderCellCoord(0, ref minVoxelChanged, out minCellLod0); MyVoxelCoordSystems.VoxelCoordToRenderCellCoord(0, ref maxVoxelChanged, out maxCellLod0); MyRenderProxy.InvalidateClipmapRange(m_renderObjectIDs[0], minCellLod0, maxCellLod0); if (minCellLod0 == Vector3I.Zero && maxCellLod0 == ((m_voxelMap.Storage.Size - 1) >> MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShift(0))) { m_renderWorkTracker.InvalidateAll(); m_mergeWorkTracker.InvalidateAll(); } else { for (int i = 0; i < MyCellCoord.MAX_LOD_COUNT; ++i) { var minCell = minCellLod0 >> i; var maxCell = maxCellLod0 >> i; var cellCoord = new MyCellCoord(i, ref minCell); for (var it = new Vector3I_RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out cellCoord.CoordInLod)) { m_renderWorkTracker.Invalidate(cellCoord.PackId64()); m_mergeWorkTracker.Invalidate(cellCoord.PackId64()); } } } }
public unsafe void TryClearCell(ulong packedCoord) { MyNavmeshComponents.CellInfo info; if (this.m_triangleLists.ContainsKey(packedCoord)) { this.ClearCachedCell(packedCoord); } this.RemoveExplored(packedCoord); if (this.m_navmeshComponents.TryGetCell(packedCoord, out info)) { for (int i = 0; i < info.ComponentNum; i++) { int index = info.StartingIndex + i; this.m_mesh.HighLevelGroup.RemovePrimitive(index); } foreach (Base6Directions.Direction direction in Base6Directions.EnumDirections) { Base6Directions.DirectionFlags directionFlag = Base6Directions.GetDirectionFlag(direction); if (info.ExploredDirections.HasFlag(directionFlag)) { MyNavmeshComponents.CellInfo info2; Vector3I intVector = Base6Directions.GetIntVector(direction); MyCellCoord coord = new MyCellCoord(); coord.SetUnpack(packedCoord); MyCellCoord *coordPtr1 = (MyCellCoord *)ref coord; coordPtr1->CoordInLod = (Vector3I)(coord.CoordInLod + intVector); if (this.m_navmeshComponents.TryGetCell(coord.PackId64(), out info2)) { Base6Directions.DirectionFlags flags2 = Base6Directions.GetDirectionFlag(Base6Directions.GetFlippedDirection(direction)); this.m_navmeshComponents.SetExplored(coord.PackId64(), info2.ExploredDirections & ((byte)~flags2)); } } } this.m_navmeshComponents.ClearCell(packedCoord, ref info); } }
protected override void ResetInternal(MyStorageDataTypeFlags dataToReset) { bool resetContent = (dataToReset & MyStorageDataTypeFlags.Content) != 0; bool resetMaterials = (dataToReset & MyStorageDataTypeFlags.Material) != 0; if (resetContent) { m_contentLeaves.Clear(); m_contentNodes.Clear(); } if (resetMaterials) { m_materialLeaves.Clear(); m_materialNodes.Clear(); } if (m_dataProvider != null) { var cellCoord = new MyCellCoord(m_treeHeight, ref Vector3I.Zero); var leafId = cellCoord.PackId64(); cellCoord.Lod += LeafLodCount; var end = Size - 1; if (resetContent) { m_contentLeaves.Add(leafId, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Content, ref cellCoord)); } if (resetMaterials) { m_materialLeaves.Add(leafId, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Material, ref cellCoord)); } } else { var nodeId = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero).PackId64(); if (resetContent) { m_contentNodes.Add(nodeId, new MyOctreeNode()); } if (resetMaterials) { m_materialNodes.Add(nodeId, new MyOctreeNode()); } } }
public void SetMesh(MyCellCoord cell, MyIsoMesh mesh) { if (cell.Lod == 0) { using (this.m_lock.AcquireExclusiveUsing()) { if (mesh == null) { this.SetEmpty(ref cell, true); } else { ulong num = cell.PackId64(); this.m_coordinateToMesh[num] = mesh; } } } }
private MyHighLevelPrimitive GetClosestHighLevelPrimitive(ref Vector3 point, ref float closestDistanceSq) { MyHighLevelPrimitive retval = null; // Convert from world matrix local coords to LeftBottomCorner-based coords Vector3 lbcPoint = point + (m_voxelMap.PositionComp.GetPosition() - m_voxelMap.PositionLeftBottomCorner); m_tmpIntList.Clear(); // Collect components from the eight closest cells Vector3I closestCellCorner = Vector3I.Round(lbcPoint / m_cellSize); for (int i = 0; i < 8; ++i) { Vector3I cell = closestCellCorner + m_cornerOffsets[i]; MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell); ulong packedCoord = coord.PackId64(); m_higherLevelHelper.CollectComponents(packedCoord, m_tmpIntList); } foreach (int componentIndex in m_tmpIntList) { var hlPrimitive = m_higherLevel.GetPrimitive(componentIndex); Debug.Assert(hlPrimitive != null, "Couldnt' find a high-level primitive for the index given by higher level helper!"); if (hlPrimitive == null) { continue; } float distSq = Vector3.DistanceSquared(hlPrimitive.Position, point); if (distSq < closestDistanceSq) { closestDistanceSq = distSq; retval = hlPrimitive; } } m_tmpIntList.Clear(); return(retval); }
private static unsafe void ReadOctreeNodes(Stream stream, ChunkHeader header, ref bool isOldFormat, Dictionary <UInt64, MyOctreeNode> contentNodes) { switch (header.Version) { case VERSION_OCTREE_NODES_32BIT_KEY: { const int entrySize = sizeof(UInt32) + MyOctreeNode.SERIALIZED_SIZE; Debug.Assert((header.Size % entrySize) == 0); int nodesCount = header.Size / entrySize; MyOctreeNode node; MyCellCoord cell = new MyCellCoord(); for (int i = 0; i < nodesCount; i++) { cell.SetUnpack(stream.ReadUInt32()); node.ChildMask = stream.ReadByteNoAlloc(); stream.ReadNoAlloc(node.Data, 0, MyOctreeNode.CHILD_COUNT); contentNodes.Add(cell.PackId64(), node); } isOldFormat = true; } break; case CURRENT_VERSION_OCTREE_NODES: { const int entrySize = sizeof(UInt64) + MyOctreeNode.SERIALIZED_SIZE; Debug.Assert((header.Size % entrySize) == 0); int nodesCount = header.Size / entrySize; MyOctreeNode node; UInt64 key; for (int i = 0; i < nodesCount; i++) { key = stream.ReadUInt64(); node.ChildMask = stream.ReadByteNoAlloc(); stream.ReadNoAlloc(node.Data, 0, MyOctreeNode.CHILD_COUNT); contentNodes.Add(key, node); } } break; default: throw new InvalidBranchException(); } }
private bool RemoveCell(Vector3I cell) { if (!MyFakes.REMOVE_VOXEL_NAVMESH_CELLS) { return(true); } Debug.Assert(m_processedCells.Contains(cell), "Removing a non-existent cell from the navmesh!"); if (!m_processedCells.Contains(cell)) { return(false); } MyTrace.Send(TraceWindow.Ai, "Removing cell " + cell); ProfilerShort.Begin("Removing navmesh links"); MyVoxelPathfinding.CellId cellId = new MyVoxelPathfinding.CellId() { VoxelMap = m_voxelMap, Pos = cell }; m_navmeshCoordinator.RemoveVoxelNavmeshLinks(cellId); ProfilerShort.End(); ProfilerShort.Begin("Removing triangles"); MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell); ulong packedCoord = coord.PackId64(); MyIntervalList triangleList = m_higherLevelHelper.TryGetTriangleList(packedCoord); if (triangleList != null) { foreach (var triangleIndex in triangleList) { RemoveTerrainTriangle(GetTriangle(triangleIndex)); } m_higherLevelHelper.ClearCachedCell(packedCoord); } ProfilerShort.End(); Debug.Assert(m_processedCells.Contains(ref cell)); m_processedCells.Remove(ref cell); return(triangleList != null); }
private MyNavigationTriangle GetClosestNavigationTriangle(ref Vector3 point, ref float closestDistanceSq) { // TODO: When point is completely away (according to BB), return null MyNavigationTriangle closestTriangle = null; // Convert from world matrix local coords to LeftBottomCorner-based coords Vector3 lbcPoint = point + (m_voxelMap.PositionComp.GetPosition() - m_voxelMap.PositionLeftBottomCorner); Vector3I closestCellCorner = Vector3I.Round(lbcPoint / m_cellSize); for (int i = 0; i < 8; ++i) { Vector3I cell = closestCellCorner + m_cornerOffsets[i]; if (!m_processedCells.Contains(cell)) { continue; } MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cell); ulong packedCoord = coord.PackId64(); MyIntervalList triList = m_higherLevelHelper.TryGetTriangleList(packedCoord); if (triList == null) { continue; } foreach (var triIndex in triList) { MyNavigationTriangle tri = GetTriangle(triIndex); // TODO: Use triangle centers so far float distSq = Vector3.DistanceSquared(tri.Center, point); if (distSq < closestDistanceSq) { closestDistanceSq = distSq; closestTriangle = tri; } } } return(closestTriangle); }
internal void OnCellRequest(MyCellCoord cell, bool highPriority, Func <int> priorityFunction, Action <Color> debugDraw) { ProfilerShort.Begin("OnCellRequest"); try { var workId = cell.PackId64(); MyPrecalcJobRender job; if (m_renderWorkTracker.TryGet(workId, out job)) { if (!highPriority) { // low priority work, no need to do anything return; } if (job.IsHighPriority) { // both are high priorities, so just invalidate previous one m_renderWorkTracker.Invalidate(workId); return; } // high priority arrived while there was one with low priority ... just cancel lower one m_renderWorkTracker.Cancel(workId); } MyPrecalcJobRender.Start(new MyPrecalcJobRender.Args() { Storage = m_voxelMap.Storage, ClipmapId = ClipmapId, Cell = cell, WorkId = workId, RenderWorkTracker = m_renderWorkTracker, IsHighPriority = highPriority, Priority = priorityFunction, DebugDraw = debugDraw, }); } finally { ProfilerShort.End(); } }
protected void SaveInternal(MemoryStream stream) { WriteStorageMetaData(stream); WriteMaterialTable(stream); WriteDataProvider(stream, DataProvider); WriteOctreeNodes(stream, ChunkTypeEnum.MacroContentNodes); WriteOctreeNodes(stream, ChunkTypeEnum.MacroMaterialNodes); var cellCoord = new MyCellCoord(m_treeHeight, ref Vector3I.Zero); var leafId = cellCoord.PackId64(); cellCoord.Lod += LeafLodCount; WriteEmptyProviderLeaf(stream, leafId, ChunkTypeEnum.ContentLeafProvider); WriteEmptyProviderLeaf(stream, leafId, ChunkTypeEnum.MaterialLeafProvider); new ChunkHeader() { ChunkType = ChunkTypeEnum.EndOfFile, }.WriteTo(stream); }
public void SetMesh(MyCellCoord cell, MyIsoMesh mesh) { // Don't store anything but the most detailed lod (used in physics and raycasts). // This cache is mostly supposed to help physics and raycasts, not render. if (cell.Lod != 0) { return; } MyPrecalcComponent.AssertUpdateThread(); using (m_lock.AcquireExclusiveUsing()) { if (mesh != null) { var key = cell.PackId64(); m_coordinateToMesh[key] = mesh; } else { SetEmpty(ref cell, true); } } }
public bool TryGetMesh(MyCellCoord cell, out bool isEmpty, out MyIsoMesh nonEmptyMesh) { using (m_lock.AcquireSharedUsing()) { if (IsEmpty(ref cell)) { isEmpty = true; nonEmptyMesh = null; return(true); } UInt64 key = cell.PackId64(); if (m_coordinateToMesh.TryGetValue(key, out nonEmptyMesh)) { isEmpty = false; return(true); } isEmpty = default(bool); nonEmptyMesh = default(MyIsoMesh); return(false); } }
/// <param name="minVoxelChanged">Inclusive min.</param> /// <param name="maxVoxelChanged">Inclusive max.</param> private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin("MyVoxelGeometry.storage_RangeChanged"); minChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_storage.ClampVoxelCoord(ref minChanged); m_storage.ClampVoxelCoord(ref maxChanged); var minCellChanged = minChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var maxCellChanged = maxChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; using (m_lock.AcquireExclusiveUsing()) { if (minCellChanged == Vector3I.Zero && maxCellChanged == m_cellsCount - 1) { m_cellsByCoordinate.Clear(); m_coordinateToMesh.Clear(); m_isEmptyCache.Reset(); } else { MyCellCoord cell = new MyCellCoord(); cell.CoordInLod = minCellChanged; for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell.CoordInLod)) { var key = cell.PackId64(); m_cellsByCoordinate.Remove(key); m_coordinateToMesh.Remove(key); SetEmpty(ref cell, false); } } } ProfilerShort.End(); }
internal CellData GetCell(ref MyCellCoord cell) { bool flag; CellData data; if (!this.TryGetCell(cell, out flag, out data)) { MyIsoMesh mesh; if (!this.TryGetMesh(cell, out flag, out mesh)) { Vector3I lodVoxelMin = cell.CoordInLod << 3; lodVoxelMin -= 1; mesh = MyPrecalcComponent.IsoMesher.Precalc(this.m_storage, 0, lodVoxelMin, (Vector3I)((lodVoxelMin + 8) + 2), MyStorageDataTypeFlags.Content, 0); } if (mesh != null) { data = new CellData(); data.Init((Vector3)mesh.PositionOffset, mesh.PositionScale, mesh.Positions.GetInternalArray <Vector3>(), mesh.VerticesCount, mesh.Triangles.GetInternalArray <MyVoxelTriangle>(), mesh.TrianglesCount); } if (cell.Lod == 0) { using (this.m_lock.AcquireExclusiveUsing()) { if (data == null) { this.SetEmpty(ref cell, true); } else { ulong num = cell.PackId64(); this.m_cellsByCoordinate[num] = data; } } } } return(data); }
private bool TryGetCell(MyCellCoord cell, out bool isEmpty, out CellData nonEmptyCell) { MyPrecalcComponent.AssertUpdateThread(); using (m_lock.AcquireSharedUsing()) { if (IsEmpty(ref cell)) { isEmpty = true; nonEmptyCell = null; return(true); } UInt64 key = cell.PackId64(); if (m_cellsByCoordinate.TryGetValue(key, out nonEmptyCell)) { isEmpty = false; return(true); } isEmpty = default(bool); nonEmptyCell = default(CellData); return(false); } }
internal void OnCellRequest(MyCellCoord cell, Func <int> priorityFunction, Action <Color> debugDraw) { ProfilerShort.Begin("OnCellRequest"); try { var workId = cell.PackId64(); MyPrecalcJobRender.Start(new MyPrecalcJobRender.Args { Storage = m_voxelMap.Storage, ClipmapId = ClipmapId, Cell = cell, WorkId = workId, RenderWorkTracker = m_renderWorkTracker, Priority = priorityFunction, DebugDraw = debugDraw, }); } finally { ProfilerShort.End(); } }
internal void OnCellRequestCancelled(MyCellCoord cell) { var workId = cell.PackId64(); m_renderWorkTracker.Cancel(workId); }
internal CellData GetCell(ref MyCellCoord cell) { MyPrecalcComponent.AssertUpdateThread(); bool isEmpty; CellData data; if (TryGetCell(cell, out isEmpty, out data)) { return(data); } MyIsoMesh mesh; if (!TryGetMesh(cell, out isEmpty, out mesh)) { ProfilerShort.Begin("Cell precalc"); if (true) { var min = cell.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS; // overlap to neighbor; introduces extra data but it makes logic for raycasts simpler (no need to check neighbor cells) min -= 1; max += 2; mesh = MyPrecalcComponent.IsoMesher.Precalc(m_storage, 0, min, max, false, false); } else { mesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs() { Storage = m_storage, GeometryCell = cell, }); } ProfilerShort.End(); } if (mesh != null) { data = new CellData(); data.Init( mesh.PositionOffset, mesh.PositionScale, mesh.Positions.GetInternalArray(), mesh.VerticesCount, mesh.Triangles.GetInternalArray(), mesh.TrianglesCount); } if (cell.Lod == 0) { using (m_lock.AcquireExclusiveUsing()) { if (data != null) { var key = cell.PackId64(); m_cellsByCoordinate[key] = data; } else { SetEmpty(ref cell, true); } } } return(data); }
public void ProcessChangedCellComponents() { ProfilerShort.Begin("ProcessChangedCellComponents"); m_currentHelper = this; Vector3I min, max, pos; List <int> triangles = null; foreach (var cell in m_changedCells) { MyCellCoord cellCoord = new MyCellCoord(0, cell); ulong packedCell = cellCoord.PackId64(); m_components.OpenCell(packedCell); min = CellToLowestCube(cell); max = min + m_cellSize - Vector3I.One; // Save a hashset of all the triangles in the current cell pos = min; for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos)) { if (!m_triangleRegistry.TryGetValue(pos, out triangles)) { continue; } foreach (var triIndex in triangles) { m_tmpCellTriangles.Add(triIndex); } } long timeBegin = m_mesh.GetCurrentTimestamp() + 1; long timeEnd = timeBegin; m_currentComponentRel = 0; foreach (var triIndex in m_tmpCellTriangles) { // Skip already visited triangles var triangle = m_mesh.GetTriangle(triIndex); if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd)) { continue; } m_components.OpenComponent(); // Make sure we have place in m_currentCellConnections if (m_currentComponentRel >= m_currentCellConnections.Count) { m_currentCellConnections.Add(new List <int>()); } // Find connected component from an unvisited triangle and mark its connections m_components.AddComponentTriangle(triangle, triangle.Center); triangle.ComponentIndex = m_components.OpenComponentIndex; m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate); var primitiveEnum = m_mesh.GetEnumerator(); while (primitiveEnum.MoveNext()) { ; } primitiveEnum.Dispose(); m_components.CloseComponent(); timeEnd = m_mesh.GetCurrentTimestamp(); if (m_currentComponentRel == 0) { timeBegin = timeEnd; } m_currentComponentRel++; } m_tmpCellTriangles.Clear(); MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo(); m_components.CloseAndCacheCell(ref cellInfo); // Add new component primitives if (cellInfo.NewCell) { for (int i = 0; i < cellInfo.ComponentNum; ++i) { m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_components.GetComponentCenter(i)); } } // Connect new components with the others in the neighboring cells for (int i = 0; i < cellInfo.ComponentNum; ++i) { foreach (var otherComponent in m_currentCellConnections[i]) { m_mesh.HighLevelGroup.ConnectPrimitives(cellInfo.StartingIndex + i, otherComponent); } m_currentCellConnections[i].Clear(); } // Set all the components as expanded for (int i = 0; i < cellInfo.ComponentNum; ++i) { int componentIndex = cellInfo.StartingIndex + i; var component = m_mesh.HighLevelGroup.GetPrimitive(componentIndex); if (component != null) { component.IsExpanded = true; } } } m_changedCells.Clear(); m_currentHelper = null; ProfilerShort.End(); }
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); }
public void ProcessChangedCellComponents() { ProfilerShort.Begin("ProcessChangedCellComponents"); m_currentHelper = this; Vector3I min, max, pos; List <int> triangles = null; foreach (var cell in m_changedCells) { min = CellToLowestCube(cell); max = min + m_cellSize - Vector3I.One; // Save a hashset of all the triangles in the current cell pos = min; for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos)) { if (!m_triangleRegistry.TryGetValue(pos, out triangles)) { continue; } foreach (var triIndex in triangles) { m_tmpCellTriangles.Add(triIndex); } } if (m_tmpCellTriangles.Count == 0) { continue; } MyCellCoord cellCoord = new MyCellCoord(0, cell); ulong packedCell = cellCoord.PackId64(); m_components.OpenCell(packedCell); long timeBegin = m_mesh.GetCurrentTimestamp() + 1; long timeEnd = timeBegin; m_currentComponentRel = 0; m_tmpComponentTriangles.Clear(); foreach (var triIndex in m_tmpCellTriangles) { // Skip already visited triangles var triangle = m_mesh.GetTriangle(triIndex); if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd)) { continue; } m_components.OpenComponent(); // Make sure we have place in m_currentCellConnections if (m_currentComponentRel >= m_currentCellConnections.Count) { m_currentCellConnections.Add(new List <int>()); } // Find connected component from an unvisited triangle and mark its connections m_components.AddComponentTriangle(triangle, triangle.Center); triangle.ComponentIndex = m_currentComponentRel; m_tmpComponentTriangles.Add(triangle); m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate); m_mesh.PerformTraversal(); m_tmpComponentTriangles.Add(null); m_components.CloseComponent(); timeEnd = m_mesh.GetCurrentTimestamp(); if (m_currentComponentRel == 0) { timeBegin = timeEnd; } m_currentComponentRel++; } m_tmpCellTriangles.Clear(); MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo(); m_components.CloseAndCacheCell(ref cellInfo); // Renumber triangles from the old indices to the newly assigned index from m_components int componentIndex = cellInfo.StartingIndex; foreach (var triangle in m_tmpComponentTriangles) { if (triangle == null) { componentIndex++; continue; } triangle.ComponentIndex = componentIndex; } m_tmpComponentTriangles.Clear(); // Remove old component primitives if (!cellInfo.NewCell && cellInfo.ComponentNum != cellInfo.OldComponentNum) { for (int i = 0; i < cellInfo.OldComponentNum; ++i) { m_mesh.HighLevelGroup.RemovePrimitive(cellInfo.OldStartingIndex + i); } } // Add new component primitives if (cellInfo.NewCell || cellInfo.ComponentNum != cellInfo.OldComponentNum) { for (int i = 0; i < cellInfo.ComponentNum; ++i) { m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_components.GetComponentCenter(i)); } } // Update existing component primitives if (!cellInfo.NewCell && cellInfo.ComponentNum == cellInfo.OldComponentNum) { for (int i = 0; i < cellInfo.ComponentNum; ++i) { var primitive = m_mesh.HighLevelGroup.GetPrimitive(cellInfo.StartingIndex + i); primitive.UpdatePosition(m_components.GetComponentCenter(i)); } } // Connect new components with the others in the neighboring cells for (int i = 0; i < cellInfo.ComponentNum; ++i) { int compIndex = cellInfo.StartingIndex + i; var primitive = m_mesh.HighLevelGroup.GetPrimitive(compIndex); primitive.GetNeighbours(m_tmpNeighbors); // Connect to disconnected components foreach (var connection in m_currentCellConnections[i]) { if (!m_tmpNeighbors.Remove(connection)) { m_mesh.HighLevelGroup.ConnectPrimitives(compIndex, connection); } } // Disconnect neighbors that should be no longer connected foreach (var neighbor in m_tmpNeighbors) { // Only disconnect from the other cell if it is expanded and there was no connection found var neighborPrimitive = m_mesh.HighLevelGroup.TryGetPrimitive(neighbor); if (neighborPrimitive != null && neighborPrimitive.IsExpanded) { m_mesh.HighLevelGroup.DisconnectPrimitives(compIndex, neighbor); } } m_tmpNeighbors.Clear(); m_currentCellConnections[i].Clear(); } // Set all the components as expanded for (int i = 0; i < cellInfo.ComponentNum; ++i) { componentIndex = cellInfo.StartingIndex + i; var component = m_mesh.HighLevelGroup.GetPrimitive(componentIndex); if (component != null) { component.IsExpanded = true; } } } m_changedCells.Clear(); m_currentHelper = null; ProfilerShort.End(); }