public static (double Size, Vector3D Center) GetBound(IEnumerable <Vector3D> positions) { var minPos = positions.Aggregate(Vector3D.MaxValue, (s, n) => Vector3D.Min(s, n)); var maxPos = positions.Aggregate(Vector3D.MinValue, (s, n) => Vector3D.Max(s, n)); var size = Vector3D.Distance(minPos, maxPos); var center = (minPos + maxPos) / 2; return(size, center); }
private int GetDivideIndex(ref Vector3D translation) { Vector3I renderCellCoord; BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3D relativeTranslation = Vector3D.Max(translation - lodAabb.Min, Vector3D.Zero); MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lod, ref relativeTranslation, out renderCellCoord); return(GetDivideIndex(ref renderCellCoord)); }
public MyBBSetSampler(Vector3D min, Vector3D max) { Vector3D newMax = Vector3D.Max(min, max); Vector3D newMin = Vector3D.Min(min, max); m_bBox = new BoundingBoxD(newMin, newMax); m_sampler = new IntervalSampler(newMin.X, newMax.X, (newMax.Y - newMin.Y) * (newMax.Z - newMin.Z), Base6Directions.Axis.LeftRight); }
public static void CreateMerged(ref BoundingBoxD original, ref BoundingBoxD additional, out BoundingBoxD result) { Vector3D vectord; Vector3D vectord2; Vector3D.Min(ref original.Min, ref additional.Min, out vectord); Vector3D.Max(ref original.Max, ref additional.Max, out vectord2); result.Min = vectord; result.Max = vectord2; }
/// <summary> /// Creates the smallest BoundingBox that contains the two specified BoundingBox instances. /// </summary> /// <param name="original">One of the BoundingBox instances to contain.</param><param name="additional">One of the BoundingBox instances to contain.</param><param name="result">[OutAttribute] The created BoundingBox.</param> public static void CreateMerged(ref BoundingBoxD original, ref BoundingBoxD additional, out BoundingBoxD result) { Vector3D result1; Vector3D.Min(ref original.Min, ref additional.Min, out result1); Vector3D result2; Vector3D.Max(ref original.Max, ref additional.Max, out result2); result.Min = result1; result.Max = result2; }
public Vector3D MaxCoord() { Vector3D maxCoord = new Vector3D(double.MinValue, double.MinValue, double.MinValue); for (int i = 0, j = 0; i < vertexCount; i++, j += 3) { Vector3D v = new Vector3D(vertexPos, j); maxCoord = Vector3D.Max(maxCoord, v); } return(maxCoord); }
public void Vector3MaxTest() { Vector3D <float> a = new Vector3D <float>(-1.0f, 4.0f, -3.0f); Vector3D <float> b = new Vector3D <float>(2.0f, 1.0f, -1.0f); Vector3D <float> expected = new Vector3D <float>(2.0f, 4.0f, -1.0f); Vector3D <float> actual; actual = Vector3D.Max(a, b); Assert.True(MathHelper.Equal(expected, actual), "Vector3D<float>.Max did not return the expected value."); }
public static Vector3D MaxCoord(TriMesh mesh) { Vector3D maxCoord = new Vector3D(double.MinValue, double.MinValue, double.MinValue); for (int i = 0; i < mesh.Vertices.Count; i++) { Vector3D v = mesh.Vertices[i].Traits.Position; maxCoord = Vector3D.Max(maxCoord, v); } return(maxCoord); }
private bool TickThrusters(MotionState state, MotionTarget target) { Vector3D currentVelocity = state.VelocityLocal; Vector3D currentPosition = Vector3D.Transform(state.Position, state.WorldMatrixInverse); Vector3D currentGravity = state.GravityLocal; Vector3D targetSpeed = target.Speed; Vector3D targetPosition = Vector3D.Transform(target.Position ?? (state.Position + (targetSpeed + currentVelocity) * DELTA * .66), state.WorldMatrixInverse); Vector3D speedDifference = targetSpeed - currentVelocity; Vector3D positionDifference = targetPosition - currentPosition; if (speedDifference.LengthSquared() < velocityPrecision && positionDifference.LengthSquared() < positionPrecision) { ClearThrustersOverride(); SetDampeners(true); return(true); } Vector3D deceleration = GetAccelerations(speedDifference) + currentGravity; Vector3D decelerationTimes = speedDifference / deceleration; Vector3D positionAtFullStop = currentPosition + currentVelocity * decelerationTimes + deceleration * decelerationTimes * decelerationTimes / 2; Vector3D maxAccelerationDelta = targetPosition - positionAtFullStop; Vector3D shipAcceleration = GetAccelerations(maxAccelerationDelta); Vector3D acceleration = shipAcceleration + currentGravity; Vector3D accelerationForTick = (maxAccelerationDelta - currentVelocity * DELTA) / DELTA_SQ_2 - currentGravity; Vector3D overrides = Vector3D.Max(-Vector3D.One, Vector3D.Min(Vector3D.One, 0.5 * accelerationForTick / shipAcceleration)) * 100; if (maxAccelerationDelta.X < 0) { overrides.X = -overrides.X; } if (maxAccelerationDelta.Y < 0) { overrides.Y = -overrides.Y; } if (maxAccelerationDelta.Z < 0) { overrides.Z = -overrides.Z; } if (currentVelocity.LengthSquared() >= maxSpeed * maxSpeed && (overrides * currentVelocity).Min() >= -0.01) { ClearThrustersOverride(); return(false); } SetDampeners(decelerationTimes.Max() < DELTA); SetThrustersOverride(overrides); return(false); }
public override float GetVolume(ref Vector3D voxelPosition) { if (base.m_inverseIsDirty) { base.m_inverse = MatrixD.Invert(base.m_transformation); base.m_inverseIsDirty = false; } voxelPosition = Vector3D.Transform(voxelPosition, base.m_inverse); Vector3D vectord = Vector3D.Abs(voxelPosition) - this.Boundaries.HalfExtents; double num = Vector3D.Dot(voxelPosition, this.RampNormal) + this.RampNormalW; return(base.SignedDistanceToDensity((float)Math.Max(vectord.Max(), -num))); }
public override float GetVolume(ref Vector3D voxelPosition) { if (base.m_inverseIsDirty) { base.m_inverse = MatrixD.Invert(base.m_transformation); base.m_inverseIsDirty = false; } voxelPosition = Vector3D.Transform(voxelPosition, base.m_inverse); Vector3D center = this.Boundaries.Center; Vector3D vectord2 = Vector3D.Abs(voxelPosition - center) - (center - this.Boundaries.Min); return(base.SignedDistanceToDensity((float)vectord2.Max())); }
public static Vector3D Center(this IEnumerable <IMyCubeGrid> grids) { Vector3D min = Vector3D.MaxValue; Vector3D max = Vector3D.MinValue; foreach (var grid in grids) { min = Vector3D.Min(min, grid.WorldAABB.Min); max = Vector3D.Max(max, grid.WorldAABB.Max); } return((min + max) / 2.0); }
public static MatrixD AsMatrixD(this MyPositionAndOrientation posAndOrient) { var matrix = MatrixD.CreateWorld(posAndOrient.Position, posAndOrient.Forward, posAndOrient.Up); const float offset = 100.0f; if (MyAPIGatewayShortcuts.GetWorldBoundaries == null) { return(matrix); } var bound = MyAPIGatewayShortcuts.GetWorldBoundaries(); matrix.Translation = Vector3D.Min(Vector3D.Max(matrix.Translation, bound.Min + offset), bound.Max - offset); return(matrix); }
public static MyDefinitionId?VoxelMaterialAt(this MyVoxelBase voxel, Vector3D min, Vector3D grow, ref MyStorageData cache) { if (cache == null) { cache = new MyStorageData(); } var shape = new BoundingBoxD(Vector3D.Min(min, min + grow), Vector3D.Max(min, min + grow)); Vector3I voxMin; Vector3I voxMax; Vector3I voxCells; GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells); Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells); while (cellsItr.IsValid()) { Vector3I cellMinCorner; Vector3I cellMaxCorner; GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner); Vector3I rangeMin = cellMinCorner - 1; Vector3I rangeMax = cellMaxCorner + 1; voxel.Storage.ClampVoxelCoord(ref rangeMin); voxel.Storage.ClampVoxelCoord(ref rangeMax); cache.Resize(rangeMin, rangeMax); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, rangeMin, rangeMax); var mortonCode = -1; var maxMortonCode = cache.Size3D.Size; while (++mortonCode < maxMortonCode) { Vector3I pos; MyMortonCode3D.Decode(mortonCode, out pos); var content = cache.Content(ref pos); if (content <= MyVoxelConstants.VOXEL_CONTENT_EMPTY) { continue; } var material = cache.Material(ref pos); var def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); if (def != null) { return(def.Id); } } cellsItr.MoveNext(); } return(null); }
public Solve(List <Vector3D> _points, List <Thetra> _thetras, double[,] _coefficients, double[] _q, Func <double, double, double, double> _exact) { q = _q; points = _points; max = points[0]; min = points[0]; foreach (Vector3D item in points) { max = Vector3D.Max(item, max); min = Vector3D.Min(item, min); } thetras = _thetras; coefficients = _coefficients; exact = _exact; }
private bool TryGetDivideIndex(ref Vector3D translation, out int divideIndex) { divideIndex = 0; if (m_boundingBoxes.GetRoot() < 0) { return(false); } Vector3I renderCellCoord; BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3D relativeTranslation = Vector3D.Max(translation - lodAabb.Min, Vector3D.Zero); MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lod, ref relativeTranslation, out renderCellCoord); divideIndex = GetDivideIndex(ref renderCellCoord); return(true); }
/// <summary> /// Constructs a <see cref="SlimMath.BoundingBox"/> that fully contains the given points. /// </summary> /// <param name="points">The points that will be contained by the box.</param> /// <returns>The newly constructed bounding box.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="points"/> is <c>null</c>.</exception> public static BoundingBox FromPoints(Vector3D[] points) { if (points == null) { throw new ArgumentNullException("points"); } Vector3D min = new Vector3D(double.MaxValue); Vector3D max = new Vector3D(double.MinValue); for (int i = 0; i < points.Length; ++i) { Vector3D.Min(ref min, ref points[i], out min); Vector3D.Max(ref max, ref points[i], out max); } return(new BoundingBox(min, max)); }
public void Vector3MinMaxCodeCoverageTest() { Vector3D <float> min = Vector3D <float> .Zero; Vector3D <float> max = Vector3D <float> .One; Vector3D <float> actual; // Min. actual = Vector3D.Min(min, max); Assert.Equal(actual, min); actual = Vector3D.Min(max, min); Assert.Equal(actual, min); // Max. actual = Vector3D.Max(min, max); Assert.Equal(actual, max); actual = Vector3D.Max(max, min); Assert.Equal(actual, max); }
public void Vector3MinMaxCodeCoverageTest() { Vector3D min = Vector3D.Zero; Vector3D max = Vector3D.One; Vector3D actual; // Min. actual = Vector3D.Min(min, max); Assert.AreEqual(actual, min); actual = Vector3D.Min(max, min); Assert.AreEqual(actual, min); // Max. actual = Vector3D.Max(min, max); Assert.AreEqual(actual, max); actual = Vector3D.Max(max, min); Assert.AreEqual(actual, max); }
public void Draw() { MatrixD transfromMatrix = this.Origin.TransformMatrix; Vector3D min = Vector3D.One; Vector3D max = Vector3D.Zero; for (int i = 0; i < 8; i++) { Vector3D corner = World.MySector.MainCamera.WorldToScreen(ref m_corners[i]); min = Vector3D.Min(min, corner); max = Vector3D.Max(max, corner); } Vector3D distProj = max - min; // distance vec in screen coordinates (from 0 to 1, where 1 is screen width(for X) or height(for Y) float lineWidth = BBOX_BORDER_THICKNESS_MODIF / (float)MathHelper.Clamp(distProj.Length(), 0.01, 1); Color boxColor = RenderColor; BoundingBoxD box = new BoundingBoxD(-m_boundingBox.HalfExtent, m_boundingBox.HalfExtent); MySimpleObjectDraw.DrawTransparentBox(ref transfromMatrix, ref box, ref boxColor, MySimpleObjectRasterizer.SolidAndWireframe, 1, lineWidth, "Square", "Square"); if (Engine.Utils.MyFakes.ENABLE_DEBUG_DRAW_COORD_SYS) { //x for (int i = -10; i < 11; i++) { Vector3D v1 = this.Origin.Position + transfromMatrix.Forward * 20 + transfromMatrix.Right * (i * 2.5); Vector3D v2 = this.Origin.Position - transfromMatrix.Forward * 20 + transfromMatrix.Right * (i * 2.5); VRageRender.MyRenderProxy.DebugDrawLine3D(v1, v2, boxColor, boxColor, false); } //y for (int i = -10; i < 11; i++) { Vector3D v1 = this.Origin.Position + transfromMatrix.Right * 20 + transfromMatrix.Forward * (i * 2.5); Vector3D v2 = this.Origin.Position - transfromMatrix.Right * 20 + transfromMatrix.Forward * (i * 2.5); VRageRender.MyRenderProxy.DebugDrawLine3D(v1, v2, boxColor, boxColor, false); } } }
public void Draw() { MatrixD transfromMatrix = this.Origin.TransformMatrix; Vector3D min = Vector3D.One; Vector3D max = Vector3D.Zero; for (int i = 0; i < 8; i++) { Vector3D corner = World.MySector.MainCamera.WorldToScreen(ref m_corners[i]); min = Vector3D.Min(min, corner); max = Vector3D.Max(max, corner); } Vector3D distProj = max - min; // distance vec in screen coordinates (from 0 to 1, where 1 is screen width(for X) or height(for Y) float lineWidth = BBOX_BORDER_THICKNESS_MODIF / (float)MathHelper.Clamp(distProj.Length(), 0.01, 1); Color boxColor = RenderColor; BoundingBoxD box = new BoundingBoxD(-m_boundingBox.HalfExtent, m_boundingBox.HalfExtent); MySimpleObjectDraw.DrawTransparentBox(ref transfromMatrix, ref box, ref boxColor, MySimpleObjectRasterizer.SolidAndWireframe, 1, lineWidth, "Square", "Square"); }
internal void DebugDraw(Vector3I sectorPos, float sectorSize) { foreach (var part in m_instanceParts.Values) { foreach (var data in part.InstanceData) { var dist = (data.LocalMatrix.Translation - Sandbox.Game.World.MySector.MainCamera.Position).Length(); if (dist < 30) { MyRenderProxy.DebugDrawText3D(data.LocalMatrix.Translation, part.SubtypeId.ToString(), Color.Red, (float)(7.0 / dist), true); } } } BoundingBoxD bb = new BoundingBoxD(sectorPos * sectorSize, (sectorPos + Vector3I.One) * sectorSize); BoundingBoxD bb2 = new BoundingBoxD(m_AABB.Min, m_AABB.Max); bb2.Min = Vector3D.Max(bb2.Min, bb.Min); bb2.Max = Vector3D.Min(bb2.Max, bb.Max); MyRenderProxy.DebugDrawAABB(bb, Color.Orange, 1.0f, 1.0f, true); MyRenderProxy.DebugDrawAABB(bb2, Color.OrangeRed, 1.0f, 1.0f, true); }
public static BoundingBoxD CreateFromPoints(IEnumerable <Vector3D> points) { if (points == null) { throw new ArgumentNullException(); } bool flag = false; Vector3D vectord = new Vector3D(double.MaxValue); Vector3D vectord2 = new Vector3D(double.MinValue); foreach (Vector3D vectord3 in points) { Vector3D vectord4 = vectord3; Vector3D.Min(ref vectord, ref vectord4, out vectord); Vector3D.Max(ref vectord2, ref vectord4, out vectord2); flag = true; } if (!flag) { throw new ArgumentException(); } return(new BoundingBoxD(vectord, vectord2)); }
//double IntersectionLineAndSphere(Vector3D centerPoint, double radius, Vector3D lineOrigin, Vector3D lineDir) //{ // // https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection // Vector3D c = centerPoint; // double r = radius; // Vector3D o = lineOrigin; // Vector3D l = lineDir; // double sq1 = Math.Pow(Vector3D.Dot((o - c)*(o - c), l), 2); // double sq2 = l.LengthSquared() * ((o - c).LengthSquared() - r*r); // double sq = sq1 - sq2; // MyRenderProxy.Assert(sq >= 0, "the line needs to be crossing sphere! Some internal bug..."); // double d1 = Vector3D.Dot(l, o - c); // return -d1 + Math.Sqrt(sq); //} MatrixD CreateRigidLightMatrix(Vector3D[] verts, Vector3D lightDir, double zOffset) { // Create orthoghonal vectors: Vector3D lightUp = Math.Abs(Vector3.UnitX.Dot(lightDir)) < 0.99f ? Vector3.UnitX : Vector3.UnitY; Vector3D lightRight = Vector3.Cross(lightDir, lightUp); lightUp = Vector3D.Cross(lightRight, lightDir); lightUp.Normalize(); lightRight.Normalize(); // Look for the most compact encapsulation of verts: ... vMin and vMax will contain corners of encapsulation box with sides defined lightUp, lightRight,and lightDir var lightMatrix = MatrixD.CreateLookAt(new Vector3D(0, 0, 0), lightDir, lightUp); var invLightMatrix = MatrixD.Invert(lightMatrix); Vector3D.Transform(verts, ref lightMatrix, m_tmpCreateOrthoVertsLS); Vector3D vMinLS = m_tmpCreateOrthoVertsLS[0]; Vector3D vMaxLS = m_tmpCreateOrthoVertsLS[0]; for (uint i = 1; i < verts.Length; i++) { vMinLS = Vector3D.Min(vMinLS, m_tmpCreateOrthoVertsLS[i]); vMaxLS = Vector3D.Max(vMaxLS, m_tmpCreateOrthoVertsLS[i]); } Vector3D vMinWS = Vector3D.Transform(vMinLS, ref invLightMatrix); Vector3D vMaxWS = Vector3D.Transform(vMaxLS, ref invLightMatrix); // Create matrices: Vector3D vMinOffsetLS = -(vMaxLS - vMinLS) / 2; Vector3D vMaxOffsetLS = (vMaxLS - vMinLS) / 2; Vector3D vCenterWS = (vMaxWS + vMinWS) / 2; MatrixD matrixLightPlacer = MatrixD.CreateLookAt(vCenterWS, vCenterWS - lightDir, lightUp); MatrixD matrixLightSizer = MatrixD.CreateOrthographicOffCenter(vMinOffsetLS.X, vMaxOffsetLS.X, vMinOffsetLS.Y, vMaxOffsetLS.Y, vMaxOffsetLS.Z + zOffset, vMinOffsetLS.Z); return(matrixLightPlacer * matrixLightSizer); }
/// <summary> /// <para>Grows the Bounds to include the point.</para> /// </summary> /// <param name="point"></param> public void Encapsulate(Vector3D point) { this.SetMinMax(Vector3D.Min(this.min, point), Vector3D.Max(this.max, point)); }
public MyObjectBuilder_EntityBase BuildEntity() { // Realign both asteroids to a common grid, so voxels can be lined up. Vector3I roundedPosLeft = SelectionLeft.WorldAABB.Min.RoundToVector3I(); Vector3D offsetPosLeft = SelectionLeft.WorldAABB.Min - (Vector3D)roundedPosLeft; // Use for everything. Vector3I roundedPosRight = (SelectionRight.WorldAABB.Min - offsetPosLeft).RoundToVector3I(); Vector3D offsetPosRight = SelectionRight.WorldAABB.Min - (Vector3D)roundedPosRight; // Use for everything. // calculate smallest allowable size for contents of both. const int paddCells = 3; // Force a calculation of the ContentBounds, as multi select in the ListView doesn't necessarily make it happen, or make it happen fast enough. SelectionLeft.LoadDetailsSync(); SelectionRight.LoadDetailsSync(); var minLeft = SelectionLeft.WorldAABB.Min + SelectionLeft.InflatedContentBounds.Min - offsetPosLeft; var minRight = SelectionRight.WorldAABB.Min + SelectionRight.InflatedContentBounds.Min - offsetPosRight; var min = Vector3D.Zero; var posOffset = Vector3D.Zero; var asteroidSize = Vector3I.Zero; switch (VoxelMergeType) { case VoxelMergeType.UnionVolumeLeftToRight: case VoxelMergeType.UnionVolumeRightToLeft: min = Vector3D.Min(minLeft, minRight) - paddCells; var max = Vector3D.Max(SelectionLeft.WorldAABB.Min + SelectionLeft.InflatedContentBounds.Max - offsetPosLeft, SelectionRight.WorldAABB.Min + SelectionRight.InflatedContentBounds.Max - offsetPosRight) + paddCells; posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z); var size = (max - min).RoundToVector3I(); asteroidSize = MyVoxelBuilder.CalcRequiredSize(size); break; case VoxelMergeType.UnionMaterialLeftToRight: min = SelectionRight.WorldAABB.Min - offsetPosRight; posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z); asteroidSize = SelectionRight.Size; break; case VoxelMergeType.UnionMaterialRightToLeft: min = SelectionLeft.WorldAABB.Min - offsetPosLeft; posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z); asteroidSize = SelectionLeft.Size; break; case VoxelMergeType.SubtractVolumeLeftFromRight: min = SelectionRight.WorldAABB.Min - offsetPosRight; posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z); asteroidSize = SelectionRight.Size; break; case VoxelMergeType.SubtractVolumeRightFromLeft: min = SelectionLeft.WorldAABB.Min - offsetPosLeft; posOffset = new Vector3D(minLeft.X < minRight.X ? offsetPosLeft.X : offsetPosRight.X, minLeft.Y < minRight.Y ? offsetPosLeft.Y : offsetPosRight.Y, minLeft.Z < minRight.Z ? offsetPosLeft.Z : offsetPosRight.Z); asteroidSize = SelectionLeft.Size; break; } // Prepare new asteroid. var newAsteroid = new MyVoxelMap(); newAsteroid.Create(asteroidSize, SpaceEngineersCore.Resources.GetDefaultMaterialIndex()); if (string.IsNullOrEmpty(MergeFileName)) { MergeFileName = "merge"; } var filename = MainViewModel.CreateUniqueVoxelStorageName(MergeFileName); // merge. switch (VoxelMergeType) { case VoxelMergeType.UnionVolumeLeftToRight: MergeAsteroidVolumeInto(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft); break; case VoxelMergeType.UnionVolumeRightToLeft: MergeAsteroidVolumeInto(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight); break; case VoxelMergeType.UnionMaterialLeftToRight: MergeAsteroidMaterialFrom(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft); break; case VoxelMergeType.UnionMaterialRightToLeft: MergeAsteroidMaterialFrom(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight); break; case VoxelMergeType.SubtractVolumeLeftFromRight: SubtractAsteroidVolumeFrom(ref newAsteroid, min, SelectionRight, SelectionLeft, minRight, minLeft); break; case VoxelMergeType.SubtractVolumeRightFromLeft: SubtractAsteroidVolumeFrom(ref newAsteroid, min, SelectionLeft, SelectionRight, minLeft, minRight); break; } // Generate Entity var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); newAsteroid.Save(tempfilename); SourceFile = tempfilename; var position = min + posOffset; var entity = new MyObjectBuilder_VoxelMap(position, filename) { EntityId = SpaceEngineersApi.GenerateEntityId(IDType.ASTEROID), PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene, StorageName = Path.GetFileNameWithoutExtension(filename), PositionAndOrientation = new MyPositionAndOrientation { Position = position, Forward = Vector3.Forward, Up = Vector3.Up } }; return(entity); }
public OrientedBoundingBoxFaces(IMyTerminalBlock block) { Corners = new Vector3D[8]; if (block == null) { Position = new Vector3D(); localMin = new Vector3D(); localMax = new Vector3D(); return; } // Reconstruct bounding box vectors in world dimensions // For a 1x1x1 cube where Min = Max we still have the 1x1x1 cube as bounding box, // hence half that gets added in each direction. // var localMin = new Vector3D(block.CubeGrid.Min) - new Vector3D(0.5, 0.5, 0.5); localMin = new Vector3D(block.CubeGrid.Min) - new Vector3D(0.5, 0.5, 0.5); localMin *= block.CubeGrid.GridSize; // var localMax = new Vector3D(block.CubeGrid.Max) + new Vector3D(0.5, 0.5, 0.5); localMax = new Vector3D(block.CubeGrid.Max) + new Vector3D(0.5, 0.5, 0.5); localMax *= block.CubeGrid.GridSize; // The reference-blocks orientation. var blockOrient = block.WorldMatrix.GetOrientation(); // Get the matrix that transforms from the cube grids orientation to the blocks orientation. var matrix = block.CubeGrid.WorldMatrix.GetOrientation() * MatrixD.Transpose(blockOrient); // Transform the cubegrid-relative min/max to block-relative min/max. Vector3D.TransformNormal(ref localMin, ref matrix, out localMin); Vector3D.TransformNormal(ref localMax, ref matrix, out localMax); // Form clean min/max again. var tmpMin = Vector3D.Min(localMin, localMax); localMax = Vector3D.Max(localMin, localMax); localMin = tmpMin; // Get the center for the offset correction into worldspace. var center = block.CubeGrid.GetPosition(); Vector3D tmp2; Vector3D tmp3; tmp2 = localMin; Vector3D.TransformNormal(ref tmp2, ref blockOrient, out tmp2); tmp2 += center; tmp3 = localMax; Vector3D.TransformNormal(ref tmp3, ref blockOrient, out tmp3); tmp3 += center; BoundingBox bb = new BoundingBox(tmp2, tmp3); Position = bb.Center; // Iterate over all edges and get them into world space. Vector3D tmp; for (int i = 0; i < 8; i++) { tmp.X = ((i & 1) == 0 ? localMin : localMax).X; tmp.Y = ((i & 2) == 0 ? localMin : localMax).Y; tmp.Z = ((i & 4) == 0 ? localMin : localMax).Z; Vector3D.TransformNormal(ref tmp, ref blockOrient, out tmp); tmp += center; Corners[i] = tmp; } }
/// <summary> /// Performes a physics raycast /// It can be recursive (it calls CastDDA when it hits a grid). /// </summary> /// <param name="fromWorldPos"></param> /// <returns>Returns starting damage for current stack</returns> private MyRaycastDamageInfo CastPhysicsRay(Vector3D fromWorldPos) { Vector3D pos = Vector3D.Zero; IMyEntity hitEntity = null; var hitInfo = MyPhysics.CastRay(fromWorldPos, m_explosion.Center, MyPhysics.CollisionLayers.ExplosionRaycastLayer); if (hitInfo.HasValue) { hitEntity = (hitInfo.Value.HkHitInfo.Body.UserObject != null) ? ((MyPhysicsBody)hitInfo.Value.HkHitInfo.Body.UserObject).Entity : null; pos = hitInfo.Value.Position; } Vector3D direction = (m_explosion.Center - fromWorldPos); float lengthToCenter = (float)direction.Normalize(); var grid = (hitEntity as MyCubeGrid); if (grid == null) { MyCubeBlock hitBlock = hitEntity as MyCubeBlock; if (hitBlock != null) { grid = hitBlock.CubeGrid; } } if (grid != null) { var localPos = Vector3D.Transform(pos, grid.PositionComp.WorldMatrixNormalizedInv) * grid.GridSizeR; var localDir = Vector3D.TransformNormal(direction, grid.PositionComp.WorldMatrixNormalizedInv) * 1 / 8f; //Try advancing the point to find the intersected block //If the block is a cube, this is necessary because the raycast will return a point somewhere outside the cube //If the block is not a full cube (slope, special block), the raycast can return inside the cube //It advances 4 times, each time one 8th the grid size for (int i = 0; i < 5; i++) { Vector3I gridPos = Vector3I.Round(localPos); var cubeBlock = grid.GetCubeBlock(gridPos); if (cubeBlock != null) { if (m_castBlocks.Contains(cubeBlock)) { //This shouldn't happen //There is a corner case where the explosion position is inside the empty cell, but this should be handleded somewhere higher System.Diagnostics.Debug.Fail("Raycast failed!"); DrawRay(fromWorldPos, pos, Color.Red); return(new MyRaycastDamageInfo(0f, lengthToCenter)); } else { //if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS) // DrawRay(fromWorldPos, pos, Color.Blue); return(CastDDA(cubeBlock)); } } localPos += localDir; } pos = Vector3D.Transform(localPos * grid.GridSize, grid.WorldMatrix); //We hit a grid but were unable to find the hit cube. Send another raycast //Ideally, we would want to get the cube in all cases, but it also has to be fast //We need to check if the explosion center is between the initial start position (fromWorldPos) and the new one (pos) Vector3D min = Vector3D.Min(fromWorldPos, pos); Vector3D max = Vector3D.Max(fromWorldPos, pos); BoundingBoxD boundingBox = new BoundingBoxD(min, max); if (boundingBox.Contains(m_explosion.Center) == ContainmentType.Contains) { return(new MyRaycastDamageInfo(m_explosionDamage, lengthToCenter)); } stackOverflowGuard++; if (stackOverflowGuard > MAX_PHYSICS_RECURSION_COUNT) { System.Diagnostics.Debug.Fail("Potential stack overflow!"); if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS) { DrawRay(fromWorldPos, pos, Color.Red); } return(new MyRaycastDamageInfo(0f, lengthToCenter)); } else { if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS) { DrawRay(fromWorldPos, pos, Color.White); } return(CastPhysicsRay(pos)); } } else if (hitInfo.HasValue) { //Something was hit, but it wasn't a grid. This needs to be handled somehow if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS) { DrawRay(fromWorldPos, pos, Color.Violet); } return(new MyRaycastDamageInfo(0, lengthToCenter)); } //Nothing was hit, so we can assume the there was nothing blocking the explosion //if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS) // DrawRay(fromWorldPos, pos, Color.Salmon); return(new MyRaycastDamageInfo(m_explosionDamage, lengthToCenter)); }
public BoundingBoxD GetBoundingBox() => new BoundingBoxD(Vector3D.Min(this.From, this.To), Vector3D.Max(this.From, this.To));
public BoundingBoxD Include(ref BoundingBoxD box) { this.Min = Vector3D.Min(this.Min, box.Min); this.Max = Vector3D.Max(this.Max, box.Max); return(this); }