private HkdBreakableShape AddMountForShape(HkdBreakableShape shape, Matrix transform, ref BoundingBox blockBB) { Vector4 min; Vector4 max; shape.GetShape().GetLocalAABB(0.01f, out min, out max);//.Transform(CubeGrid.PositionComp.WorldMatrix); var bb = new BoundingBox(new Vector3(min), new Vector3(max)); bb = bb.Transform(transform); bb.Min /= CubeGrid.GridSize; //normalize for mount point bb.Max /= CubeGrid.GridSize; bb.Inflate(0.04f);//add tolerance (fracture shapes are smaller than block) bb.Min += blockBB.HalfExtents; bb.Max += blockBB.HalfExtents; if (blockBB.Contains(bb) == ContainmentType.Intersects) { bb.Inflate(-0.04f); foreach (var directionEnum in Base6Directions.EnumDirections) { int dirEnum = (int)directionEnum; Vector3 direction = Base6Directions.Directions[dirEnum]; Vector3 absDir = Vector3.Abs(direction); var mp = new MyCubeBlockDefinition.MountPoint(); mp.Start = bb.Min; mp.End = bb.Max; var start = mp.Start * absDir / (blockBB.HalfExtents * 2) - absDir * 0.04f; var end = mp.End * absDir / (blockBB.HalfExtents * 2) + absDir * 0.04f; bool add = false; bool one = false; if (start.Max() < 1 && end.Max() > 1 && direction.Max() > 0) { add = true; one = true; } else if (start.Min() < 0 && end.Max() > 0 && direction.Min() < 0) { add = true; } if (!add) { continue; } mp.Start -= mp.Start * absDir - absDir * 0.04f; mp.End -= mp.End * absDir + absDir * 0.04f; if (one) { mp.Start += absDir * blockBB.HalfExtents * 2; mp.End += absDir * blockBB.HalfExtents * 2; } mp.Start -= blockBB.HalfExtents - Vector3.One / 2; mp.End -= blockBB.HalfExtents - Vector3.One / 2; mp.Normal = new Vector3I(direction); MountPoints.Add(mp); } } return shape; }
/// <summary> /// Fills passed lists with mount point data, which is transformed using orientation /// of the block. /// </summary> /// <param name="outMountPoints">Output buffer.</param> /// <param name="performCorrection">True when you want to have correction performed for when rotation of fractional values would have different result than integers.</param> public static void TransformMountPoints(List<MyCubeBlockDefinition.MountPoint> outMountPoints, MyCubeBlockDefinition def, MyCubeBlockDefinition.MountPoint[] mountPoints, ref MyBlockOrientation orientation) { Debug.Assert(outMountPoints != null); outMountPoints.Clear(); if (mountPoints == null) return; Matrix rotation; orientation.GetMatrix(out rotation); var center = def.Center; for (int i = 0; i < mountPoints.Length; ++i) { var mountPoint = mountPoints[i]; var mp = new MyCubeBlockDefinition.MountPoint(); var centeredStart = mountPoint.Start - center; var centeredEnd = mountPoint.End - center; Vector3I.Transform(ref mountPoint.Normal, ref rotation, out mp.Normal); Vector3.Transform(ref centeredStart, ref rotation, out mp.Start); Vector3.Transform(ref centeredEnd, ref rotation, out mp.End); mp.ExclusionMask = mountPoint.ExclusionMask; mp.PropertiesMask = mountPoint.PropertiesMask; mp.Enabled = mountPoint.Enabled; // Correction of situations when 0.5 would get transformed to -0.5, resulting in different floor() (integer 0 is transformed to 0). var startICorrect = Vector3I.Floor(mountPoint.Start) - center; var endICorrect = Vector3I.Floor(mountPoint.End) - center; Vector3I.Transform(ref startICorrect, ref rotation, out startICorrect); Vector3I.Transform(ref endICorrect, ref rotation, out endICorrect); var startI = Vector3I.Floor(mp.Start); var endI = Vector3I.Floor(mp.End); var startCorrection = startICorrect - startI; var endCorrection = endICorrect - endI; mp.Start += startCorrection; mp.End += endCorrection; outMountPoints.Add(mp); } }
static bool FindMountPoint(HkShapeCutterUtil cutter, HkShape shape, Vector3 direction, float gridSize, List<Sandbox.Definitions.MyCubeBlockDefinition.MountPoint> mountPoints) { //VRageRender.MyRenderProxy.DebugDrawLine3D(drawMatrix.Translation, Vector3D.Transform(direction, drawMatrix), Color.Green, Color.Green, false); //float offset = (gridSize * 0.9f) / 2.0f; float offset = (gridSize * 0.75f) / 2.0f; //because fracture pieces can be bit inside the cube Plane plane = new Plane(-direction, offset); float minimumSize = 0.2f; Vector3 min, max; if (cutter.Cut(shape, new Vector4(plane.Normal.X, plane.Normal.Y, plane.Normal.Z, plane.D), out min, out max)) { var aabb = new BoundingBox(min, max); aabb.InflateToMinimum(new Vector3(minimumSize)); float centerOffset = gridSize * 0.5f; // VRageRender.MyRenderProxy.DebugDrawOBB(boxC, Color.Red, 0.02f, true, false); MyCubeBlockDefinition.MountPoint mountPoint = new MyCubeBlockDefinition.MountPoint(); mountPoint.Normal = new Vector3I(direction); mountPoint.Start = (aabb.Min + new Vector3(centerOffset)) / gridSize; mountPoint.End = (aabb.Max + new Vector3(centerOffset)) / gridSize; mountPoint.Enabled = true; //because it didnt work if shape wasnt realy near the edge var zExt = Vector3.Abs(direction) * mountPoint.Start; bool add = zExt.AbsMax() > 0.5f; mountPoint.Start -= zExt; mountPoint.Start -= direction * 0.04f; mountPoint.End -= Vector3.Abs(direction) * mountPoint.End; mountPoint.End += direction * 0.04f; if (add) { mountPoint.Start += Vector3.Abs(direction); mountPoint.End += Vector3.Abs(direction); } mountPoints.Add(mountPoint); return true; } return false; }