internal void GenerateAllShapes() { if (this.m_mesher != null) { if (!this.m_bodiesInitialized) { this.CreateRigidBodies(); } Vector3I zero = Vector3I.Zero; Vector3I size = this.m_voxelMap.Size; Vector3I end = new Vector3I(0, 0, 0) { X = size.X >> 3, Y = size.Y >> 3, Z = size.Z >> 3 }; end = (Vector3I)(end + zero); MyPrecalcJobPhysicsPrefetch.Args args = new MyPrecalcJobPhysicsPrefetch.Args { GeometryCell = new MyCellCoord(1, zero), Storage = this.m_voxelMap.Storage, TargetPhysics = this, Tracker = this.m_workTracker }; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref zero, ref end); while (iterator.IsValid()) { MyPrecalcJobPhysicsPrefetch.Start(args); iterator.GetNext(out args.GeometryCell.CoordInLod); } } }
/// <summary> /// Non-allocating version of Sandbox.Game.Entities.MyCubeGrid.GetBlocksInsideSphere() /// </summary> public void GetBlocksInsideSphere(IMyCubeGrid grid, List <IMySlimBlock> blockList, ref BoundingSphereD sphere) { if (grid.PositionComp != null) { MatrixD matrix = grid.PositionComp.WorldMatrixNormalizedInv; Vector3D result; Vector3D.Transform(ref sphere.Center, ref matrix, out result); BoundingSphere localSphere = new BoundingSphere(result, (float)sphere.Radius); BoundingBox boundingBox = BoundingBox.CreateFromSphere(localSphere); double gridSizeR = 1d / grid.GridSize; Vector3I searchMin = new Vector3I ( (int)Math.Round(boundingBox.Min.X * gridSizeR), (int)Math.Round(boundingBox.Min.Y * gridSizeR), (int)Math.Round(boundingBox.Min.Z * gridSizeR) ); Vector3I searchMax = new Vector3I ( (int)Math.Round(boundingBox.Max.X * gridSizeR), (int)Math.Round(boundingBox.Max.Y * gridSizeR), (int)Math.Round(boundingBox.Max.Z * gridSizeR) ); Vector3I start = Vector3I.Max(Vector3I.Min(searchMin, searchMax), grid.Min); Vector3I end = Vector3I.Min(Vector3I.Max(searchMin, searchMax), grid.Max); var gridIterator = new Vector3I_RangeIterator(ref start, ref end); Vector3I next = gridIterator.Current; blockHashBuffer.Clear(); while (gridIterator.IsValid()) { IMySlimBlock cube = grid.GetCubeBlock(next); float gridSizeHalf = grid.GridSize / 2f; if (cube != null) { var cubeBounds = new BoundingBox((cube.Min * grid.GridSize) - gridSizeHalf, (cube.Max * grid.GridSize) + gridSizeHalf); if (cubeBounds.Intersects(localSphere)) { blockHashBuffer.Add(cube); } } gridIterator.GetNext(out next); } blockList.Clear(); blockList.EnsureCapacity(blockHashBuffer.Count); foreach (IMySlimBlock block in blockHashBuffer) { blockList.Add(block); } } }
private void Segment() { m_segmentation.ClearInput(); foreach (MySlimBlock local1 in this.m_grid.CubeBlocks) { Vector3I min = local1.Min; Vector3I max = local1.Max; Vector3I input = min; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref min, ref max); while (iterator.IsValid()) { m_segmentation.AddInput(input); iterator.GetNext(out input); } } List <Sandbox.Engine.Utils.MyVoxelSegmentation.Segment> list = m_segmentation.FindSegments(MyVoxelSegmentationType.Simple2, 1); this.m_segments = new List <BoundingBox>(list.Count); for (int i = 0; i < list.Count; i++) { BoundingBox item = new BoundingBox { Min = ((new Vector3(list[i].Min) - Vector3.Half) * this.m_grid.GridSize) - Vector3.Half, Max = ((new Vector3(list[i].Max) + Vector3.Half) * this.m_grid.GridSize) + Vector3.Half }; this.m_segments.Add(item); } m_segmentation.ClearInput(); }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { Vector3I vectori; Vector3I vectori2; minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged = (Vector3I)(maxVoxelChanged + MyPrecalcComponent.InvalidatedRangeInflate); this.m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged, 1); this.m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged, 1); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out vectori); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out vectori2); Vector3I position = vectori; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2); while (iterator.IsValid()) { if (!this.m_processedCells.Contains(ref position)) { this.m_higherLevelHelper.TryClearCell(new MyCellCoord(0, position).PackId64()); } else if (!this.m_cellsToChangeSet.Contains(ref position)) { this.m_cellsToChange.AddLast(position); this.m_cellsToChangeSet.Add(position); } iterator.GetNext(out position); } }
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; } } } }
public unsafe void MarkBoxForAddition(BoundingBoxD box) { Vector3I vectori; Vector3I vectori2; MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Min, out vectori); MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Max, out vectori2); this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori, 1); this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1); Vector3I *vectoriPtr1 = (Vector3I *)ref vectori; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr1, out vectori); Vector3I *vectoriPtr2 = (Vector3I *)ref vectori2; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr2, out vectori2); Vector3 vector = (vectori + vectori2) * 0.5f; vectori = (Vector3I)(vectori / 1); vectori2 = (Vector3I)(vectori2 / 1); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2); while (iterator.IsValid()) { if (Vector3.RectangularDistance((Vector3)vectori, vector) <= 1f) { this.MarkCellForAddition(vectori, PresentEntityWeight); } iterator.GetNext(out vectori); } }
/// <summary> /// Checks only immediate children (any deeper would take too long). /// </summary> private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell) { if (childLod == null) { return(false); } Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1); var childLodCell = new MyCellCoord(); childLodCell.Lod = childLod.m_lodIndex; var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod); var start = thisLodCell.CoordInLod << shiftToChild; var end = start + ((1 << shiftToChild) >> 1); Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne); Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end); childLodCell.CoordInLod = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out childLodCell.CoordInLod)) { var key = childLodCell.PackId64(); MyClipmap_CellData data; if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded) { return(false); } } return(true); }
internal void GenerateAllShapes() { if (!m_bodiesInitialized) { CreateRigidBodies(); } var min = Vector3I.Zero; Vector3I storageSize = m_voxelMap.Size; Vector3I max = new Vector3I(0, 0, 0); max.X = storageSize.X >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max.Y = storageSize.Y >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max.Z = storageSize.Z >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max += min; var args = new MyPrecalcJobPhysicsPrefetch.Args { GeometryCell = new MyCellCoord(1, min), Storage = m_voxelMap.Storage, TargetPhysics = this, Tracker = m_workTracker }; for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out args.GeometryCell.CoordInLod)) { MyPrecalcJobPhysicsPrefetch.Start(args); } }
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 void AddBlock(MySlimBlock block) { Vector3I min = block.Min; Vector3I max = block.Max; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref min, ref max); while (iterator.IsValid()) { this.m_cubeSet.Add(ref min); iterator.GetNext(out min); } MatrixI transform = new MatrixI(block.Position, block.Orientation.Forward, block.Orientation.Up); this.MergeFromAnotherMesh(block.BlockDefinition.NavigationDefinition.Mesh, ref transform); }
private void RemoveBlock(Vector3I min, Vector3I max, bool eraseCubeSet) { Vector3I start = min; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref max); while (iterator.IsValid()) { if (eraseCubeSet) { this.m_cubeSet.Remove(ref start); } this.EraseCubeTriangles(start); iterator.GetNext(out start); } }
public static bool AnyBlocksInAABB(this MyGridDataComponent g, BoundingBoxD box) { var e = g.Entity; if (e.PositionComp == null) { return(false); } if (box.Contains(e.PositionComp.WorldAABB) == ContainmentType.Contains) { return(g.BlockCount > 0); } var orientedBoundingBoxD = OrientedBoundingBoxD.Create(box, e.PositionComp.WorldMatrixNormalizedInv); var sizeR = 1f / g.Size; orientedBoundingBoxD.Center *= sizeR; orientedBoundingBoxD.HalfExtent *= sizeR; box = box.TransformFast(e.PositionComp.WorldMatrixNormalizedInv); var min = box.Min; var max = box.Max; var obbPt1 = new Vector3I((int)Math.Round(min.X * sizeR), (int)Math.Round(min.Y * sizeR), (int)Math.Round(min.Z * sizeR)); var obbPt2 = new Vector3I((int)Math.Round(max.X * sizeR), (int)Math.Round(max.Y * sizeR), (int)Math.Round(max.Z * sizeR)); var obbMin = Vector3I.Min(obbPt1, obbPt2); var obbMax = Vector3I.Max(obbPt1, obbPt2); var start = Vector3I.Max(obbMin, g.Min); var end = Vector3I.Min(obbMax, g.Max); if (start.X > end.X || start.Y > end.Y || start.Z > end.Z) { return(false); } var vector3IRangeIterator = new Vector3I_RangeIterator(ref start, ref end); var next = vector3IRangeIterator.Current; while (vector3IRangeIterator.IsValid()) { if (g.GetAnyBlock(next) != null) { return(true); } vector3IRangeIterator.GetNext(out next); } return(false); }
/// <summary> /// Checks if blocks are neigbors to block(s) in aabbForNeighbors. /// </summary> private static void CheckNeighborBlocks(MySlimBlock block, BoundingBoxD aabbForNeighbors, MyCubeGrid cubeGrid, List <MySlimBlock> blocks) { var compositeTransformToGrid = block.CubeGrid.WorldMatrix * cubeGrid.PositionComp.WorldMatrixNormalizedInv; var aabbForNeighborsInGrid = aabbForNeighbors.TransformFast(ref compositeTransformToGrid); Vector3I start = Vector3I.Round(cubeGrid.GridSizeR * aabbForNeighborsInGrid.Min); Vector3I end = Vector3I.Round(cubeGrid.GridSizeR * aabbForNeighborsInGrid.Max); Vector3I startIt = Vector3I.Min(start, end); Vector3I endIt = Vector3I.Max(start, end); for (int slimBlockIndex = blocks.Count - 1; slimBlockIndex >= 0; --slimBlockIndex) { var slimBlock = blocks[slimBlockIndex]; bool found = false; Vector3I_RangeIterator itBlockInGridPos = new Vector3I_RangeIterator(ref slimBlock.Min, ref slimBlock.Max); var posInGrid = itBlockInGridPos.Current; for (; itBlockInGridPos.IsValid(); itBlockInGridPos.GetNext(out posInGrid)) { Vector3I_RangeIterator itBlockPos = new Vector3I_RangeIterator(ref startIt, ref endIt); var pos = itBlockPos.Current; for (; itBlockPos.IsValid(); itBlockPos.GetNext(out pos)) { Vector3I diff = Vector3I.Abs(posInGrid - pos); if (pos == posInGrid || diff.X + diff.Y + diff.Z == 1) { found = true; break; } } if (found) { break; } } if (!found) { blocks.RemoveAt(slimBlockIndex); } } }
// Actually, this function marks even cubes around the block to make sure that any changes caused in their triangles // will be reflected in the navigation mesh. public void MarkBlockChanged(MySlimBlock block) { Vector3I min = block.Min - Vector3I.One; Vector3I max = block.Max + Vector3I.One; Vector3I pos = min; for (var it = new Vector3I_RangeIterator(ref block.Min, ref block.Max); it.IsValid(); it.GetNext(out pos)) { m_changedCubes.Add(pos); } Vector3I minCell = CubeToCell(ref min); Vector3I maxCell = CubeToCell(ref max); pos = minCell; for (var it = new Vector3I_RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out pos)) { m_changedCells.Add(pos); } }
//[Conditional("DEBUG")] private void FixCacheMaterial(Vector3I voxelStart, Vector3I voxelEnd) { var mcount = Sandbox.Definitions.MyDefinitionManager.Static.VoxelMaterialCount; voxelEnd = Vector3I.Min(voxelEnd - voxelStart, m_cache.Size3D); voxelStart = Vector3I.Zero; var it = new Vector3I_RangeIterator(ref voxelStart, ref voxelEnd); var pos = it.Current; for (; it.IsValid(); it.GetNext(out pos)) { var lin = m_cache.ComputeLinear(ref pos); var mat = m_cache.Material(lin); if (mat >= mcount && mat != MyVoxelConstants.NULL_MATERIAL) { //Debug.Fail(String.Format("VoxelData contains invalid materials (id: {0}).", m_cache.Material(lin))); m_cache.Material(lin, MyVoxelConstants.NULL_MATERIAL); } } }
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()); } } } }
private bool FindNextNonemptyBin() { m_previousIndex = -1; if (!m_rangeIterator.IsValid()) { return(false); } Vector3I bin = m_rangeIterator.Current; while (!m_parent.m_bins.TryGetValue(bin, out m_storageIndex)) { m_rangeIterator.GetNext(out bin); if (!m_rangeIterator.IsValid()) { return(false); } } return(true); }
void IMyOctreeLeafNode.WriteRange(MyStorageData source, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max) { m_octree.WriteRange(source, m_dataType, ref readOffset, ref min, ref max); if (DEBUG_WRITES) { var tmp = new MyStorageData(); tmp.Resize(min, max); m_octree.ReadRange(tmp, m_dataType, ref Vector3I.Zero, 0, ref min, ref max); Vector3I p = Vector3I.Zero; var cacheEnd = max - min; int errorCounter = 0; for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref cacheEnd); it.IsValid(); it.GetNext(out p)) { var read = readOffset + p; if (source.Get(m_dataType, ref read) != tmp.Get(m_dataType, ref p)) { ++errorCounter; } } Debug.Assert(errorCounter == 0, string.Format("{0} errors writing to leaf octree.", errorCounter)); } }
private Vector3I FindTriangleCube(int triIndex, ref Vector3I edgePositionA, ref Vector3I edgePositionB) { Vector3I vectori; Vector3I vectori2; Vector3I.Min(ref edgePositionA, ref edgePositionB, out vectori); Vector3I.Max(ref edgePositionA, ref edgePositionB, out vectori2); vectori = Vector3I.Round((new Vector3(vectori) / 256f) - Vector3.Half); vectori2 = Vector3I.Round((new Vector3(vectori2) / 256f) + Vector3.Half); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2); while (iterator.IsValid()) { List <int> list; this.m_smallTriangleRegistry.TryGetValue(vectori, out list); if ((list != null) && list.Contains(triIndex)) { return(vectori); } iterator.GetNext(out vectori); } return(Vector3I.Zero); }
public void MarkBlockChanged(MySlimBlock block) { Vector3I cube = block.Min - Vector3I.One; Vector3I vectori2 = (Vector3I)(block.Max + Vector3I.One); Vector3I position = cube; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref block.Min, ref block.Max); while (iterator.IsValid()) { this.m_changedCubes.Add(position); iterator.GetNext(out position); } Vector3I start = this.CubeToCell(ref cube); Vector3I end = this.CubeToCell(ref vectori2); position = start; Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref start, ref end); while (iterator2.IsValid()) { this.m_changedCells.Add(position); iterator2.GetNext(out position); } }
private void Segment() { m_segmentation.ClearInput(); foreach (var block in m_grid.CubeBlocks) { Vector3I begin = block.Min; Vector3I end = block.Max; Vector3I pos = begin; for (var it = new Vector3I_RangeIterator(ref begin, ref end); it.IsValid(); it.GetNext(out pos)) m_segmentation.AddInput(pos); } var segmentList = m_segmentation.FindSegments(MyVoxelSegmentationType.Simple2); m_segments = new List<BoundingBox>(segmentList.Count); for (int i = 0; i < segmentList.Count; ++i) { BoundingBox bb = new BoundingBox(); bb.Min = (new Vector3(segmentList[i].Min) - Vector3.Half) * m_grid.GridSize - Vector3.Half; // The another half is here to just add some head space bb.Max = (new Vector3(segmentList[i].Max) + Vector3.Half) * m_grid.GridSize + Vector3.Half; m_segments.Add(bb); } m_segmentation.ClearInput(); }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List<MyCubeGrid> gridsToTest, List<MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { ProfilerShort.Begin("TestVoxelNavmeshTriangle"); ProfilerShort.Begin("Triangle-obstacle tests"); Vector3D s = (a + b + c) / 3.0; if (m_obstacles.IsInObstacle(s)) { intersecting = true; ProfilerShort.End(); ProfilerShort.End(); return; } ProfilerShort.End(); BoundingBoxD triBB; Vector3D aLocal, bLocal, cLocal, gLocal; Vector3D g = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { g = Vector3.Down * 2.0f; } m_tmpLinkCandidates.Clear(); intersecting = false; foreach (var grid in gridsToTest) { MatrixD mat = grid.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref mat, out aLocal); Vector3D.Transform(ref b, ref mat, out bLocal); Vector3D.Transform(ref c, ref mat, out cLocal); Vector3D.TransformNormal(ref g, ref mat, out gLocal); triBB = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); triBB.Include(ref aLocal, ref bLocal, ref cLocal); Vector3I min = grid.LocalToGridInteger(triBB.Min); Vector3I max = grid.LocalToGridInteger(triBB.Max); Vector3I pos = min - Vector3I.One; Vector3I max2 = max + Vector3I.One; for (var it = new Vector3I_RangeIterator(ref pos, ref max2); it.IsValid(); it.GetNext(out pos)) { if (grid.GetCubeBlock(pos) != null) { Vector3 largeMin = (pos - Vector3.One) * grid.GridSize; Vector3 largeMax = (pos + Vector3.One) * grid.GridSize; Vector3 smallMin = (pos - Vector3.Half) * grid.GridSize; Vector3 smallMax = (pos + Vector3.Half) * grid.GridSize; BoundingBoxD largeBb = new BoundingBoxD(largeMin, largeMax); BoundingBoxD bb = new BoundingBoxD(smallMin, smallMax); largeBb.Include(largeMin + gLocal); largeBb.Include(largeMax + gLocal); bb.Include(smallMin + gLocal); bb.Include(smallMax + gLocal); ProfilerShort.Begin("Triangle intersection tests"); if (largeBb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { if (bb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal)) { intersecting = true; ProfilerShort.End(); break; } else { int dx = Math.Min(Math.Abs(min.X - pos.X), Math.Abs(max.X - pos.X)); int dy = Math.Min(Math.Abs(min.Y - pos.Y), Math.Abs(max.Y - pos.Y)); int dz = Math.Min(Math.Abs(min.Z - pos.Z), Math.Abs(max.Z - pos.Z)); if ((dx + dy + dz) < 3) m_tmpLinkCandidates.Add(new MyGridPathfinding.CubeId() { Grid = grid, Coords = pos }); } } ProfilerShort.End(); } } if (intersecting) break; } if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; ++i) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); ProfilerShort.End(); }
public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List <MyCubeGrid> gridsToTest, List <MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting) { Vector3D point = ((a + b) + c) / 3.0; if (this.m_obstacles.IsInObstacle(point)) { intersecting = true; return; } Vector3D zero = Vector3D.Zero; if (MyPerGameSettings.NavmeshPresumesDownwardGravity) { zero = Vector3.Down * 2f; } m_tmpLinkCandidates.Clear(); intersecting = false; using (List <MyCubeGrid> .Enumerator enumerator = gridsToTest.GetEnumerator()) { goto TR_0016; TR_0008: if (intersecting) { goto TR_0006; } TR_0016: while (true) { if (enumerator.MoveNext()) { Vector3D vectord2; Vector3D vectord3; Vector3D vectord4; Vector3D vectord5; MyCubeGrid current = enumerator.Current; MatrixD worldMatrixNormalizedInv = current.PositionComp.WorldMatrixNormalizedInv; Vector3D.Transform(ref a, ref worldMatrixNormalizedInv, out vectord2); Vector3D.Transform(ref b, ref worldMatrixNormalizedInv, out vectord3); Vector3D.Transform(ref c, ref worldMatrixNormalizedInv, out vectord4); Vector3D.TransformNormal(ref zero, ref worldMatrixNormalizedInv, out vectord5); BoundingBoxD xd = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue); xd.Include(ref vectord2, ref vectord3, ref vectord4); Vector3I vectori = current.LocalToGridInteger((Vector3)xd.Min); Vector3I vectori2 = current.LocalToGridInteger((Vector3)xd.Max); Vector3I start = vectori - Vector3I.One; Vector3I end = (Vector3I)(vectori2 + Vector3I.One); Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end); while (iterator.IsValid()) { if (current.GetCubeBlock(start) != null) { Vector3 min = (Vector3)((start - Vector3.One) * current.GridSize); Vector3 max = (start + Vector3.One) * current.GridSize; Vector3 vector3 = (Vector3)((start - Vector3.Half) * current.GridSize); Vector3 vector4 = (start + Vector3.Half) * current.GridSize; BoundingBoxD xd3 = new BoundingBoxD(min, max); BoundingBoxD xd4 = new BoundingBoxD(vector3, vector4); xd3.Include(min + vectord5); xd3.Include(max + vectord5); xd4.Include(vector3 + vectord5); xd4.Include(vector4 + vectord5); if (xd3.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { if (xd4.IntersectsTriangle(ref vectord2, ref vectord3, ref vectord4)) { intersecting = true; break; } int num3 = Math.Min(Math.Abs((int)(vectori.Z - start.Z)), Math.Abs((int)(vectori2.Z - start.Z))); if (((Math.Min(Math.Abs((int)(vectori.X - start.X)), Math.Abs((int)(vectori2.X - start.X))) + Math.Min(Math.Abs((int)(vectori.Y - start.Y)), Math.Abs((int)(vectori2.Y - start.Y)))) + num3) < 3) { MyGridPathfinding.CubeId item = new MyGridPathfinding.CubeId { Grid = current, Coords = start }; m_tmpLinkCandidates.Add(item); } } } iterator.GetNext(out start); } } else { goto TR_0006; } break; } goto TR_0008; } TR_0006: if (!intersecting) { for (int i = 0; i < m_tmpLinkCandidates.Count; i++) { linkCandidatesOutput.Add(m_tmpLinkCandidates[i]); } } m_tmpLinkCandidates.Clear(); }
internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale) { int lodIndex = m_lodIndex; if (!ShouldBeThisLodVisible(camDistanceFromCenter)) { MyUtils.Swap(ref m_storedCellData, ref m_clippedCells); m_storedCellData.Clear(); return; } m_localPosition = localPosition; MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance); farPlaneDistance *= rangeScale; m_farDistance *= rangeScale; m_nearDistance *= rangeScale; m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance; if (!m_fitsInFrustum && m_lodIndex == lodIndex) return; //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix); var frustum = CameraFrustumGetter(); Vector3I min, max; // Vector3I ignoreMin, ignoreMax; var minD = m_localPosition - (double)m_farDistance; var maxD = m_localPosition + (double)m_farDistance; MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min); MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max); BoundingBoxI lodBox = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero)); bool intersects = false; //bool intersectsNear = false; m_localFarCameraBox = new BoundingBoxI(min, max); m_localNearCameraBox = new BoundingBoxI(min, max); if (lodBox.Intersects(m_localFarCameraBox)) { intersects = true; var intersection = lodBox; intersection.IntersectWith(ref m_localFarCameraBox); min = intersection.Min; max = intersection.Max; //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells //if (m_lodIndex > 1) //{ // float lowerFar, lowerNear; // MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear); // var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2); // var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2); // MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin); // MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax); // m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax); // if (lodBox.Intersects(m_localNearCameraBox)) // intersectsNear = false; //} } //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping) // return; //m_lastMin = min; //m_lastMax = max; //LodLevel parentLod, childLod; //GetNearbyLodLevels(out parentLod, out childLod); // Moves cells which are still needed from one collection to another. // All that is left behind is unloaded as no longer needed. // Move everything in range to collection of next stored cells. if (frustumCulling) { MyUtils.Swap(ref m_storedCellData, ref m_clippedCells); m_storedCellData.Clear(); } if (intersects) { float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex); MyCellCoord cell = new MyCellCoord(lodIndex, ref min); for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out cell.CoordInLod)) { //if (intersectsNear && // m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains) // continue; //if (frustumCulling) //{ // Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix); // Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix); // if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint) // { // m_outsideCells.Add(cell.CoordInLod); // continue; // } //} UnclipCell(collector, cell, true); } //cache cells around frustum if (collector.SentRequestsEmpty) { foreach (var outsideCell in m_outsideCells) { cell.CoordInLod = outsideCell; UnclipCell(collector, cell, frustumCulling); } } m_outsideCells.Clear(); } }
private void LoadBlocks(GridSimulationData simData) { simData.BlockCount = m_grid.GetBlocks().Count; simData.All.Clear(); simData.DynamicBlocks.Clear(); simData.StaticBlocks.Clear(); using (Stats.Timing.Measure("SI - Collect", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag)) { // Store blocks foreach (var block in m_grid.GetBlocks()) { if (simData.All.ContainsKey(block.Position)) { Debug.Fail("Same blocks in grid!"); continue; } bool isStatic = m_grid.Physics.Shape.BlocksConnectedToWorld.Contains(block.Position); if (isStatic) { var n = new Node(block.Position, true); n.PhysicalMaterial = block.BlockDefinition.PhysicalMaterial; simData.StaticBlocks.Add(n); simData.All.Add(block.Position, n); } else { float mass = m_grid.Physics.Shape.GetBlockMass(block.Position); var cubeMass = MassToSI(mass); var physicalMaterial = block.BlockDefinition.PhysicalMaterial; if (block.FatBlock is MyCompoundCubeBlock) { var compBlock = block.FatBlock as MyCompoundCubeBlock; physicalMaterial = compBlock.GetBlocks().First().BlockDefinition.PhysicalMaterial; //Simulate blocks where or pieces are generated bool allAreGenerated = true; foreach (var b in compBlock.GetBlocks()) { if (!b.BlockDefinition.IsGeneratedBlock) { allAreGenerated = false; break; } } bool isGenerated = true; foreach (var b in compBlock.GetBlocks()) { if (!b.BlockDefinition.IsGeneratedBlock) { isGenerated = false; break; } else if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "Stone") { isGenerated = false; break; } else if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofTile" && allAreGenerated) { isGenerated = false; cubeMass *= 6f; break; } else if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofWood" && allAreGenerated) { isGenerated = false; cubeMass *= 3f; break; } else if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofHay" && allAreGenerated) { isGenerated = false; cubeMass *= 1.2f; break; } else { } } //we dont want to simulate these pieces.. if (isGenerated) continue; } Vector3I pos = block.Min; float volumeRecip = 1.0f / block.BlockDefinition.Size.Size; for (var it = new Vector3I_RangeIterator(ref block.Min, ref block.Max); it.IsValid(); it.GetNext(out pos)) { var node = new Node(pos, false); node.Mass = cubeMass * volumeRecip; node.PhysicalMaterial = physicalMaterial; simData.DynamicBlocks.Add(node); simData.All.Add(pos, node); } } } foreach (var block in simData.DynamicWeights) { if (simData.All.ContainsKey(block.Key)) { simData.All[block.Key].Mass += block.Value; } else { var node = new Node(block.Key, false); node.Mass = simData.DynamicWeights[block.Key]; node.IsDynamicWeight = true; simData.DynamicBlocks.Add(node); simData.All.Add(block.Key, node); } } } m_grid.Physics.ContactPointCallback -= Physics_ContactPointCallback; m_grid.Physics.ContactPointCallback += Physics_ContactPointCallback; AddNeighbours(simData); }
/// <summary> /// Checks only immediate children (any deeper would take too long). /// </summary> private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell) { if (childLod == null) return false; Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1); var childLodCell = new MyCellCoord(); childLodCell.Lod = childLod.m_lodIndex; var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod); var start = thisLodCell.CoordInLod << shiftToChild; var end = start + ((1 << shiftToChild) >> 1); Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne); Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end); childLodCell.CoordInLod = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out childLodCell.CoordInLod)) { var key = childLodCell.PackId64(); MyClipmap_CellData data; if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded) { return false; } } return true; }
/// <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(); }
private unsafe static void WriteRange( ref WriteRangeArgs args, byte defaultData, int lodIdx, Vector3I lodCoord, ref Vector3I min, ref Vector3I max) { MyOctreeNode node = new MyOctreeNode(); { MyCellCoord leaf = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord); var leafKey = leaf.PackId64(); if (args.Leaves.ContainsKey(leafKey) && leaf.Lod > 0) { args.Leaves.Remove(leafKey); var childBase = lodCoord << 1; Vector3I childOffset; MyCellCoord child = new MyCellCoord(); child.Lod = leaf.Lod - 1; var leafSize = LeafSizeInVoxels << child.Lod; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; var childCopy = child; childCopy.Lod += LeafLodCount; IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy); args.Leaves.Add(child.PackId64(), octreeLeaf); node.SetChild(i, true); node.SetData(i, octreeLeaf.GetFilteredValue()); } } else { leaf.Lod -= 1; // changes to node coord instead of leaf coord var nodeKey = leaf.PackId64(); if (!args.Nodes.TryGetValue(nodeKey, out node)) { for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) node.SetData(i, defaultData); } } } if (lodIdx <= (LeafLodCount + 1)) { MyCellCoord child = new MyCellCoord(); Vector3I childBase = lodCoord << 1; Vector3I minInLod = min >> LeafLodCount; Vector3I maxInLod = max >> LeafLodCount; Vector3I leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1); Vector3I childOffset; var rangeEnd = new Vector3I(LeafSizeInVoxels - 1); m_temporaryCache.Resize(Vector3I.Zero, rangeEnd); for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod)) continue; var childMin = child.CoordInLod << LeafLodCount; var childMax = childMin + LeafSizeInVoxels - 1; Vector3I.Max(ref childMin, ref min, out childMin); Vector3I.Min(ref childMax, ref max, out childMax); var readOffset = childMin - min; IMyOctreeLeafNode leaf; var leafKey = child.PackId64(); var startInChild = childMin - (child.CoordInLod << LeafLodCount); var endInChild = childMax - (child.CoordInLod << LeafLodCount); args.Leaves.TryGetValue(leafKey, out leaf); byte uniformValue; bool uniformLeaf; { // ensure leaf exists and is writable // the only writable leaf type is MicroOctree at this point byte childDefaultData = node.GetData(i); if (leaf == null) { var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(childDefaultData); leaf = octree; } if (leaf.ReadOnly) { MyVoxelRequestFlags flags = 0; if (startInChild != Vector3I.Zero || endInChild != rangeEnd) //if write is aligned you dont need to read (make write aligned everywhere possible) leaf.ReadRange(m_temporaryCache, args.DataType.ToFlags(),ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd, ref flags); var inCell = startInChild; for (var it2 = new Vector3I_RangeIterator(ref startInChild, ref endInChild); it2.IsValid(); it2.GetNext(out inCell)) { var read = readOffset + (inCell - startInChild); m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read)); } var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(m_temporaryCache); //TODO: Optimize the building leaf = octree; } else { leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild); } uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue); } if (!uniformLeaf) { args.Leaves[leafKey] = leaf; node.SetChild(i, true); } else { args.Leaves.Remove(leafKey); node.SetChild(i, false); } node.SetData(i, leaf.GetFilteredValue()); } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } else { MyCellCoord child = new MyCellCoord(); child.Lod = lodIdx - 2 - LeafLodCount; var childBase = lodCoord << 1; Vector3I childOffset; var minInChild = (min >> (lodIdx-1)) - childBase; var maxInChild = (max >> (lodIdx-1)) - childBase; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild)) continue; child.CoordInLod = childBase + childOffset; WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max); var childKey = child.PackId64(); var childNode = args.Nodes[childKey]; if (!childNode.HasChildren && childNode.AllDataSame()) { node.SetChild(i, false); node.SetData(i, childNode.GetData(0)); args.Nodes.Remove(childKey); } else { node.SetChild(i, true); node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter, child.Lod)); } } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } }
void IMyOctreeLeafNode.WriteRange(MyStorageData source, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max) { m_octree.WriteRange(source, m_dataType, ref readOffset, ref min, ref max); if (DEBUG_WRITES) { var tmp = new MyStorageData(); tmp.Resize(min, max); m_octree.ReadRange(tmp, m_dataType, ref Vector3I.Zero, 0, ref min, ref max); Vector3I p = Vector3I.Zero; var cacheEnd = max - min; int errorCounter = 0; for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref cacheEnd); it.IsValid(); it.GetNext(out p)) { var read = readOffset + p; if (source.Get(m_dataType, ref read) != tmp.Get(m_dataType, ref p)) ++errorCounter; } Debug.Assert(errorCounter == 0, string.Format("{0} errors writing to leaf octree.", errorCounter)); } }
public override MyProceduralCell GenerateCell(ref Vector3I id) { MyProceduralCell cell = new MyProceduralCell(id, CELL_SIZE_); int cellSeed = GetCellSeed(ref id); using (MyRandom.Instance.PushSeed(cellSeed)) { int index = 0; int subCellSize = (int)(OBJECT_SIZE_MAX * 2 / m_density); int subcells = CELL_SIZE_ / subCellSize; Vector3I subcellId = Vector3I.Zero; Vector3I max = new Vector3I(subcells - 1); for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); it.IsValid(); it.GetNext(out subcellId)) { Vector3D position = new Vector3D(MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble()); position += (Vector3D)subcellId; position *= subCellSize; position += id * CELL_SIZE_; if (!MyEntities.IsInsideWorld(position)) { continue; } MySystemItem obj = IsInsideRing(position); if (obj == null) { continue; } int minSize = OBJECT_SIZE_MIN; int maxSize = OBJECT_SIZE_MAX; if (obj.Type == SystemObjectType.BELT) { minSize = ((MySystemBeltItem)obj).RoidSize; } if (obj.Type == SystemObjectType.RING) { minSize = ((MyPlanetRingItem)obj).RoidSize; maxSize = ((MyPlanetRingItem)obj).RoidSizeMax; } var cellObject = new MyObjectSeed(cell, position, MyRandom.Instance.Next(Math.Min(maxSize, minSize), Math.Max(maxSize, minSize))); cellObject.Params.Type = MyObjectSeedType.Asteroid; cellObject.Params.Seed = MyRandom.Instance.Next(); cellObject.Params.Index = index++; cell.AddObject(cellObject); } } return(cell); }
internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod) { MyPrecalcComponent.AssertUpdateThread(); // No physics there ever was so we don't care. if (!m_bodiesInitialized) { return; } if (m_queueInvalidation) { if (m_queuedRange.Max.X < 0) { m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged); } else { var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged); m_queuedRange.Include(ref bb); } return; } ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange"); minVoxelChanged -= 1; // MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += 1; //MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCellChanged, maxCellChanged; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged); Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap; minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod; maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod; var maxCell = m_voxelMap.Size - 1; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell); maxCell >>= lod; Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap); Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen."); var rb = GetRigidBody(lod); Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen."); if (rb != null) { HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape(); Debug.Assert(shape.Base.IsValid); var numCells = (maxCellChangedVoxelMap - minCellChangedVoxelMap + 1).Size; if (numCells >= m_cellsToGenerateBuffer.Length) { m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(numCells)]; } var tmpBuffer = m_cellsToGenerateBuffer; int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); Debug.Assert(invalidCount <= tmpBuffer.Length); //if (numCells <= 8) //shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap); Debug.Assert(invalidCount <= tmpBuffer.Length); for (int i = 0; i < invalidCount; i++) { InvalidCells[lod].Add(tmpBuffer[i]); } if (RunningBatchTask[lod] == null && InvalidCells[lod].Count != 0) { MyPrecalcComponent.PhysicsWithInvalidCells.Add(this); } } if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell) { m_workTracker.CancelAll(); } else { var cell = minCellChanged; for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell)) { m_workTracker.Cancel(new MyCellCoord(lod, cell)); } } m_needsShapeUpdate = true; ProfilerShort.End(); m_voxelMap.RaisePhysicsChanged(); }
internal void GenerateAllShapes() { if (!m_bodiesInitialized) CreateRigidBodies(); var min = Vector3I.Zero; Vector3I storageSize = m_voxelMap.Size; Vector3I max = new Vector3I(0, 0, 0); max.X = storageSize.X >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max.Y = storageSize.Y >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max.Z = storageSize.Z >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS; max += min; var args = new MyPrecalcJobPhysicsPrefetch.Args { GeometryCell = new MyCellCoord(1, min), Storage = m_voxelMap.Storage, TargetPhysics = this, Tracker = m_workTracker }; for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out args.GeometryCell.CoordInLod)) { MyPrecalcJobPhysicsPrefetch.Start(args); } }
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(); }
private MySlimBlock GetBlockInMergeArea() { Vector3I minI, maxI; CalculateMergeArea(out minI, out maxI); Vector3I pos = minI; for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos)) { var block = this.CubeGrid.GetCubeBlock(pos); if (block != null) { return(block); } } return(null); }
public static void GetAllBlocksPositions(HashSet<Tuple<MySlimBlock, ushort?>> blockInCompoundIDs, HashSet<Vector3I> outPositions) { foreach (var blockInCompoundID in blockInCompoundIDs) { Vector3I cube = blockInCompoundID.Item1.Min; for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref blockInCompoundID.Item1.Min, ref blockInCompoundID.Item1.Max); it.IsValid(); it.GetNext(out cube)) { outPositions.Add(cube); } } }
protected override void Init(MyObjectBuilder_DefinitionBase ob) { base.Init(ob); var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition; Debug.Assert(ob != null); if (ob == null) return; if (objectBuilder.NoEntry || objectBuilder.Triangles == null) { NoEntry = true; } else { NoEntry = false; var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length); Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center; Vector3I minPos = - (Vector3I)(objectBuilder.Center); foreach (var triOb in objectBuilder.Triangles) { Vector3 pa = (Vector3)triOb.Points[0]; Vector3 pb = (Vector3)triOb.Points[1]; Vector3 pc = (Vector3)triOb.Points[2]; var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc); var center = (pa + pb + pc) / 3.0f; // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube Vector3 cvA = (center - pa) * 0.0001f; Vector3 cvB = (center - pb) * 0.0001f; Vector3 cvC = (center - pc) * 0.0001f; Vector3I gridPosA = Vector3I.Round(pa + cvA); Vector3I gridPosB = Vector3I.Round(pb + cvB); Vector3I gridPosC = Vector3I.Round(pc + cvC); Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA); Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB); Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC); Vector3I min, max; Vector3I.Min(ref gridPosA, ref gridPosB, out min); Vector3I.Min(ref min, ref gridPosC, out min); Vector3I.Max(ref gridPosA, ref gridPosB, out max); Vector3I.Max(ref max, ref gridPosC, out max); Vector3I pos = min; for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos)) { newMesh.RegisterTriangle(tri, ref pos); } } m_mesh = newMesh; } }
internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod) { MyPrecalcComponent.AssertUpdateThread(); // No physics there ever was so we don't care. if (!m_bodiesInitialized) return; if (m_queueInvalidation) { if (m_queuedRange.Max.X < 0) { m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged); } else { var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged); m_queuedRange.Include(ref bb); } return; } ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange"); minVoxelChanged -= 1;// MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += 1;//MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCellChanged, maxCellChanged; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged); Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap; minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod; maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod; var maxCell = m_voxelMap.Size - 1; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell); maxCell >>= lod; Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap); Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen."); var rb = GetRigidBody(lod); Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen."); if (rb != null) { HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape(); Debug.Assert(shape.Base.IsValid); var numCells = (maxCellChangedVoxelMap - minCellChangedVoxelMap + 1).Size; if (numCells >= m_cellsToGenerateBuffer.Length) { m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(numCells)]; } var tmpBuffer = m_cellsToGenerateBuffer; int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); Debug.Assert(invalidCount <= tmpBuffer.Length); //if (numCells <= 8) //shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap); Debug.Assert(invalidCount <= tmpBuffer.Length); for (int i = 0; i < invalidCount; i++) { InvalidCells[lod].Add(tmpBuffer[i]); } if (RunningBatchTask[lod] == null && InvalidCells[lod].Count != 0) { MyPrecalcComponent.PhysicsWithInvalidCells.Add(this); } } if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell) { m_workTracker.CancelAll(); } else { var cell = minCellChanged; for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell)) { m_workTracker.Cancel(new MyCellCoord(lod, cell)); } } m_needsShapeUpdate = true; ProfilerShort.End(); m_voxelMap.RaisePhysicsChanged(); }
protected override MyProceduralCell GenerateProceduralCell(ref VRageMath.Vector3I cellId) { MyProceduralCell cell = new MyProceduralCell(cellId, this.CELL_SIZE); ProfilerShort.Begin("GenerateObjectSeedsCell"); IMyModule densityFunctionFilled = GetCellDensityFunctionFilled(cell.BoundingVolume); if (densityFunctionFilled == null) { ProfilerShort.End(); return null; } IMyModule densityFunctionRemoved = GetCellDensityFunctionRemoved(cell.BoundingVolume); int cellSeed = GetCellSeed(ref cellId); var random = MyRandom.Instance; using (random.PushSeed(cellSeed)) { int index = 0; Vector3I subCellId = Vector3I.Zero; Vector3I max = new Vector3I(SUBCELLS - 1); for (var iter = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); iter.IsValid(); iter.GetNext(out subCellId)) { // there is a bug in the position calculation which can very rarely cause overlaping objects but backwards compatibility so meh Vector3D position = new Vector3D(random.NextDouble(), random.NextDouble(), random.NextDouble()); position += (Vector3D)subCellId / SUBCELL_SIZE; position += cellId; position *= CELL_SIZE; if (!MyEntities.IsInsideWorld(position)) { continue; } ProfilerShort.Begin("Density functions"); double valueRemoved = -1; if (densityFunctionRemoved != null) { valueRemoved = densityFunctionRemoved.GetValue(position.X, position.Y, position.Z); if (valueRemoved <= -1) { ProfilerShort.End(); continue; } } var valueFilled = densityFunctionFilled.GetValue(position.X, position.Y, position.Z); if (densityFunctionRemoved != null) { if (valueRemoved < valueFilled) { ProfilerShort.End(); continue; } } ProfilerShort.End(); if (valueFilled < m_objectDensity) // -1..+1 { var objectSeed = new MyObjectSeed(cell, position, GetObjectSize(random.NextDouble())); objectSeed.Params.Type = GetSeedType(random.NextDouble()); objectSeed.Params.Seed = random.Next(); objectSeed.Params.Index = index++; GenerateObject(cell, objectSeed, ref index, random, densityFunctionFilled, densityFunctionRemoved); } } } ProfilerShort.End(); return cell; }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck, bool adviceCache = false) { m_resultVerticesCounter = 0; m_resultTrianglesCounter = 0; m_edgeVertexCalcCounter++; m_temporaryVoxelsCounter++; CalcPolygCubeSize(lod, storage.Size); m_voxelStart = voxelStart; //voxelStart = voxelStart; //voxelEnd = voxelEnd; var ssize = storage.Size; m_cache.Resize(voxelStart, voxelEnd); // Load content first, check it if it contains isosurface, early exit if it doesn't. storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) return null; storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); ProfilerShort.Begin("Marching cubes"); { // Size of voxel or cell (in meters) and size of voxel map / voxel cells ComputeSizeAndOrigin(lod, storage.Size); var start = Vector3I.Zero; var end = voxelEnd - voxelStart - 3; Vector3I coord0 = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0)) { int cubeIndex = 0; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 1; if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 2; if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 4; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 8; if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 16; if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 32; if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 64; if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 128; // Cube is entirely in/out of the surface if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0) { continue; } // We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc. Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod); // Create the triangles CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0); } } ProfilerShort.End(); double numCellsHalf = 0.5f * (m_cache.Size3D.X); var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh(); for (int i = 0; i < m_resultVerticesCounter; i++) { var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size; m_resultVertices[i].Position = pos; m_resultVertices[i].PositionMorph = pos; m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal; m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material; m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient; } for (int i = 0; i < m_resultVerticesCounter; i++) { isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient); } for (int i = 0; i < m_resultTrianglesCounter; i++) { isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2); } var mIsoMesh = (MyIsoMesh)isomesh; mIsoMesh.PositionOffset = storage.Size / 2; mIsoMesh.PositionScale = storage.Size; mIsoMesh.CellStart = voxelStart; mIsoMesh.CellEnd = voxelEnd; var vertexCells = mIsoMesh.Cells.GetInternalArray(); for (int i = 0; i < mIsoMesh.VerticesCount; i++) { vertexCells[i] += vertexCellOffset; } return (MyIsoMesh)isomesh; }
protected override MyProceduralCell GenerateCellSeeds(Vector3I cellId) { if (m_loadedCells.ContainsKey(cellId)) { return(null); } var settings = MySettingsSession.Static.Settings.GeneratorSettings; if (settings.AsteroidGenerator == AsteroidGenerationMethod.VANILLA) { return(null); } MyProceduralCell cell = new MyProceduralCell(cellId, CELL_SIZE); int cellSeed = CalculateCellSeed(cellId); int index = 0; double subCellSize = OBJECT_SIZE_MAX * 1f / settings.AsteroidDensity; int subcells = (int)(CELL_SIZE / subCellSize); using (MyRandom.Instance.PushSeed(cellSeed)) { Vector3I subcellId = Vector3I.Zero; Vector3I max = new Vector3I(subcells - 1); for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); it.IsValid(); it.GetNext(out subcellId)) { Vector3D position = new Vector3D(MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble()); position += (Vector3D)subcellId; position *= subCellSize; position += ((Vector3D)cellId) * CELL_SIZE; if (!MyEntities.IsInsideWorld(position) || (settings.WorldSize >= 0 && position.Length() > settings.WorldSize)) { continue; } var ring = GetAsteroidObjectAt(position); if (ring == null) { continue; } var cellObjectSeed = new MyObjectSeed(cell, position, MyRandom.Instance.Next(ring.AsteroidSize.Min, ring.AsteroidSize.Max)); cellObjectSeed.Params.Type = VRage.Game.MyObjectSeedType.Asteroid; cellObjectSeed.Params.Seed = MyRandom.Instance.Next(); cellObjectSeed.Params.Index = index++; cellObjectSeed.Params.GeneratorSeed = m_definition.UseGeneratorSeed ? MyRandom.Instance.Next() : 0; cell.AddObject(cellObjectSeed); MyPluginLog.Debug("Adding seed"); } } return(cell); }
protected override void Init(MyObjectBuilder_DefinitionBase ob) { base.Init(ob); var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition; Debug.Assert(ob != null); if (ob == null) { return; } if (objectBuilder.NoEntry || objectBuilder.Triangles == null) { NoEntry = true; } else { NoEntry = false; var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length); Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center; Vector3I minPos = -(Vector3I)(objectBuilder.Center); foreach (var triOb in objectBuilder.Triangles) { Vector3 pa = (Vector3)triOb.Points[0]; Vector3 pb = (Vector3)triOb.Points[1]; Vector3 pc = (Vector3)triOb.Points[2]; var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc); var center = (pa + pb + pc) / 3.0f; // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube Vector3 cvA = (center - pa) * 0.0001f; Vector3 cvB = (center - pb) * 0.0001f; Vector3 cvC = (center - pc) * 0.0001f; Vector3I gridPosA = Vector3I.Round(pa + cvA); Vector3I gridPosB = Vector3I.Round(pb + cvB); Vector3I gridPosC = Vector3I.Round(pc + cvC); Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA); Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB); Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC); Vector3I min, max; Vector3I.Min(ref gridPosA, ref gridPosB, out min); Vector3I.Min(ref min, ref gridPosC, out min); Vector3I.Max(ref gridPosA, ref gridPosB, out max); Vector3I.Max(ref max, ref gridPosC, out max); Vector3I pos = min; for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos)) { newMesh.RegisterTriangle(tri, ref pos); } } m_mesh = newMesh; } }
private MySlimBlock GetBlockInMergeArea() { Vector3I minI, maxI; CalculateMergeArea(out minI, out maxI); Vector3I pos = minI; for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos)) { var block = this.CubeGrid.GetCubeBlock(pos); if (block != null) return block; } return null; }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck) { m_resultVerticesCounter = 0; m_resultTrianglesCounter = 0; m_edgeVertexCalcCounter++; m_temporaryVoxelsCounter++; CalcPolygCubeSize(lod, storage.Size); m_voxelStart = voxelStart; //voxelStart = voxelStart; //voxelEnd = voxelEnd; var ssize = storage.Size; m_cache.Resize(voxelStart, voxelEnd); // Load content first, check it if it contains isosurface, early exit if it doesn't. storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd); if (!m_cache.ContainsIsoSurface()) { return(null); } storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd); ProfilerShort.Begin("Marching cubes"); { // Size of voxel or cell (in meters) and size of voxel map / voxel cells ComputeSizeAndOrigin(lod, storage.Size); var start = Vector3I.Zero; var end = voxelEnd - voxelStart - 3; Vector3I coord0 = start; for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0)) { int cubeIndex = 0; if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 1; } if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 2; } if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 4; } if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 8; } if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 16; } if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 32; } if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 64; } if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) { cubeIndex |= 128; } // Cube is entirely in/out of the surface if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0) { continue; } // We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc. Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod); // Create the triangles CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0); } } ProfilerShort.End(); double numCellsHalf = 0.5f * (m_cache.Size3D.X); var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh(); for (int i = 0; i < m_resultVerticesCounter; i++) { var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size; m_resultVertices[i].Position = pos; m_resultVertices[i].PositionMorph = pos; m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal; m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material; m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient; } for (int i = 0; i < m_resultVerticesCounter; i++) { isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient); } for (int i = 0; i < m_resultTrianglesCounter; i++) { isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2); } var mIsoMesh = (MyIsoMesh)isomesh; mIsoMesh.PositionOffset = storage.Size / 2; mIsoMesh.PositionScale = storage.Size; mIsoMesh.CellStart = voxelStart; mIsoMesh.CellEnd = voxelEnd; var vertexCells = mIsoMesh.Cells.GetInternalArray(); for (int i = 0; i < mIsoMesh.VerticesCount; i++) { vertexCells[i] += vertexCellOffset; } return((MyIsoMesh)isomesh); }
private MyShipMergeBlock GetOtherMergeBlock() { Vector3I minI, maxI; CalculateMergeArea(out minI, out maxI); Vector3I pos = minI; for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos)) { var block = this.CubeGrid.GetCubeBlock(pos); if (block != null && block.FatBlock != null) { var mergeBlock = block.FatBlock as MyShipMergeBlock; if (mergeBlock == null) continue; Vector3I otherMinI, otherMaxI; mergeBlock.CalculateMergeArea(out otherMinI, out otherMaxI); Vector3I faceNormal = Base6Directions.GetIntVector(this.Orientation.TransformDirection(m_forward)); // Bounding box test of minI <-> maxI and otherMinI(shifted by faceNormal) <-> otherMaxI(shifted by faceNormal) otherMinI = maxI - (otherMinI + faceNormal); otherMaxI = otherMaxI + faceNormal - minI; if (otherMinI.X < 0) continue; if (otherMinI.Y < 0) continue; if (otherMinI.Z < 0) continue; if (otherMaxI.X < 0) continue; if (otherMaxI.Y < 0) continue; if (otherMaxI.Z < 0) continue; return mergeBlock; } } return null; }
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(); }
private MyShipMergeBlock GetOtherMergeBlock() { Vector3I minI, maxI; CalculateMergeArea(out minI, out maxI); Vector3I pos = minI; for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos)) { var block = this.CubeGrid.GetCubeBlock(pos); if (block != null && block.FatBlock != null) { var mergeBlock = block.FatBlock as MyShipMergeBlock; if (mergeBlock == null) { continue; } Vector3I otherMinI, otherMaxI; mergeBlock.CalculateMergeArea(out otherMinI, out otherMaxI); Vector3I faceNormal = Base6Directions.GetIntVector(this.Orientation.TransformDirection(m_forward)); // Bounding box test of minI <-> maxI and otherMinI(shifted by faceNormal) <-> otherMaxI(shifted by faceNormal) otherMinI = maxI - (otherMinI + faceNormal); otherMaxI = otherMaxI + faceNormal - minI; if (otherMinI.X < 0) { continue; } if (otherMinI.Y < 0) { continue; } if (otherMinI.Z < 0) { continue; } if (otherMaxI.X < 0) { continue; } if (otherMaxI.Y < 0) { continue; } if (otherMaxI.Z < 0) { continue; } return(mergeBlock); } } return(null); }
/// <summary> /// For debugging/testing only! This can be very slow for large storage. /// </summary> public void Voxelize(MyStorageDataTypeFlags data) { MyVoxelRequestFlags flags = 0; var cache = new MyStorageData(); cache.Resize(new Vector3I(LeafSizeInVoxels)); var leafCount = (Size / LeafSizeInVoxels); Vector3I leaf = Vector3I.Zero; var end = leafCount - 1; for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref end); it.IsValid(); it.GetNext(out leaf)) { Debug.WriteLine("Processing {0} / {1}", leaf, end); var min = leaf * LeafSizeInVoxels; var max = min + (LeafSizeInVoxels - 1); ReadRangeInternal(cache, ref Vector3I.Zero, data, 0, ref min, ref max, ref flags); WriteRangeInternal(cache, data, ref min, ref max); } OnRangeChanged(Vector3I.Zero, Size - 1, data); }