private static IEnumerable<MyObjectBuilder_CubeBlock> MirrorCubes(StructureCubeGridModel viewModel, bool integrate, Mirror xMirror, int xAxis, Mirror yMirror, int yAxis, Mirror zMirror, int zAxis) { var blocks = new List<MyObjectBuilder_CubeBlock>(); SubtypeId outVal; if (xMirror == Mirror.None && yMirror == Mirror.None && zMirror == Mirror.None) return blocks; foreach (var block in viewModel.CubeGrid.CubeBlocks.Where(b => b.SubtypeName == "" || (Enum.TryParse<SubtypeId>(b.SubtypeName, out outVal) && !InvalidMirrorBlocks.Contains(outVal)))) { var newBlock = block.Clone() as MyObjectBuilder_CubeBlock; newBlock.EntityId = block.EntityId == 0 ? 0 : SpaceEngineersApi.GenerateEntityId(IDType.ENTITY); if (block is MyObjectBuilder_MotorBase) { ((MyObjectBuilder_MotorBase)newBlock).RotorEntityId = ((MyObjectBuilder_MotorBase)block).RotorEntityId == 0 ? 0 : SpaceEngineersApi.GenerateEntityId(IDType.ENTITY); } if (block is MyObjectBuilder_PistonBase) { ((MyObjectBuilder_PistonBase)newBlock).TopBlockId = ((MyObjectBuilder_PistonBase)block).TopBlockId == 0 ? 0 : SpaceEngineersApi.GenerateEntityId(IDType.ENTITY); } newBlock.BlockOrientation = MirrorCubeOrientation(block.SubtypeName, block.BlockOrientation, xMirror, yMirror, zMirror); var definition = SpaceEngineersApi.GetCubeDefinition(block.TypeId, viewModel.GridSize, block.SubtypeName); if (definition.Size.X == 1 && definition.Size.Y == 1 && definition.Size.z == 1) { newBlock.Min = block.Min.Mirror(xMirror, xAxis, yMirror, yAxis, zMirror, zAxis); } else { // resolve size of component, and transform to original orientation. var orientSize = definition.Size.Add(-1).Transform(block.BlockOrientation).Abs(); var min = block.Min.Mirror(xMirror, xAxis, yMirror, yAxis, zMirror, zAxis); var blockMax = new SerializableVector3I(block.Min.X + orientSize.X, block.Min.Y + orientSize.Y, block.Min.Z + orientSize.Z); var max = blockMax.Mirror(xMirror, xAxis, yMirror, yAxis, zMirror, zAxis); if (xMirror != Mirror.None) newBlock.Min = new SerializableVector3I(max.X, min.Y, min.Z); if (yMirror != Mirror.None) newBlock.Min = new SerializableVector3I(min.X, max.Y, min.Z); if (zMirror != Mirror.None) newBlock.Min = new SerializableVector3I(min.X, min.Y, max.Z); } // Don't place a block if one already exists there in the mirror. if (integrate && viewModel.CubeGrid.CubeBlocks.Any(b => b.Min.X == newBlock.Min.X && b.Min.Y == newBlock.Min.Y && b.Min.Z == newBlock.Min.Z /*|| b.Max == newBlock.Min*/)) // TODO: check cubeblock size. continue; blocks.Add(newBlock); } return blocks; }
public void TestConvert(StructureCubeGridModel viewModel) { // Trim Horse image. //viewModel.CubeGrid.CubeBlocks.RemoveAll(b => b.SubtypeName.EndsWith("White")); //foreach (var block in viewModel.CubeGrid.CubeBlocks) //{ // if (block.SubtypeName == SubtypeId.SmallBlockArmorBlock.ToString()) // { // block.SubtypeName = SubtypeId.SmallBlockArmorBlockRed.ToString(); // } //} //IsModified = true; //viewModel.CubeGrid.CubeBlocks.RemoveAll(b => b.SubtypeName == SubtypeId.SmallLight.ToString()); //var newBlocks = new List<MyObjectBuilder_CubeBlock>(); foreach (var block in viewModel.CubeGrid.CubeBlocks) { if (block.SubtypeName == SubtypeId.SmallBlockArmorBlock.ToString()) { //block.SubtypeName = SubtypeId.SmallBlockArmorBlockBlack.ToString(); //var light = block as MyObjectBuilder_ReflectorLight; //light.Intensity = 5; //light.Radius = 5; } //if (block.SubtypeName == SubtypeId.LargeBlockArmorBlockBlack.ToString()) //{ // for (var i = 0; i < 3; i++) // { // var newBlock = new MyObjectBuilder_CubeBlock() // { // SubtypeName = block.SubtypeName, // SubtypeId.LargeBlockArmorBlockWhite.ToString(), // EntityId = block.EntityId == 0 ? 0 : SpaceEngineersAPI.GenerateEntityId(), // PersistentFlags = block.PersistentFlags, // Min = new Vector3I(block.Min.X, block.Min.Y, block.Min.Z + 1 + i), // Max = new Vector3I(block.Max.X, block.Max.Y, block.Max.Z + 1 + i), // Orientation = Quaternion.CreateFromRotationMatrix(MatrixD.CreateLookAt(Vector3D.Zero, Vector3.Forward, Vector3.Up)) // }; // newBlocks.Add(newBlock); // } //} //if (block.SubtypeName == SubtypeId.LargeBlockArmorBlockWhite.ToString()) //{ // var newBlock = new MyObjectBuilder_CubeBlock() // { // SubtypeName = block.SubtypeName, // SubtypeId.LargeBlockArmorBlockWhite.ToString(), // EntityId = block.EntityId == 0 ? 0 : SpaceEngineersAPI.GenerateEntityId(), // PersistentFlags = block.PersistentFlags, // Min = new Vector3I(block.Min.X, block.Min.Y, block.Min.Z + 3), // Max = new Vector3I(block.Max.X, block.Max.Y, block.Max.Z + 3), // Orientation = Quaternion.CreateFromRotationMatrix(MatrixD.CreateLookAt(Vector3D.Zero, Vector3.Forward, Vector3.Up)) // }; // newBlocks.Add(newBlock); //} //if (block.Min.Z == 3 && block.Min.X % 2 == 1 && block.Min.Y % 2 == 1) //{ // var newBlock = new MyObjectBuilder_InteriorLight() // { // SubtypeName = SubtypeId.SmallLight.ToString(), // EntityId = SpaceEngineersAPI.GenerateEntityId(), // PersistentFlags = MyPersistentEntityFlags2.Enabled | MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene, // Min = new Vector3I(block.Min.X, block.Min.Y, 1), // Max = new Vector3I(block.Max.X, block.Max.Y, 1), // Orientation = new Quaternion(1, 0, 0, 0), // Radius = 3.6f, // Falloff = 1.3f, // Intensity = 1.5f, // PositionAndOrientation = new MyPositionAndOrientation() // { // Position = new Vector3D(), // //Position = new Vector3D(-7.5f, -10, 27.5f), // Forward = new Vector3(0,-1,0), // Up = new Vector3(1,0,0) // } // }; // newBlocks.Add(newBlock); //} } //viewModel.CubeGrid.CubeBlocks.AddRange(newBlocks); OptimizeModel(viewModel); }
public void TestDisplayRotation(StructureCubeGridModel viewModel) { //var corners = viewModel.CubeGrid.CubeBlocks.Where(b => b.SubtypeName.Contains("ArmorCorner")).ToList(); //var corners = viewModel.CubeGrid.CubeBlocks.OfType<MyObjectBuilder_CubeBlock>().ToArray(); var corners = viewModel.CubeGrid.CubeBlocks.Where(b => StructureCubeGridModel.TubeCurvedRotationBlocks.Contains(b.SubtypeName)).ToList(); foreach (var corner in corners) { Debug.WriteLine("{0}\t = \tAxis24_{1}_{2}", corner.SubtypeName, corner.BlockOrientation.Forward, corner.BlockOrientation.Up); } }
public void OptimizeModel(StructureCubeGridModel viewModel) { if (viewModel == null) return; // Optimise ordering of CubeBlocks within structure, so that loops can load quickly based on {X+, Y+, Z+}. var neworder = viewModel.CubeGrid.CubeBlocks.OrderBy(c => c.Min.Z).ThenBy(c => c.Min.Y).ThenBy(c => c.Min.X).ToList(); viewModel.CubeGrid.CubeBlocks = neworder; IsModified = true; }
/// <summary> /// Merges and copies blocks from ship2 into ship1. /// </summary> /// <param name="model1"></param> /// <param name="model2"></param> /// <returns></returns> internal bool MergeShipParts(StructureCubeGridModel model1, StructureCubeGridModel model2) { // find closest major axis for both parts. var q1 = Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir(model1.PositionAndOrientation.Value.Forward.RoundToAxis(), model1.PositionAndOrientation.Value.Up.RoundToAxis())); var q2 = Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir(model2.PositionAndOrientation.Value.Forward.RoundToAxis(), model2.PositionAndOrientation.Value.Up.RoundToAxis())); // Calculate the rotation between the two. var fixRotate = Quaternion.Inverse(q2) * q1; fixRotate.Normalize(); // Rotate the orientation of model2 to (closely) match model1. // It's Inverse, as the ship is actually rotated inverse in response to rotation of the cubes. model2.RotateCubes(Quaternion.Inverse(fixRotate)); // At this point ship2 has been reoriented around to closely match ship1. // The cubes in ship2 have be reoriended in reverse, so effectly there is no visual difference in ship2, except now all the cubes are aligned to the same X,Y,Z axis as ship1. // find two cubes, one from each ship that are closest to each other to use as the reference. var pos1 = (Vector3D)model1.PositionAndOrientation.Value.Position; var pos2 = (Vector3D)model2.PositionAndOrientation.Value.Position; var orient1 = model1.PositionAndOrientation.Value.ToQuaternion(); var orient2 = model2.PositionAndOrientation.Value.ToQuaternion(); var multi1 = model1.GridSize.ToLength(); var multi2 = model2.GridSize.ToLength(); var maxDistance = float.MaxValue; MyObjectBuilder_CubeBlock maxCube1 = null; MyObjectBuilder_CubeBlock maxCube2 = null; foreach (var cube1 in model1.CubeGrid.CubeBlocks) { var cPos1 = pos1 + Vector3.Transform(cube1.Min.ToVector3() * multi1, orient1); foreach (var cube2 in model2.CubeGrid.CubeBlocks) { var cPos2 = pos2 + Vector3.Transform(cube2.Min.ToVector3() * multi2, orient2); var d = Vector3.Distance(cPos1, cPos2); if (maxDistance > d) { maxDistance = d; maxCube1 = cube1; maxCube2 = cube2; } } } // Ignore ships that are too far away from one another. // A distance of 4 cubes to allow for large cubes, as we are only using the Min as position, not the entire size of a cube. if (maxDistance < (model1.GridSize.ToLength() * 5)) { // calculate offset for merging of closest cubes. var cPos1 = pos1 + Vector3.Transform(maxCube1.Min.ToVector3() * multi1, orient1); var cPos2 = pos2 + Vector3.Transform(maxCube2.Min.ToVector3() * multi2, orient2); var adjustedPos = Vector3.Transform(cPos2 - pos1, VRageMath.Quaternion.Inverse(orient1)) / multi1; var offset = adjustedPos.RoundToVector3I() - maxCube2.Min.ToVector3I(); // Merge cubes in. foreach (var cube2 in model2.CubeGrid.CubeBlocks) { var newcube = (MyObjectBuilder_CubeBlock)cube2.Clone(); newcube.Min = cube2.Min + offset; model1.CubeGrid.CubeBlocks.Add(newcube); } // Merge Groupings in. foreach (var group in model2.CubeGrid.BlockGroups) { var existingGroup = model1.CubeGrid.BlockGroups.FirstOrDefault(bg => bg.Name == group.Name); if (existingGroup == null) { existingGroup = new MyObjectBuilder_BlockGroup { Name = group.Name }; model1.CubeGrid.BlockGroups.Add(existingGroup); } foreach (var block in group.Blocks) { existingGroup.Blocks.Add(block + offset); } } // TODO: Merge Bones. //if (model2.CubeGrid.Skeleton != null) //{ // if (model1.CubeGrid.Skeleton == null) // model1.CubeGrid.Skeleton = new List<BoneInfo>(); // for (var i = model2.CubeGrid.Skeleton.Count - 1; i >= 0; i--) // //foreach (var bone in model2.CubeGrid.Skeleton) // { // var bone = model2.CubeGrid.Skeleton[i]; // model1.CubeGrid.Skeleton.Insert(0, new BoneInfo() // { // BonePosition = bone.BonePosition + offset, // BoneOffset = bone.BoneOffset // }); // } //} // TODO: Merge ConveyorLines // need to fix the rotation of ConveyorLines first. return true; } return false; }
/// <summary> /// Copy blocks from ship2 into ship1. /// </summary> /// <param name="model1"></param> /// <param name="model2"></param> internal void RejoinBrokenShip(StructureCubeGridModel model1, StructureCubeGridModel model2) { // Copy blocks from ship2 into ship1. model1.CubeGrid.CubeBlocks.AddRange(model2.CubeGrid.CubeBlocks); // Merge Groupings foreach (var group in model2.CubeGrid.BlockGroups) { var existingGroup = model1.CubeGrid.BlockGroups.FirstOrDefault(bg => bg.Name == group.Name); if (existingGroup == null) { model1.CubeGrid.BlockGroups.Add(group); } else { existingGroup.Blocks.AddRange(group.Blocks); } } // Merge ConveyorLines model1.CubeGrid.ConveyorLines.AddRange(model2.CubeGrid.ConveyorLines); }