SEToolbox.Models.StructureCubeGridModel.RotateCubes C# (CSharp) Method

RotateCubes() public method

public RotateCubes ( VRageMath quaternion ) : void
quaternion VRageMath
return void
        public void RotateCubes(VRageMath.Quaternion quaternion)
        {
            foreach (var cube in CubeGrid.CubeBlocks)
            {
                var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, CubeGrid.GridSizeEnum, cube.SubtypeName);

                if (definition.Size.X == 1 && definition.Size.Y == 1 && definition.Size.Z == 1)
                {
                    // rotate position around origin.
                    cube.Min = Vector3I.Transform(cube.Min.ToVector3I(), quaternion);
                }
                else
                {
                    // resolve size of component, and transform to original orientation.
                    var orientSize = definition.Size.Add(-1).Transform(cube.BlockOrientation).Abs();

                    var min = Vector3I.Transform(cube.Min.ToVector3I(), quaternion);
                    var blockMax = new Vector3I(cube.Min.X + orientSize.X, cube.Min.Y + orientSize.Y, cube.Min.Z + orientSize.Z);
                    var max = Vector3I.Transform(blockMax, quaternion);

                    cube.Min = new SerializableVector3I(Math.Min(min.X, max.X), Math.Min(min.Y, max.Y), Math.Min(min.Z, max.Z));
                }

                // rotate BlockOrientation.
                var q = quaternion * cube.BlockOrientation.ToQuaternion();
                q.Normalize();
                cube.BlockOrientation = new SerializableBlockOrientation(ref q);
            }

            // Rotate Groupings.
            foreach (var group in CubeGrid.BlockGroups)
            {
                for (var i = 0; i < group.Blocks.Count; i++)
                {
                    // The Group location is in the center of the cube.
                    // It doesn't have to be exact though, as it appears SE is just doing a location test of whatever object is at that location.
                    group.Blocks[i] = Vector3I.Transform(group.Blocks[i], quaternion);
                }
            }

            // TODO: Rotate Bones
            //if (CubeGrid.Skeleton != null)
            //{
            //    for (var i = 0; i < CubeGrid.Skeleton.Count; i++)
            //    {
            //        var bone = CubeGrid.Skeleton[i];
            //        bone.BonePosition = Vector3I.Transform(bone.BonePosition, quaternion);
            //        bone.BoneOffset = bone.BoneOffset.Transform(VRageMath.Quaternion.Inverse(quaternion));
            //    }
            //}

            // TODO: Rotate ConveyorLines
            foreach (var conveyorLine in CubeGrid.ConveyorLines)
            {
                //conveyorLine.StartPosition = Vector3I.Transform(conveyorLine.StartPosition, quaternion);
                //conveyorLine.StartDirection = 
                //conveyorLine.EndPosition = Vector3I.Transform(conveyorLine.EndPosition, quaternion);
                //conveyorLine.EndDirection = 
            }

            // Rotate the ship also to maintain the appearance that it has not changed.
            var o = CubeGrid.PositionAndOrientation.Value.ToQuaternion() * VRageMath.Quaternion.Inverse(quaternion);
            o.Normalize();
            var p = new MyPositionAndOrientation(o.ToMatrix());

            CubeGrid.PositionAndOrientation = new MyPositionAndOrientation
            {
                Position = CubeGrid.PositionAndOrientation.Value.Position,
                Forward = p.Forward,
                Up = p.Up
            };

            UpdateGeneralFromEntityBase();
        }

Usage Example

示例#1
0
        /// <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;
        }