/// <summary> /// Gets all cubes which are affected by bone. /// </summary> /// <param name="onlyExisting">Returns only cubes which were added to skeleton.</param> public void GetAffectedCubes(Vector3I cube, Vector3I boneOffset, List <Vector3I> resultList, MyCubeGrid grid) { Debug.Assert(BoneDensity == 2, "This algorithm requires BoneDensity to be 2"); Vector3I dist = boneOffset - Vector3I.One; Vector3I sign = Vector3I.Sign(dist); dist *= sign; Vector3I offset; for (offset.X = 0; offset.X <= dist.X; offset.X++) { for (offset.Y = 0; offset.Y <= dist.Y; offset.Y++) { for (offset.Z = 0; offset.Z <= dist.Z; offset.Z++) { var targetCube = cube + offset * sign; if (grid.CubeExists(targetCube)) { resultList.Add(targetCube); } } } } }
public static void ComputeSteps(Vector3I start, Vector3I end, Vector3I rotatedSize, out Vector3I stepDelta, out Vector3I counter, out int stepCount) { var offset = end - start; stepDelta = Vector3I.Sign(offset) * rotatedSize; counter = Vector3I.Abs(end - start) / rotatedSize + Vector3I.One; stepCount = counter.Size; }
public static void ComputeSteps(Vector3I start, Vector3I end, Vector3I rotatedSize, out Vector3I stepDelta, out Vector3I counter, out int stepCount) { Vector3I vectori = end - start; stepDelta = Vector3I.Sign(vectori) * rotatedSize; counter = (Vector3I)((Vector3I.Abs(end - start) / rotatedSize) + Vector3I.One); stepCount = counter.Size; }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool result = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix); Vector3D intersectionPos; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv); Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv)); RayD r = new RayD(rayStart, rayDir); for (int i = 0; i < 100; ++i) // Limit iterations to 100 { var cubeBb = GetCubeBoundingBox(addPos); if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains) { break; } double?dist = cubeBb.Intersects(r); if (!dist.HasValue) { break; } removePos = addPos; intersectionPos = rayStart + rayDir * dist.Value; Vector3 center = removePos * CurrentGrid.GridSize; Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center)); addPos = removePos + dirInt; addDir = dirInt; result = true; if (!CurrentGrid.CubeExists(addPos)) { break; } } Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero"); return(result); }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool flag = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldMatrixInvScaled = this.CurrentGrid.PositionComp.WorldMatrixInvScaled; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D position = Vector3D.Transform(IntersectionStart, worldMatrixInvScaled); Vector3D direction = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldMatrixInvScaled)); RayD ray = new RayD(position, direction); int num = 0; while (true) { if (num < 100) { BoundingBoxD cubeBoundingBox = this.GetCubeBoundingBox(addPos); if (placingSmallGridOnLargeStatic || (cubeBoundingBox.Contains(position) != ContainmentType.Contains)) { double?nullable = cubeBoundingBox.Intersects(ray); if (nullable != null) { removePos = addPos; Vector3I vectori = Vector3I.Sign(Vector3.DominantAxisProjection((Vector3)((position + (direction * nullable.Value)) - (removePos * this.CurrentGrid.GridSize)))); addPos = (Vector3I)(removePos + vectori); addDir = vectori; if (this.CurrentGrid.CubeExists(addPos)) { num++; continue; } flag = true; } } } return(flag); } }
// Math magic by Whiplash internal static void BresenhamLineDraw(Vector3I start, Vector3I end, List <Vector3I> points) { points.Clear(); points.Add(start); Vector3I delta = end - start; Vector3I step = Vector3I.Sign(delta); delta *= step; int max = delta.AbsMax(); if (max == delta.X) { int p1 = 2 * delta.Y - delta.X; int p2 = 2 * delta.Z - delta.X; while (start.X != end.X) { start.X += step.X; if (p1 >= 0) { start.Y += step.Y; p1 -= 2 * delta.X; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.X; } p1 += 2 * delta.Y; p2 += 2 * delta.Z; points.Add(start); } } else if (max == delta.Y) { int p1 = 2 * delta.X - delta.Y; int p2 = 2 * delta.Z - delta.Y; while (start.Y != end.Y) { start.Y += step.Y; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Y; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.Y; } p1 += 2 * delta.X; p2 += 2 * delta.Z; points.Add(start); } } else { int p1 = 2 * delta.X - delta.Z; int p2 = 2 * delta.Y - delta.Z; while (start.Z != end.Z) { start.Z += step.Z; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Z; } if (p2 >= 0) { start.Y += step.Y; p2 -= 2 * delta.Z; } p1 += 2 * delta.X; p2 += 2 * delta.Y; points.Add(start); } } }
internal static bool BresenhamGridIntersection(MyCubeGrid grid, ref Vector3D worldStart, ref Vector3D worldEnd, out Vector3D?hitPos, MyCubeBlock weapon = null, GridAi ai = null) { var start = grid.WorldToGridInteger(worldStart); var end = grid.WorldToGridInteger(worldEnd); Vector3I delta = end - start; Vector3I step = Vector3I.Sign(delta); delta *= step; int max = delta.AbsMax(); hitPos = null; var gMinX = grid.Min.X; var gMinY = grid.Min.Y; var gMinZ = grid.Min.Z; var gMaxX = grid.Max.X; var gMaxY = grid.Max.Y; var gMaxZ = grid.Max.Z; if (ai != null) { var dir = (worldEnd - worldStart); var ray = new RayD(ref worldStart, ref dir); var gridMatrix = ai.MyGrid.PositionComp.WorldMatrixRef; foreach (var sub in ai.SubGrids) { if (sub == grid) { continue; } var subDist = sub.PositionComp.WorldVolume.Intersects(ray); if (subDist.HasValue) { //var rotMatrix = Quaternion.CreateFromRotationMatrix(ai.MyGrid.WorldMatrix); //var obb = new MyOrientedBoundingBoxD(ai.MyGrid.PositionComp.WorldAABB.Center, ai.MyGrid.PositionComp.LocalAABB.HalfExtents, rotMatrix); var box = ai.MyGrid.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, gridMatrix); Vector3D?ignoreHit; if (obb.Intersects(ref ray) != null && BresenhamGridIntersection(sub, ref worldStart, ref worldEnd, out ignoreHit, weapon)) { return(true); } } } } if (max == delta.X) { int p1 = 2 * delta.Y - delta.X; int p2 = 2 * delta.Z - delta.X; while (start.X != end.X) { start.X += step.X; if (p1 >= 0) { start.Y += step.Y; p1 -= 2 * delta.X; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.X; } p1 += 2 * delta.Y; p2 += 2 * delta.Z; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } else if (max == delta.Y) { int p1 = 2 * delta.X - delta.Y; int p2 = 2 * delta.Z - delta.Y; while (start.Y != end.Y) { start.Y += step.Y; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Y; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.Y; } p1 += 2 * delta.X; p2 += 2 * delta.Z; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } else { int p1 = 2 * delta.X - delta.Z; int p2 = 2 * delta.Y - delta.Z; while (start.Z != end.Z) { start.Z += step.Z; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Z; } if (p2 >= 0) { start.Y += step.Y; p2 -= 2 * delta.Z; } p1 += 2 * delta.X; p2 += 2 * delta.Y; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } return(false); }
public void Init(IMyCubeBlock startBlock, IMyCubeBlock endBlock) { IMyCubeGrid cubeGrid = startBlock.CubeGrid; Vector3I start = startBlock.Position; Vector3I end = endBlock.Position; Vector3I size = (Vector3I.Max(start, end) - Vector3I.Min(start, end)) + Vector3I.One; if (size.X != 1 && size.Y != 1 && size.Z != 1) { throw new Exception("Blocks must be on a consistent plane."); } List <List <T> > rows = new List <List <T> >(); Vector3I inc = Vector3I.Sign(end - start); Vector3I v = start; end += inc; int colSize = 0; if (inc.X == 0) { for (v.Y = start.Y; v.Y != end.Y; v.Y += inc.Y) { List <T> col = new List <T>(); for (v.Z = start.Z; v.Z != end.Z; v.Z += inc.Z) { IMyCubeBlock temp = cubeGrid.GetCubeBlock(v)?.FatBlock; if (temp is T && temp.Position == v) { T b = (T)temp; int y = (v.Z - start.Z) * inc.Z; if (col.Count >= y) { col.Add(b); } else { col [y] = b; } //this.grid [coords.Y, coords.Z] = b; } } colSize = Math.Max(col.Count, colSize); int x = (v.Y - start.Y) * inc.Y; if (rows.Count >= x) { rows.Add(col); } else { rows [x] = col; } } } else if (inc.Y == 0) { for (v.X = start.X; v.X != end.X; v.X += inc.X) { List <T> col = new List <T>(); for (v.Z = start.Z; v.Z != end.Z; v.Z += inc.Z) { IMyCubeBlock temp = cubeGrid.GetCubeBlock(v)?.FatBlock; if (temp is T && temp.Position == v) { T b = (T)temp; int y = (v.Z - start.Z) * inc.Z; if (col.Count >= y) { col.Add(b); } else { col [y] = b; } //Vector3I coords = (v - start) * inc; //this.grid [coords.X, coords.Z] = b; } } colSize = Math.Max(col.Count, colSize); int x = (v.X - start.X) * inc.X; if (rows.Count >= x) { rows.Add(col); } else { rows [x] = col; } } } else { for (v.X = start.X; v.X != end.X; v.X += inc.X) { List <T> col = new List <T>(); for (v.Y = start.Y; v.Y != end.Y; v.Y += inc.Y) { IMyCubeBlock temp = cubeGrid.GetCubeBlock(v)?.FatBlock; if (temp is T && temp.Position == v) { T b = (T)temp; int y = (v.Y - start.Y) * inc.Y; if (col.Count >= y) { col.Add(b); } else { col [y] = b; } //Vector3I coords = (v - start) * inc; //this.grid [coords.X, coords.Y] = b; } } colSize = Math.Max(col.Count, colSize); int x = (v.X - start.X) * inc.X; if (rows.Count >= x) { rows.Add(col); } else { rows [x] = col; } } } if (colSize == 0) { throw new Exception("No blocks found."); } grid = new T [rows.Count, colSize]; //StringBuilder sb = new StringBuilder(); for (int y = 0; y < grid.GetLength(1); y++) { for (int x = 0; x < grid.GetLength(0); x++) { List <T> col = rows [x]; if (y < col.Count) { grid [x, y] = col [y]; } //if (block == null) // sb.Append("null "); //else // sb.Append(block.CustomName).Append(' '); } //sb.AppendLine(); } //me.GetSurface(0).WriteText(sb); Size = new Vector2I(grid.GetLength(0), grid.GetLength(1)); }