private string GetDirectionString() { var cockpit = MySession.ControlledEntity as MyCockpit; if (cockpit != null) { Quaternion cockpitOrientation; cockpit.Orientation.GetQuaternion(out cockpitOrientation); var thrustDir = Vector3I.Transform(ThrustForwardVector, Quaternion.Inverse(cockpitOrientation)); if (thrustDir.X == 1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Left)); } else if (thrustDir.X == -1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Right)); } else if (thrustDir.Y == 1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Down)); } else if (thrustDir.Y == -1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Up)); } else if (thrustDir.Z == 1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Forward)); } else if (thrustDir.Z == -1) { return(MyTexts.GetString(MySpaceTexts.Thrust_Back)); } } return(null); }
private void CopyTriangle(MyNavigationTriangle otherTri, Vector3I triPosition, ref MatrixI transform) { Vector3 newA, newB, newC; otherTri.GetTransformed(ref transform, out newA, out newB, out newC); if (MyFakes.NAVMESH_PRESUMES_DOWNWARD_GRAVITY) { Vector3 n = Vector3.Cross(newC - newA, newB - newA); n.Normalize(); if (Vector3.Dot(n, Base6Directions.GetVector(Base6Directions.Direction.Up)) < 0.7f) { return; // Slightly lower than sqrt(2)/2 = 45 deg } } Vector3I.Transform(ref triPosition, ref transform, out triPosition); // This is not an error - we need to swap C and B from the navmesh, // because they will be swapped again when the triangle is added var tri = AddTriangleInternal(newA, newC, newB); RegisterTriangleInternal(tri, ref triPosition); }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { ProfilerShort.Begin("MergeFromAnotherMesh"); m_mergeHelper.Clear(); // Save the cubes from the other mesh that are touching cubes of this mesh into a helper set. // Also put the touched cubes from this mesh into the set. foreach (var position in otherMesh.m_smallTriangleRegistry.Keys) { bool add = false; foreach (var direction in Base6Directions.IntDirections) { // CH: TODO: We query the grid so far, but in the future, we should make sure that the access is thread-safe Vector3I pos = Vector3I.Transform(position + direction, transform); if (m_cubeSet.Contains(ref pos)) // Test the transformed position... { m_mergeHelper.Add(position + direction); // ... but add the original one add = true; } } if (add) { m_mergeHelper.Add(position); } } foreach (var entry in otherMesh.m_smallTriangleRegistry) { Vector3I originalCube = entry.Key; Vector3I tformedCube; Vector3I.Transform(ref originalCube, ref transform, out tformedCube); // If the cube is one of the touching cubes, we have to intersect the touching triangles if (m_mergeHelper.Contains(originalCube)) { // Take the touching pairs one by one and calculate triangulation of the disjoint union of the opposing faces // Remove the opposing faces from the old block // Add the triangulation to the mesh // Add the rest of the navmesh from this block to the mesh m_tmpTriangleList.Clear(); // CH: TODO. Just remove the triangles now foreach (var direction in Base6Directions.EnumDirections) { Vector3I directionVec = Base6Directions.GetIntVector((int)direction); Base6Directions.Direction tformedDirection = transform.GetDirection(direction); Vector3I tformedFlippedVec = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(tformedDirection)); // Remove face triangles from this mesh if (m_mergeHelper.Contains(originalCube + directionVec)) { List <int> triList = null; if (m_smallTriangleRegistry.TryGetValue(tformedCube - tformedFlippedVec, out triList)) { foreach (var index in triList) { var triangle = GetTriangle(index); // CH: TODO: This will probably be expensive. Could we precalculate it? if (IsFaceTriangle(triangle, tformedCube - tformedFlippedVec, tformedFlippedVec)) { m_tmpTriangleList.Add(new KeyValuePair <MyNavigationTriangle, Vector3I>(triangle, tformedCube - tformedFlippedVec)); } } } } } foreach (var triangle in m_tmpTriangleList) { RemoveTriangle(triangle.Key, triangle.Value); } m_tmpTriangleList.Clear(); int debugCounter = 0; // CH: TODO: optimize this (actually whole this method) foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); Vector3I pos = entry.Key; bool addTriangle = true; foreach (var direction in Base6Directions.EnumDirections) { Vector3I dirvec = Base6Directions.GetIntVector((int)direction); if (m_mergeHelper.Contains(pos + dirvec) && IsFaceTriangle(triangle, pos, dirvec)) { addTriangle = false; break; } } if (addTriangle) { if (debugCounter == 5) { } CopyTriangle(triangle, pos, ref transform); debugCounter++; } } } // Otherwise, we just transform the triangles from the other mesh and add them to this mesh else { foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); CopyTriangle(triangle, entry.Key, ref transform); //if (triangleIndex > 1) break; } } } m_mergeHelper.Clear(); ProfilerShort.End(); }
/// <summary> /// Check if other block can be added to area of multiblock. /// </summary> public bool CanAddBlock(ref Vector3I otherGridPositionMin, ref Vector3I otherGridPositionMax, MyBlockOrientation otherOrientation, MyCubeBlockDefinition otherDefinition) { MatrixI transform; if (!GetTransform(out transform)) { return(true); } try { // Calculate other block position in multiblock space. MatrixI invTransform; MatrixI.Invert(ref transform, out invTransform); Vector3I otherPositionInMultiBlockMinTmp = Vector3I.Transform(otherGridPositionMin, ref invTransform); Vector3I otherPositionInMultiBlockMaxTmp = Vector3I.Transform(otherGridPositionMax, ref invTransform); Vector3I otherPositionInMultiBlockMin = Vector3I.Min(otherPositionInMultiBlockMinTmp, otherPositionInMultiBlockMaxTmp); Vector3I otherPositionInMultiBlockMax = Vector3I.Max(otherPositionInMultiBlockMinTmp, otherPositionInMultiBlockMaxTmp); // Check intersection with AABB of whole multiblock if (!Vector3I.BoxIntersects(ref MultiBlockDefinition.Min, ref MultiBlockDefinition.Max, ref otherPositionInMultiBlockMin, ref otherPositionInMultiBlockMax)) { return(true); } // Other block rotation in multiblock space. MatrixI otherRotation = new MatrixI(otherOrientation); MatrixI otherRotationInMultiBlock; MatrixI.Multiply(ref otherRotation, ref invTransform, out otherRotationInMultiBlock); MyBlockOrientation otherOrientationInMultiBlock = new MyBlockOrientation(otherRotationInMultiBlock.Forward, otherRotationInMultiBlock.Up); // Multiblock part (block) definitions in the same position. m_tmpPartDefinitions.Clear(); foreach (var partDefinition in MultiBlockDefinition.BlockDefinitions) { if (Vector3I.BoxIntersects(ref partDefinition.Min, ref partDefinition.Max, ref otherPositionInMultiBlockMin, ref otherPositionInMultiBlockMax)) { if (otherPositionInMultiBlockMin == otherPositionInMultiBlockMax && partDefinition.Min == partDefinition.Max) // Size = 1 { m_tmpPartDefinitions.Add(partDefinition); } else { return(false); } } } if (m_tmpPartDefinitions.Count == 0) { return(true); } // Check if multiblock part blocks and other block can be added together bool canAdd = true; foreach (var partDefinition in m_tmpPartDefinitions) { MyCubeBlockDefinition blockDefinition; if (MyDefinitionManager.Static.TryGetCubeBlockDefinition(partDefinition.Id, out blockDefinition) && blockDefinition != null) { canAdd &= MyCompoundCubeBlock.CanAddBlocks(blockDefinition, new MyBlockOrientation(partDefinition.Forward, partDefinition.Up), otherDefinition, otherOrientationInMultiBlock); if (!canAdd) { break; } } } return(canAdd); } finally { m_tmpPartDefinitions.Clear(); } }
private static bool IntersectsInternalExpensive(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional) { using (partA.LockSharedUsing()) using (partB.LockSharedUsing()) { var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA); var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB); var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partA.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA))); } } var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partB.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB))); } } // Reserved spaces intersect? if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll)) { if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2)))) { return(true); } } var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA); var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB); // Block spaces intersect with reserved space? if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll)) { foreach (var aabb in reservedA) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockBAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockBAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partB.CubeExists(Vector3I.Transform(vi.Current, invTransformB))) { return(true); } } } } if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll)) { foreach (var aabb in reservedB) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockAAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockAAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partA.CubeExists(Vector3I.Transform(vi.Current, invTransformA))) { return(true); } } } } // Block space intersects with block space? if (!blockAAll.Intersects(blockBAll)) { return(false); } if (partA.m_blocks.Count < partB.m_blocks.Count) { foreach (var pos in partA.m_blocks.Keys) { if (partB.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformA), ref invTransformB))) { return(true); } } } else { foreach (var pos in partB.m_blocks.Keys) { if (partA.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformB), ref invTransformA))) { return(true); } } } return(false); } }
private MyCubeGrid DetectTouchingGrid(MySlimBlock block) { MyCubeGrid grid2; if (MyCubeBuilder.Static.DynamicMode) { return(null); } if (block == null) { return(null); } if (block.FatBlock is MyCompoundCubeBlock) { using (List <MySlimBlock> .Enumerator enumerator = (block.FatBlock as MyCompoundCubeBlock).GetBlocks().GetEnumerator()) { while (true) { if (enumerator.MoveNext()) { MySlimBlock current = enumerator.Current; MyCubeGrid grid = this.DetectTouchingGrid(current); if (grid == null) { continue; } grid2 = grid; } else { return(null); } break; } return(grid2); } } else { BoundingBoxD xd; block.GetWorldBoundingBox(out xd, false); xd.Inflate((double)(block.CubeGrid.GridSize / 2f)); m_tmpNearEntities.Clear(); Sandbox.Game.Entities.MyEntities.GetElementsInBox(ref xd, m_tmpNearEntities); MyCubeBlockDefinition.MountPoint[] buildProgressModelMountPoints = block.BlockDefinition.GetBuildProgressModelMountPoints(block.BuildLevelRatio); try { int num2 = 0; while (true) { if (num2 >= m_tmpNearEntities.Count) { break; } MyCubeGrid objA = m_tmpNearEntities[num2] as MyCubeGrid; if (((objA != null) && (!ReferenceEquals(objA, block.CubeGrid) && ((objA.Physics != null) && (objA.Physics.Enabled && objA.IsStatic)))) && (objA.GridSizeEnum == block.CubeGrid.GridSizeEnum)) { Vector3I gridOffset = objA.WorldToGridInteger(base.m_pastePosition); if (objA.CanMergeCubes(block.CubeGrid, gridOffset)) { Quaternion quaternion; MatrixI transformation = objA.CalculateMergeTransform(block.CubeGrid, gridOffset); new MyBlockOrientation(transformation.GetDirection(block.Orientation.Forward), transformation.GetDirection(block.Orientation.Up)).GetQuaternion(out quaternion); Vector3I position = Vector3I.Transform(block.Position, transformation); if (MyCubeGrid.CheckConnectivity(objA, block.BlockDefinition, buildProgressModelMountPoints, ref quaternion, ref position)) { return(objA); } } } num2++; } } finally { m_tmpNearEntities.Clear(); } return(null); } return(grid2); }
private static void GetMultiMatches(IReadOnlyList <PartMountPointBlock> mine, IReadOnlyList <PartMountPointBlock> other, HashSet <MatrixI> cache) { cache.Clear(); var match = Math.Min(mine.Count, other.Count); if (match == mine.Count) { foreach (var ot in other) { mine[0].GetTransforms(ot, cache); } MatrixI inv; cache.RemoveWhere(x => { MatrixI.Invert(ref x, out inv); for (var i = 1; i < mine.Count; i++) { var loc = Vector3I.Transform(mine[i].MountLocation, ref inv); var contains = false; foreach (var y in other) { var opposLoc = y.AnchorLocation; if (opposLoc != loc) { continue; } contains = true; break; } if (!contains) { return(true); } } return(false); }); } else { foreach (var mi in mine) { mi.GetTransforms(other[0], cache); } cache.RemoveWhere(x => { for (var i = 1; i < other.Count; i++) { var loc = Vector3I.Transform(other[i].MountLocation, ref x); var contains = false; foreach (var y in mine) { var opposLoc = y.AnchorLocation; if (opposLoc != loc) { continue; } contains = true; break; } if (!contains) { return(true); } } return(false); }); } }
public Vector3I GridToPrefab(Vector3I gridPos) { return(Vector3I.Transform(gridPos, ref m_invTransform)); }
private MyCubeGrid DetectTouchingGrid(MySlimBlock block) { if (MyCubeBuilder.Static.DynamicMode) { return(null); } if (block == null) { return(null); } if (block.FatBlock is MyCompoundCubeBlock) { foreach (var blockInCompound in (block.FatBlock as MyCompoundCubeBlock).GetBlocks()) { MyCubeGrid touchingGrid = DetectTouchingGrid(blockInCompound); if (touchingGrid != null) { return(touchingGrid); } } return(null); } ProfilerShort.Begin("MultiBlockClipboard: DetectMerge"); float gridSize = block.CubeGrid.GridSize; BoundingBoxD aabb; block.GetWorldBoundingBox(out aabb); // Inflate by half cube, so it will intersect for sure when there's anything aabb.Inflate(gridSize / 2); m_tmpNearEntities.Clear(); MyEntities.GetElementsInBox(ref aabb, m_tmpNearEntities); var mountPoints = block.BlockDefinition.GetBuildProgressModelMountPoints(block.BuildLevelRatio); try { for (int i = 0; i < m_tmpNearEntities.Count; i++) { var grid = m_tmpNearEntities[i] as MyCubeGrid; if (grid != null && grid != block.CubeGrid && grid.Physics != null && grid.Physics.Enabled && grid.IsStatic && grid.GridSizeEnum == block.CubeGrid.GridSizeEnum) { Vector3I gridOffset = grid.WorldToGridInteger(m_pastePosition); if (!grid.CanMergeCubes(block.CubeGrid, gridOffset)) { continue; } MatrixI transform = grid.CalculateMergeTransform(block.CubeGrid, gridOffset); Base6Directions.Direction forward = transform.GetDirection(block.Orientation.Forward); Base6Directions.Direction up = transform.GetDirection(block.Orientation.Up); MyBlockOrientation newOrientation = new MyBlockOrientation(forward, up); Quaternion newRotation; newOrientation.GetQuaternion(out newRotation); Vector3I newPosition = Vector3I.Transform(block.Position, transform); if (!MyCubeGrid.CheckConnectivity(grid, block.BlockDefinition, mountPoints, ref newRotation, ref newPosition)) { continue; } return(grid); } } } finally { m_tmpNearEntities.Clear(); ProfilerShort.End(); } return(null); }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { int num; m_mergeHelper.Clear(); foreach (Vector3I vectori in otherMesh.m_smallTriangleRegistry.Keys) { bool flag = false; Vector3I[] intDirections = Base6Directions.IntDirections; num = 0; while (true) { if (num >= intDirections.Length) { if (flag) { m_mergeHelper.Add(vectori); } break; } Vector3I vectori2 = intDirections[num]; Vector3I position = Vector3I.Transform((Vector3I)(vectori + vectori2), (MatrixI)transform); if (this.m_cubeSet.Contains(ref position)) { m_mergeHelper.Add(vectori + vectori2); flag = true; } num++; } } using (Dictionary <Vector3I, List <int> > .Enumerator enumerator2 = otherMesh.m_smallTriangleRegistry.GetEnumerator()) { while (true) { while (true) { if (enumerator2.MoveNext()) { Vector3I vectori5; KeyValuePair <Vector3I, List <int> > current = enumerator2.Current; Vector3I key = current.Key; Vector3I.Transform(ref key, ref transform, out vectori5); if (m_mergeHelper.Contains(key)) { m_tmpTriangleList.Clear(); Base6Directions.Direction[] enumDirections = Base6Directions.EnumDirections; num = 0; while (true) { if (num < enumDirections.Length) { Base6Directions.Direction direction = enumDirections[num]; Vector3I intVector = Base6Directions.GetIntVector((int)direction); Vector3I vectori7 = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(transform.GetDirection(direction))); if (m_mergeHelper.Contains(key + intVector)) { List <int> list = null; if (this.m_smallTriangleRegistry.TryGetValue(vectori5 - vectori7, out list)) { foreach (int num3 in list) { MyNavigationTriangle triangle = base.GetTriangle(num3); if (this.IsFaceTriangle(triangle, vectori5 - vectori7, vectori7)) { m_tmpTriangleList.Add(new KeyValuePair <MyNavigationTriangle, Vector3I>(triangle, vectori5 - vectori7)); } } } } num++; continue; } foreach (KeyValuePair <MyNavigationTriangle, Vector3I> pair2 in m_tmpTriangleList) { this.RemoveTriangle(pair2.Key, pair2.Value); } m_tmpTriangleList.Clear(); int num2 = 0; foreach (int num4 in current.Value) { MyNavigationTriangle triangle = otherMesh.GetTriangle(num4); Vector3I cubePosition = current.Key; bool flag2 = true; enumDirections = Base6Directions.EnumDirections; num = 0; while (true) { if (num < enumDirections.Length) { Vector3I intVector = Base6Directions.GetIntVector((int)enumDirections[num]); if (!m_mergeHelper.Contains(cubePosition + intVector) || !this.IsFaceTriangle(triangle, cubePosition, intVector)) { num++; continue; } flag2 = false; } if (flag2) { int num6 = num2; this.CopyTriangle(triangle, cubePosition, ref transform); num2++; } break; } } } } foreach (int num5 in current.Value) { MyNavigationTriangle triangle = otherMesh.GetTriangle(num5); this.CopyTriangle(triangle, current.Key, ref transform); } } else { goto TR_0000; } } } } TR_0000: m_mergeHelper.Clear(); }
public override bool Invoke(ulong steamId, long playerId, string messageText) { if (messageText.StartsWith("/rotateroid ", StringComparison.InvariantCultureIgnoreCase)) { var match = Regex.Match(messageText, @"/rotateroid\s{1,}(?<Key>.+){1,}\s{1,}(?<X>[+-]?((\d+(\.\d*)?)|(\.\d+)))\s{1,}(?<Y>[+-]?((\d+(\.\d*)?)|(\.\d+)))\s{1,}(?<Z>[+-]?((\d+(\.\d*)?)|(\.\d+)))", RegexOptions.IgnoreCase); if (match.Success) { var rotateVector = new Vector3( double.Parse(match.Groups["X"].Value, CultureInfo.InvariantCulture), double.Parse(match.Groups["Y"].Value, CultureInfo.InvariantCulture), double.Parse(match.Groups["Z"].Value, CultureInfo.InvariantCulture)); var searchName = match.Groups["Key"].Value; var currentAsteroidList = new List <IMyVoxelBase>(); IMyVoxelBase originalAsteroid = null; MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(searchName, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count == 1) { originalAsteroid = currentAsteroidList[0]; } else { MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.IndexOf(searchName, StringComparison.InvariantCultureIgnoreCase) >= 0); if (currentAsteroidList.Count == 1) { originalAsteroid = currentAsteroidList[0]; } } List <IMyVoxelBase> asteroidCache = CommandAsteroidsList.GetAsteroidCache(steamId); int index; if (searchName.Substring(0, 1) == "#" && Int32.TryParse(searchName.Substring(1), out index) && index > 0 && index <= asteroidCache.Count) { originalAsteroid = asteroidCache[index - 1]; } if (originalAsteroid == null) { MyAPIGateway.Utilities.SendMessage(steamId, "Cannot find asteroid", string.Format("'{0}'", searchName)); return(true); } var quaternion = Quaternion.CreateFromYawPitchRoll(rotateVector.X / (180 / MathHelper.Pi), rotateVector.Y / (180 / MathHelper.Pi), rotateVector.Z / (180 / MathHelper.Pi)); var oldStorage = originalAsteroid.Storage; var oldCache = new MyStorageData(); oldCache.Resize(oldStorage.Size); oldStorage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, Vector3I.Zero, oldStorage.Size - 1); var transSize = Vector3I.Transform(oldStorage.Size, quaternion); var newSize = Vector3I.Abs(transSize); var newName = Support.CreateUniqueStorageName(originalAsteroid.StorageName); var newVoxelMap = Support.CreateNewAsteroid(newName, newSize, originalAsteroid.PositionLeftBottomCorner); var cache = new MyStorageData(); var min = Vector3I.Zero; var max = newSize - 1; cache.Resize(min, max); Vector3I p; for (p.Z = 0; p.Z < oldStorage.Size.Z; ++p.Z) { for (p.Y = 0; p.Y < oldStorage.Size.Y; ++p.Y) { for (p.X = 0; p.X < oldStorage.Size.X; ++p.X) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); var newP = Vector3I.Transform(p, quaternion); // readjust the points, as rotation occurs arround 0,0,0. newP.X = newP.X < 0 ? newP.X - transSize.X - 1 : newP.X; newP.Y = newP.Y < 0 ? newP.Y - transSize.Y - 1 : newP.Y; newP.Z = newP.Z < 0 ? newP.Z - transSize.Z - 1 : newP.Z; cache.Content(ref newP, content); cache.Material(ref newP, material); } } } newVoxelMap.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); MyAPIGateway.Entities.RemoveEntity((IMyEntity)originalAsteroid); // Invalidate the cache, to force user to select again to prevent possible corruption by using an old cache. asteroidCache.Clear(); return(true); } } return(false); }
public bool CanAddBlock(ref Vector3I otherGridPositionMin, ref Vector3I otherGridPositionMax, MyBlockOrientation otherOrientation, MyCubeBlockDefinition otherDefinition) { MatrixI xi; bool flag2; if (!this.GetTransform(out xi)) { return(true); } try { MatrixI xi2; MatrixI.Invert(ref xi, out xi2); Vector3I vectori1 = Vector3I.Transform(otherGridPositionMin, ref xi2); Vector3I vectori = Vector3I.Transform(otherGridPositionMax, ref xi2); Vector3I minB = Vector3I.Min(vectori1, vectori); Vector3I maxB = Vector3I.Max(vectori1, vectori); if (Vector3I.BoxIntersects(ref this.MultiBlockDefinition.Min, ref this.MultiBlockDefinition.Max, ref minB, ref maxB)) { MatrixI xi4; MatrixI leftMatrix = new MatrixI(otherOrientation); MatrixI.Multiply(ref leftMatrix, ref xi2, out xi4); MyBlockOrientation orientation = new MyBlockOrientation(xi4.Forward, xi4.Up); m_tmpPartDefinitions.Clear(); MyMultiBlockDefinition.MyMultiBlockPartDefinition[] blockDefinitions = this.MultiBlockDefinition.BlockDefinitions; int index = 0; while (true) { if (index < blockDefinitions.Length) { MyMultiBlockDefinition.MyMultiBlockPartDefinition item = blockDefinitions[index]; if (Vector3I.BoxIntersects(ref item.Min, ref item.Max, ref minB, ref maxB)) { if (!(minB == maxB)) { break; } if (!(item.Min == item.Max)) { break; } m_tmpPartDefinitions.Add(item); } index++; continue; } if (m_tmpPartDefinitions.Count == 0) { flag2 = true; } else { bool flag = true; foreach (MyMultiBlockDefinition.MyMultiBlockPartDefinition definition2 in m_tmpPartDefinitions) { MyCubeBlockDefinition definition3; if (!MyDefinitionManager.Static.TryGetCubeBlockDefinition(definition2.Id, out definition3)) { continue; } if (definition3 != null) { flag &= MyCompoundCubeBlock.CanAddBlocks(definition3, new MyBlockOrientation(definition2.Forward, definition2.Up), otherDefinition, orientation); if (!flag) { break; } } } flag2 = flag; } return(flag2); } flag2 = false; } else { flag2 = true; } } finally { m_tmpPartDefinitions.Clear(); } return(flag2); }
static bool CanMergeCubes(IMyCubeBlock padA, IMyCubeBlock padB, Vector3I gridOffset, List <IMySlimBlock> blocksOverlapping, List <IMySlimBlock> weldPadsOverlapping) { blocksOverlapping.Clear(); try { IMyCubeGrid gridA = padA.CubeGrid; IMyCubeGrid gridB = padB.CubeGrid; MyCubeGrid internalGridB = (MyCubeGrid)gridB; MatrixI transform = gridA.CalculateMergeTransform(gridB, gridOffset); bool result = true; // check gridToMerge's blocks against grid's blocks foreach (IMySlimBlock slimGridB in internalGridB.GetBlocks()) // get blocks without intermediary lists { if (slimGridB.FatBlock == padB) { continue; } // ignore all pads //if(IsWeldPad(slimGridB.BlockDefinition.Id)) // continue; Vector3I pos = Vector3I.Transform(slimGridB.Position, transform); IMySlimBlock slimGridA = gridA.GetCubeBlock(pos); if (slimGridA != null) { if (slimGridA.FatBlock == padA) { continue; } // ignore all pads //if(IsWeldPad(slimGridA.BlockDefinition.Id)) // continue; //MyAPIGateway.Utilities.ShowNotification($"{(master ? "master" : "slavetest")} :: {slimGrid1.BlockDefinition.ToString()} OVERLAPS {slimGrid2.BlockDefinition.ToString()}", 16); //DebugDraw(slimGrid1.CubeGrid, slimGrid1.Min, slimGrid1.Max, Color.Red, master); //DebugDraw(slimGrid2.CubeGrid, slimGrid2.Min, slimGrid2.Max, Color.Yellow, master); //result = false; //continue; bool isWeldPadA = (slimGridA?.FatBlock?.GameLogic?.GetAs <WeldPad>() != null); bool isWeldPadB = (slimGridB?.FatBlock?.GameLogic?.GetAs <WeldPad>() != null); if (isWeldPadA || isWeldPadB) { if (isWeldPadA) { weldPadsOverlapping.Add(slimGridA); } if (isWeldPadB) { weldPadsOverlapping.Add(slimGridB); } } else { blocksOverlapping.Add(slimGridA); blocksOverlapping.Add(slimGridB); result = false; } // allow more blocks to be found } //DebugDraw(grid1, pos, pos, Color.Blue, master); } return(result); } catch (Exception e) { Log.Error(e); } return(false); }
public Vector3I PrefabToGrid(Vector3I prefabPos) { return(Vector3I.Transform(prefabPos, ref m_transform)); }
public static SerializableVector3UByte Transform(this SerializableVector3UByte value, Quaternion rotation) { var vector = Vector3I.Transform(new Vector3I(value.X - 127, value.Y - 127, value.Z - 127), rotation); return(new SerializableVector3UByte((byte)(vector.X + 127), (byte)(vector.Y + 127), (byte)(vector.Z + 127))); }
public void RotateAsteroid(Quaternion quaternion) { var sourceFile = SourceVoxelFilepath ?? VoxelFilepath; var asteroid = new MyVoxelMap(); asteroid.Load(sourceFile); var newAsteroid = new MyVoxelMap(); var newSize = asteroid.Size; newAsteroid.Create(newSize, SpaceEngineersCore.Resources.GetDefaultMaterialIndex()); Vector3I block; var halfSize = asteroid.Storage.Size / 2; // Don't use anything smaller than 64 for smaller voxels, as it trashes the cache. var cacheSize = new Vector3I(64); var halfCacheSize = new Vector3I(32); // This should only be used for the Transform, not the cache. // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue. for (block.Z = 0; block.Z < asteroid.Storage.Size.Z; block.Z += 64) { for (block.Y = 0; block.Y < asteroid.Storage.Size.Y; block.Y += 64) { for (block.X = 0; block.X < asteroid.Storage.Size.X; block.X += 64) { #region source voxel var cache = new MyStorageData(); cache.Resize(cacheSize); // LOD1 is not detailed enough for content information on asteroids. asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); #endregion #region target Voxel // the block is a cubiod. The entire space needs to rotate, to be able to gauge where the new block position starts from. var newBlockMin = Vector3I.Transform(block - halfSize, quaternion) + halfSize; var newBlockMax = Vector3I.Transform(block + 64 - halfSize, quaternion) + halfSize; var newBlock = Vector3I.Min(newBlockMin, newBlockMax); var newCache = new MyStorageData(); newCache.Resize(cacheSize); newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1); #endregion bool changed = false; Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) { for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) { for (p.X = 0; p.X < cacheSize.X; ++p.X) { byte volume = cache.Content(ref p); byte cellMaterial = cache.Material(ref p); var newP1 = Vector3I.Transform(p - halfCacheSize, quaternion) + halfCacheSize; var newP2 = Vector3I.Transform(p + 1 - halfCacheSize, quaternion) + halfCacheSize; var newP = Vector3I.Min(newP1, newP2); newCache.Content(ref newP, volume); newCache.Material(ref newP, cellMaterial); changed = true; } } } if (changed) { newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1); } } } } var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); newAsteroid.Save(tempfilename); SourceVoxelFilepath = tempfilename; }
public override void Remap(MyObjectBuilder_CubeGrid grid) { var transformCopy = LocalTransform; var minToMin = new Dictionary <Vector3I, Vector3I>(grid.CubeBlocks.Count * 3 / 2); foreach (var x in grid.CubeBlocks) { var orig = (Vector3I)x.Min; var cMin = orig; Vector3I cMax; BlockTransformations.ComputeBlockMax(x, out cMax); x.BlockOrientation.Forward = LocalTransform.GetDirection(x.BlockOrientation.Forward); x.BlockOrientation.Up = LocalTransform.GetDirection(x.BlockOrientation.Up); Vector3I.Transform(ref cMin, ref transformCopy, out cMin); Vector3I.Transform(ref cMax, ref transformCopy, out cMax); minToMin[orig] = x.Min = Vector3I.Min(cMin, cMax); var proj = x as MyObjectBuilder_ProjectorBase; // Don't have to update the rotation; it is bound to the world matrix of the projector. if (proj != null) { Vector3I.TransformNormal(ref proj.ProjectionOffset, ref transformCopy, out proj.ProjectionOffset); } } if (grid.BlockGroups != null) { foreach (var g in grid.BlockGroups) { for (var i = 0; i < g.Blocks.Count; i++) { Vector3I tmpOut; if (minToMin.TryGetValue(g.Blocks[i], out tmpOut)) { g.Blocks[i] = tmpOut; } else { g.Blocks[i] = Vector3I.MaxValue; // sorta discards it? } } } } if (grid.ConveyorLines != null) { foreach (var l in grid.ConveyorLines) { l.StartDirection = LocalTransform.GetDirection(l.StartDirection); l.StartPosition = Vector3I.Transform(l.StartPosition, ref transformCopy); l.EndDirection = LocalTransform.GetDirection(l.EndDirection); l.EndPosition = Vector3I.Transform(l.EndPosition, ref transformCopy); if (l.Sections == null) { continue; } for (var s = 0; s < l.Sections.Count; s++) { l.Sections[s] = new SerializableLineSectionInformation() { Direction = LocalTransform.GetDirection(l.Sections[s].Direction), Length = l.Sections[s].Length } } ; } } }